From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for battery temperature monitor driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com --- .../bindings/power_supply/ab8500/btemp.txt | 54 ++ arch/arm/boot/dts/db8500.dtsi | 17 + arch/arm/mach-ux500/Makefile | 4 +- arch/arm/mach-ux500/board-mop500-bm.c | 532 ++++++++++++++++++++ arch/arm/mach-ux500/include/mach/board-mop500-bm.h | 24 + drivers/mfd/ab8500-core.c | 1 + drivers/power/Kconfig | 8 +- drivers/power/ab8500_btemp.c | 79 ++- include/linux/mfd/ab8500/pwmleds.h | 20 + 9 files changed, 722 insertions(+), 17 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt create mode 100644 arch/arm/mach-ux500/board-mop500-bm.c create mode 100644 arch/arm/mach-ux500/include/mach/board-mop500-bm.h create mode 100644 include/linux/mfd/ab8500/pwmleds.h
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt new file mode 100644 index 0000000..8543ed1 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt @@ -0,0 +1,54 @@ +AB8500 Battery Termperature Monitor Driver + +AB8500 is a mixed signal multimedia and power management +device comprising: power and energy management module, +WalliCharger and USB charger interface, audio, general +purpose ADC TVOut, clock management and SIM card Interface. + +Battery temperature monitoring support is part of 'energy +management module', the other components of this module +are: 'main and USB Combo charger' and fuel guage. + +The properties below describes the node for battery +temperature monitor driver. + +Required Properties: +- compatible = "stericsson,ab8500-btemp" + +interrupts: + Four battery temperature ranges are be defined + which results in interrupt events as: + - Btemp + - BtempLow + - BtempMedium + - BtempHigh + + +Supplied-to: + This shall be power supply class dependency where in the runtime battery + properties will be shared across fuel guage and charging algorithm driver. + +Thermister-interface: + 'btemp' and 'batctrl' are the pins interfaced for battery temperature + measurement, btemp is used when NTC(Negative Termperature coefficient) + resister is interfaced external to battery and batctrl is used when + NTC resister is internal to battery. + +example: +ab8500-btemp { + compatible = "stericsson,ab8500-btemp"; + + interrupt-names = + "BAT_CTRL_INDB", /* battery removal indicator */ + "BTEMP_LOW", /* Btemp < BtempLow, if battery temperature is lower than -10°C */ + "BTEMP_HIGH", /* BtempLow < Btemp < BtempMedium, + if battery temperature is between -10 and 0°C */ + "BTEMP_LOW_MEDIUM", /* BtempMedium < Btemp < BtempHigh, + if battery temperature is between 0°C and “MaxTemp”.*/ + "BTEMP_MEDIUM_HIGH";/* Btemp > BtempHigh, + if battery temperature is higher than “MaxTemp”. */ + + supplied-to = "ab8500_chargalg", "ab8500_fg"; + + thermister-internal-to-battery = <1>; +}; diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index 7279165..527fdc3 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -330,6 +330,23 @@ vddadc-supply = <&ab8500_ldo_tvout_reg>; };
+ ab8500-btemp { + compatible = "stericsson,ab8500-btemp"; + interrupts = <20 0x04 + 80 0x04 + 81 0x04 + 82 0x04 + 83 0x04>; + interrupt-names = "BAT_CTRL_INDB", + "BTEMP_LOW", + "BTEMP_HIGH", + "BTEMP_LOW_MEDIUM", + "BTEMP_MEDIUM_HIGH"; + supplied_to = "ab8500_chargalg", "ab8500_fg"; + num_supplicants = <2>; + battery_term_on_batctrl = <1>; + }; + ab8500-usb { compatible = "stericsson,ab8500-usb"; interrupts = < 90 0x4 diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 026086f..b474917 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -12,6 +12,8 @@ obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ board-mop500-uib.o board-mop500-stuib.o \ board-mop500-u8500uib.o \ board-mop500-pins.o \ - board-mop500-msp.o + board-mop500-msp.o \ + board-mop500-bm.o + obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c new file mode 100644 index 0000000..3349ceb --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -0,0 +1,532 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U8500 board specific charger and battery initialization parameters. + * + * Author: Johan Palsson johan.palsson@stericsson.com for ST-Ericsson. + * Author: Johan Gardsmark johan.gardsmark@stericsson.com for ST-Ericsson. + * + */ + +#include <linux/power_supply.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500-bm.h> +#include <linux/mfd/ab8500/pwmleds.h> +#include <mach/board-mop500-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_thermister[] = { + {-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_thermister[] = { + {-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_thermister[] = { + {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_thermister[] = { + {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. + */ +static struct batres_vs_temp temp_to_batres_tbl_thermister[] = { + { 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. + */ +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY +#define BATRES 180 +#else +#define BATRES 300 +#endif +static struct batres_vs_temp temp_to_batres_tbl[] = { + { 60, BATRES}, + { 30, BATRES}, + { 20, BATRES}, + { 10, BATRES}, + { 00, BATRES}, + {-10, BATRES}, + {-20, BATRES}, +}; + +static const struct abx500_battery_type bat_type_thermister[] = { +[BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .charge_full_design = 2600, +#else + .charge_full_design = 612, +#endif + .nominal_voltage = 3700, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .termination_vol = 4150, +#else + .termination_vol = 4050, +#endif + .termination_curr = 200, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .recharge_vol = 4130, + .normal_cur_lvl = 520, + .normal_vol_lvl = 4200, +#else + .recharge_vol = 3990, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, +#endif + .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), + .batres_tbl = temp_to_batres_tbl, +}, +{ + .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_thermister), + .r_to_t_tbl = temp_tbl_A_thermister, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermister), + .v_to_cap_tbl = cap_tbl_A_thermister, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermister), + .batres_tbl = temp_to_batres_tbl_thermister, + +}, +{ + .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_thermister), + .r_to_t_tbl = temp_tbl_B_thermister, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermister), + .v_to_cap_tbl = cap_tbl_B_thermister, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermister), + .batres_tbl = temp_to_batres_tbl_thermister, +}, +}; + +struct abx500_battery_type bat_type_ext_thermister[] = { +[BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .charge_full_design = 2600, +#else + .charge_full_design = 612, +#endif + .nominal_voltage = 3700, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .termination_vol = 4150, +#else + .termination_vol = 4050, +#endif + .termination_curr = 200, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .recharge_vol = 4130, + .normal_cur_lvl = 520, + .normal_vol_lvl = 4200, +#else + .recharge_vol = 3990, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, +#endif + .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), + .batres_tbl = temp_to_batres_tbl, +}, +/* + * 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), + .batres_tbl = temp_to_batres_tbl, +}, +{ + .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), + .batres_tbl = temp_to_batres_tbl, +}, +{ + .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), + .batres_tbl = temp_to_batres_tbl, +}, +}; + +static char *ab8500_charger_supplied_to[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + +static char *ab8500_chargalg_supplied_to[] = { + "ab8500_fg", +}; + +struct abx500_charger_platform_data ab8500_charger_plat_data = { + .supplied_to = ab8500_charger_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_charger_supplied_to), + .autopower_cfg = false, +}; + +struct abx500_chargalg_platform_data ab8500_chargalg_plat_data = { + .supplied_to = ab8500_chargalg_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_chargalg_supplied_to), +}; + +static struct ab8500_led_pwm leds_pwm_data[] = { + [0] = { + .pwm_id = 1, + .blink_en = 1, + }, + [1] = { + .pwm_id = 2, + .blink_en = 0, + }, + [2] = { + .pwm_id = 3, + .blink_en = 0, + }, +}; + +struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data = { + .num_pwm = 3, + .leds = leds_pwm_data, +}; + +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, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .no_maintenance = true, +#else + .no_maintenance = false, +#endif + .adc_therm = ABx500_ADC_THERM_BATCTRL, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .chg_unknown_bat = true, +#else + .chg_unknown_bat = false, +#endif + .enable_overshoot = false, + .fg_res = 100, + .cap_levels = &cap_levels, + .bat_type = bat_type_thermister, + .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, +}; diff --git a/arch/arm/mach-ux500/include/mach/board-mop500-bm.h b/arch/arm/mach-ux500/include/mach/board-mop500-bm.h new file mode 100644 index 0000000..11c7384 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/board-mop500-bm.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U8500 board specific charger and battery initialization parameters. + * + * Author: Johan Palsson johan.palsson@stericsson.com for ST-Ericsson. + * Author: Johan Gardsmark johan.gardsmark@stericsson.com for ST-Ericsson. + * + */ + +#ifndef __BOARD_MOP500_BM_H +#define __BOARD_MOP500_BM_H + +#include <linux/mfd/abx500/ab8500-bm.h> + +extern struct abx500_charger_platform_data ab8500_charger_plat_data; +extern struct abx500_chargalg_platform_data ab8500_chargalg_plat_data; +extern struct abx500_bm_data ab8500_bm_data; +extern struct abx500_battery_type bat_type_ext_thermister[]; +extern struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data; + +#endif diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 738b9c5..402f630 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1046,6 +1046,7 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = { }, { .name = "ab8500-btemp", + .of_compatible = "stericsson,ab8500-btemp", .num_resources = ARRAY_SIZE(ab8500_btemp_resources), .resources = ab8500_btemp_resources, }, diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index e3a3b49..00dec0f 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -303,10 +303,10 @@ config AB8500_BM help Say Y to include support for AB5500 battery management.
-config AB8500_BATTERY_THERM_ON_BATCTRL - bool "Thermistor connected on BATCTRL ADC" +config AB8500_9100_LI_ION_BATTERY + bool "Enable support of the 9100 Li-ion battery charging" depends on AB8500_BM help - Say Y to enable battery temperature measurements using - thermistor connected on BATCTRL ADC. + Say Y to enable support of the 9100 Li-ion battery charging. + endif # POWER_SUPPLY diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index bba3cca..1272bba 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -16,6 +16,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/completion.h> @@ -25,6 +26,7 @@ #include <linux/mfd/abx500/ab8500-bm.h> #include <linux/mfd/abx500/ab8500-gpadc.h> #include <linux/jiffies.h> +#include <mach/board-mop500-bm.h>
#define VTVOUT_V 1800
@@ -964,11 +966,13 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) { int irq, i, ret = 0; u8 val; - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; struct ab8500_btemp *di; + u32 pval; + const char *sup_val;
- if (!plat_data) { - dev_err(&pdev->dev, "No platform data\n"); + if (!np) { + dev_err(&pdev->dev, "No DT node for btemp found\n"); return -EINVAL; }
@@ -981,21 +985,64 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->parent = dev_get_drvdata(pdev->dev.parent); di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- /* get btemp specific platform data */ - di->pdata = plat_data->btemp; - if (!di->pdata) { - dev_err(di->dev, "no btemp platform data supplied\n"); + di->pdata = + kzalloc(sizeof(struct abx500_btemp_platform_data), GFP_KERNEL); + if (di->pdata == NULL) { + ret = -ENOMEM; + goto free_device_info; + } + /* get battery specific platform data */ + ret = of_property_read_u32(np, "num_supplicants", &pval); + if (ret) { + dev_err(di->dev, "missing property num_supplicants\n"); + kfree(di->pdata); + ret = -EINVAL; + goto free_device_info; + } + di->pdata->num_supplicants = pval; + di->pdata->supplied_to = + kzalloc(di->pdata->num_supplicants * + sizeof(const char *), GFP_KERNEL); + if (di->pdata->supplied_to == NULL) { + kfree(di->pdata); ret = -EINVAL; goto free_device_info; }
- /* get battery specific platform data */ - di->bat = plat_data->battery; + for (val = 0; val < di->pdata->num_supplicants; ++val) + if (of_property_read_string_index + (np, "supplied_to", val, &sup_val) == 0) + *(di->pdata->supplied_to + val) = (char *)sup_val; + else { + dev_err(di->dev, "insufficient number of supplied_to data found\n"); + kfree(di->pdata); + kfree(di->pdata->supplied_to); + ret = -EINVAL; + goto free_device_info; + } + + di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL); if (!di->bat) { - dev_err(di->dev, "no battery platform data supplied\n"); - ret = -EINVAL; + kfree(di->pdata->supplied_to); + kfree(di->pdata); + ret = -ENOMEM; goto free_device_info; } + dev_dbg(di->dev, "getting battery information\n"); + di->bat = &ab8500_bm_data; + ret = of_property_read_u32(np, "battery_term_on_batctrl", &pval); + if (ret) { + dev_err(di->dev, "missing property battery_term_on_batctrl\n"); + kfree(di->pdata->supplied_to); + kfree(di->pdata); + kfree(di->bat); + ret = -ENOMEM; + goto free_device_info; + } + if (pval == 0) { + di->bat->bat_type = bat_type_ext_thermister; + di->bat->adc_therm = ABx500_ADC_THERM_BATTEMP; + }
/* BTEMP supply */ di->btemp_psy.name = "ab8500_btemp"; @@ -1008,7 +1055,6 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->btemp_psy.external_power_changed = ab8500_btemp_external_power_changed;
- /* Create a work queue for the btemp */ di->btemp_wq = create_singlethread_workqueue("ab8500_btemp_wq"); @@ -1090,14 +1136,22 @@ free_irq: irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); free_irq(irq, di); } + free_btemp_wq: destroy_workqueue(di->btemp_wq); + free_device_info: kfree(di);
return ret; }
+static const struct of_device_id ab8500_btemp_match[] = { + {.compatible = "stericsson,ab8500-btemp",}, + {}, +}; + + static struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = __devexit_p(ab8500_btemp_remove), @@ -1106,6 +1160,7 @@ static struct platform_driver ab8500_btemp_driver = { .driver = { .name = "ab8500-btemp", .owner = THIS_MODULE, + .of_match_table = ab8500_btemp_match, }, };
diff --git a/include/linux/mfd/ab8500/pwmleds.h b/include/linux/mfd/ab8500/pwmleds.h new file mode 100644 index 0000000..e316582 --- /dev/null +++ b/include/linux/mfd/ab8500/pwmleds.h @@ -0,0 +1,20 @@ +/* + * Copyright ST-Ericsson 2012. + * + * Author: Naga Radhesh naga.radheshy@stericsson.com + * Licensed under GPLv2. + */ +#ifndef _AB8500_PWMLED_H +#define _AB8500_PWMLED_H + +struct ab8500_led_pwm { + int pwm_id; + int blink_en; +}; + +struct ab8500_pwmled_platform_data { + int num_pwm; + struct ab8500_led_pwm *leds; +}; + +#endif
On Tuesday 10 July 2012, Rajanikanth H.V wrote:
--- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt @@ -0,0 +1,54 @@ +AB8500 Battery Termperature Monitor Driver
+AB8500 is a mixed signal multimedia and power management +device comprising: power and energy management module, +WalliCharger and USB charger interface, audio, general +purpose ADC TVOut, clock management and SIM card Interface.
+Battery temperature monitoring support is part of 'energy +management module', the other components of this module +are: 'main and USB Combo charger' and fuel guage.
+The properties below describes the node for battery +temperature monitor driver.
+Required Properties: +- compatible = "stericsson,ab8500-btemp"
+interrupts:
- Four battery temperature ranges are be defined
- which results in interrupt events as:
- Btemp
- BtempLow
- BtempMedium
- BtempHigh
These names do not match the five interrupts in the example or in the code. When you provide an "interrupt-names" property you have to define the exact strings that are permissible for them in the binding.
+Supplied-to:
- This shall be power supply class dependency where in the runtime battery
- properties will be shared across fuel guage and charging algorithm driver.
I probably don't understand enough of this, but shouldn't the other devices that are supplied by this have a reference to this node rather than doing it this way around? Why use strings here instead of phandles?
You are also not listing some of the properties that are in the device tree here, like the "interrupts" property itself.
diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c new file mode 100644 index 0000000..3349ceb --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-bm.c
Didn't we conclude that this file has no board-specific information in it? Either explain why it's still here, or move it into the driver itself.
+/*
- Note that the batres_vs_temp table must be strictly sorted by falling
- temperature values to work.
- */
+#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY +#define BATRES 180 +#else +#define BATRES 300 +#endif
I think I mentioned before that you need to get rid of the CONFIG_AB8500_9100_LI_ION_BATTERY symbol. If you have exclusive compile-time options, it is impossible to build a kernel that runs on all system, so this has to be a run-time option.
Arnd
Some of my comments are picky, but if it's going into Mainline, it should at least look professional.
You didn't CC the ST-Ericsson internal mailing list.
Address is STEricsson_nomadik_linux@list.st.com
I'll do it for now, but please do so on your next submission.
On 10/07/12 15:23, Rajanikanth H.V wrote:
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for battery temperature monitor driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com
.../bindings/power_supply/ab8500/btemp.txt | 54 ++ arch/arm/boot/dts/db8500.dtsi | 17 + arch/arm/mach-ux500/Makefile | 4 +- arch/arm/mach-ux500/board-mop500-bm.c | 532 ++++++++++++++++++++ arch/arm/mach-ux500/include/mach/board-mop500-bm.h | 24 + drivers/mfd/ab8500-core.c | 1 + drivers/power/Kconfig | 8 +- drivers/power/ab8500_btemp.c | 79 ++- include/linux/mfd/ab8500/pwmleds.h | 20 + 9 files changed, 722 insertions(+), 17 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt create mode 100644 arch/arm/mach-ux500/board-mop500-bm.c create mode 100644 arch/arm/mach-ux500/include/mach/board-mop500-bm.h create mode 100644 include/linux/mfd/ab8500/pwmleds.h
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt new file mode 100644 index 0000000..8543ed1 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt @@ -0,0 +1,54 @@ +AB8500 Battery Termperature Monitor Driver
Spelling.
+AB8500 is a mixed signal multimedia and power management +device comprising: power and energy management module, +WalliCharger and USB charger interface, audio, general +purpose ADC TVOut, clock management and SIM card Interface.
Mixture of capitalised and otherwise device names.
+Battery temperature monitoring support is part of 'energy +management module', the other components of this module +are: 'main and USB Combo charger' and fuel guage.
Spelling. Mixed use of ''.
+The properties below describes the node for battery +temperature monitor driver.
+Required Properties: +- compatible = "stericsson,ab8500-btemp"
+interrupts:
- Four battery temperature ranges are be defined
- which results in interrupt events as:
- Btemp
- BtempLow
- BtempMedium
- BtempHigh
+Supplied-to:
- This shall be power supply class dependency where in the runtime battery
- properties will be shared across fuel guage and charging algorithm driver.
Spelling.
+Thermister-interface:
- 'btemp' and 'batctrl' are the pins interfaced for battery temperature
- measurement, btemp is used when NTC(Negative Termperature coefficient)
Spelling.
- resister is interfaced external to battery and batctrl is used when
- NTC resister is internal to battery.
+example: +ab8500-btemp {
- compatible = "stericsson,ab8500-btemp";
- interrupt-names =
"BAT_CTRL_INDB", /* battery removal indicator */
"BTEMP_LOW", /* Btemp < BtempLow, if battery temperature is lower than -10°C */
"BTEMP_HIGH", /* BtempLow < Btemp < BtempMedium,
if battery temperature is between -10 and 0°C */
"BTEMP_LOW_MEDIUM", /* BtempMedium < Btemp < BtempHigh,
if battery temperature is between 0°C and “MaxTemp”.*/
"BTEMP_MEDIUM_HIGH";/* Btemp > BtempHigh,
if battery temperature is higher than “MaxTemp”. */
- supplied-to = "ab8500_chargalg", "ab8500_fg";
- thermister-internal-to-battery = <1>;
+}; diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index 7279165..527fdc3 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -330,6 +330,23 @@ vddadc-supply = <&ab8500_ldo_tvout_reg>; };
ab8500-btemp {
compatible = "stericsson,ab8500-btemp";
interrupts = <20 0x04
80 0x04
81 0x04
82 0x04
83 0x04>;
Odd tabbing.
interrupt-names = "BAT_CTRL_INDB",
"BTEMP_LOW",
"BTEMP_HIGH",
"BTEMP_LOW_MEDIUM",
"BTEMP_MEDIUM_HIGH";
As above.
supplied_to = "ab8500_chargalg", "ab8500_fg";
num_supplicants = <2>;
battery_term_on_batctrl = <1>;
};
ab8500-usb { compatible = "stericsson,ab8500-usb"; interrupts = < 90 0x4
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 026086f..b474917 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -12,6 +12,8 @@ obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ board-mop500-uib.o board-mop500-stuib.o \ board-mop500-u8500uib.o \ board-mop500-pins.o \
board-mop500-msp.o
board-mop500-msp.o \
board-mop500-bm.o
Unrelated line change.
obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c diff --git a/arch/arm/mach-ux500/include/mach/board-mop500-bm.h b/arch/arm/mach-ux500/include/mach/board-mop500-bm.h
It would be better if you can find a way to not upstream these.
I think this data would be better suited for an include header file.
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 738b9c5..402f630 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1046,6 +1046,7 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = { }, { .name = "ab8500-btemp",
.num_resources = ARRAY_SIZE(ab8500_btemp_resources), .resources = ab8500_btemp_resources, },.of_compatible = "stericsson,ab8500-btemp",
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index e3a3b49..00dec0f 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -303,10 +303,10 @@ config AB8500_BM help Say Y to include support for AB5500 battery management.
-config AB8500_BATTERY_THERM_ON_BATCTRL
- bool "Thermistor connected on BATCTRL ADC"
+config AB8500_9100_LI_ION_BATTERY
- bool "Enable support of the 9100 Li-ion battery charging" depends on AB8500_BM help
Say Y to enable battery temperature measurements using
thermistor connected on BATCTRL ADC.
Say Y to enable support of the 9100 Li-ion battery charging.
Random formatting.
endif # POWER_SUPPLY diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index bba3cca..1272bba 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -16,6 +16,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/completion.h> @@ -25,6 +26,7 @@ #include <linux/mfd/abx500/ab8500-bm.h> #include <linux/mfd/abx500/ab8500-gpadc.h> #include <linux/jiffies.h> +#include <mach/board-mop500-bm.h>
#define VTVOUT_V 1800
@@ -964,11 +966,13 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) { int irq, i, ret = 0; u8 val;
- struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
I already told you about this.
- struct device_node *np = pdev->dev.of_node; struct ab8500_btemp *di;
- u32 pval;
- const char *sup_val;
- if (!plat_data) {
dev_err(&pdev->dev, "No platform data\n");
And this. Check the last review I provided.
- if (!np) {
return -EINVAL; }dev_err(&pdev->dev, "No DT node for btemp found\n");
@@ -981,21 +985,64 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->parent = dev_get_drvdata(pdev->dev.parent); di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- /* get btemp specific platform data */
- di->pdata = plat_data->btemp;
- if (!di->pdata) {
dev_err(di->dev, "no btemp platform data supplied\n");
We still need to support registering from platform code.
- di->pdata =
kzalloc(sizeof(struct abx500_btemp_platform_data), GFP_KERNEL);
Use devm_kzalloc instead.
- if (di->pdata == NULL) {
ret = -ENOMEM;
goto free_device_info;
- }
- /* get battery specific platform data */
- ret = of_property_read_u32(np, "num_supplicants", &pval);
- if (ret) {
dev_err(di->dev, "missing property num_supplicants\n");
kfree(di->pdata);
Then remove this line.
ret = -EINVAL;
goto free_device_info;
- }
- di->pdata->num_supplicants = pval;
- di->pdata->supplied_to =
kzalloc(di->pdata->num_supplicants *
sizeof(const char *), GFP_KERNEL);
- if (di->pdata->supplied_to == NULL) {
ret = -EINVAL; goto free_device_info; }kfree(di->pdata);
- /* get battery specific platform data */
- di->bat = plat_data->battery;
Don't remove this, check for it.
- for (val = 0; val < di->pdata->num_supplicants; ++val)
if (of_property_read_string_index
(np, "supplied_to", val, &sup_val) == 0)
*(di->pdata->supplied_to + val) = (char *)sup_val;
else {
dev_err(di->dev, "insufficient number of supplied_to data found\n");
kfree(di->pdata);
kfree(di->pdata->supplied_to);
ret = -EINVAL;
goto free_device_info;
}
- di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL); if (!di->bat) {
dev_err(di->dev, "no battery platform data supplied\n");
ret = -EINVAL;
kfree(di->pdata->supplied_to);
kfree(di->pdata);
goto free_device_info; }ret = -ENOMEM;
- dev_dbg(di->dev, "getting battery information\n");
Is this really necessary?
di->bat = &ab8500_bm_data;
ret = of_property_read_u32(np, "battery_term_on_batctrl", &pval);
if (ret) {
dev_err(di->dev, "missing property battery_term_on_batctrl\n");
kfree(di->pdata->supplied_to);
kfree(di->pdata);
kfree(di->bat);
ret = -ENOMEM;
goto free_device_info;
}
if (pval == 0) {
di->bat->bat_type = bat_type_ext_thermister;
di->bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
}
/* BTEMP supply */ di->btemp_psy.name = "ab8500_btemp";
@@ -1008,7 +1055,6 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->btemp_psy.external_power_changed = ab8500_btemp_external_power_changed;
Unrelated change.
/* Create a work queue for the btemp */ di->btemp_wq = create_singlethread_workqueue("ab8500_btemp_wq"); @@ -1090,14 +1136,22 @@ free_irq: irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); free_irq(irq, di); }
As above.
free_btemp_wq: destroy_workqueue(di->btemp_wq);
As above.
free_device_info: kfree(di);
return ret; }
+static const struct of_device_id ab8500_btemp_match[] = {
- {.compatible = "stericsson,ab8500-btemp",},
Spacing is not consistent with previous submissions.
- {},
+};
- static struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = __devexit_p(ab8500_btemp_remove),
@@ -1106,6 +1160,7 @@ static struct platform_driver ab8500_btemp_driver = { .driver = { .name = "ab8500-btemp", .owner = THIS_MODULE,
}, };.of_match_table = ab8500_btemp_match,
diff --git a/include/linux/mfd/ab8500/pwmleds.h b/include/linux/mfd/ab8500/pwmleds.h new file mode 100644 index 0000000..e316582 --- /dev/null +++ b/include/linux/mfd/ab8500/pwmleds.h @@ -0,0 +1,20 @@ +/*
- Copyright ST-Ericsson 2012.
- Author: Naga Radhesh naga.radheshy@stericsson.com
- Licensed under GPLv2.
- */
+#ifndef _AB8500_PWMLED_H +#define _AB8500_PWMLED_H
+struct ab8500_led_pwm {
- int pwm_id;
- int blink_en;
+};
+struct ab8500_pwmled_platform_data {
- int num_pwm;
- struct ab8500_led_pwm *leds;
+};
+#endif