diff options
author | Liam Breck <liam@networkimprov.net> | 2017-01-18 12:26:52 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-14 08:00:14 -0400 |
commit | 4b7dac0a23b7c416b30962362268e8e55da9eaff (patch) | |
tree | c786f8eb84239aee67b92567107932a873624601 | |
parent | 63e1acc84d28d73107e72482e33dcca152bb5ea4 (diff) |
power: supply: bq24190_charger: Call power_supply_changed() for relevant component
commit 2d9fee6a42ea170e4378b3363a7ad385d0e67281 upstream.
We wrongly get uevents for bq24190-charger and bq24190-battery on every
register change.
Fix by checking the association with charger and battery before
emitting uevent(s).
Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger")
Signed-off-by: Liam Breck <kernel@networkimprov.net>
Acked-by: Mark Greer <mgreer@animalcreek.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/power/supply/bq24190_charger.c | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index d0afafd7b1cb..94d282286bfd 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c | |||
@@ -159,7 +159,6 @@ struct bq24190_dev_info { | |||
159 | unsigned int gpio_int; | 159 | unsigned int gpio_int; |
160 | unsigned int irq; | 160 | unsigned int irq; |
161 | struct mutex f_reg_lock; | 161 | struct mutex f_reg_lock; |
162 | bool first_time; | ||
163 | bool charger_health_valid; | 162 | bool charger_health_valid; |
164 | bool battery_health_valid; | 163 | bool battery_health_valid; |
165 | bool battery_status_valid; | 164 | bool battery_status_valid; |
@@ -1197,7 +1196,10 @@ static const struct power_supply_desc bq24190_battery_desc = { | |||
1197 | static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) | 1196 | static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) |
1198 | { | 1197 | { |
1199 | struct bq24190_dev_info *bdi = data; | 1198 | struct bq24190_dev_info *bdi = data; |
1200 | bool alert_userspace = false; | 1199 | const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK; |
1200 | const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK | ||
1201 | | BQ24190_REG_F_NTC_FAULT_MASK; | ||
1202 | bool alert_charger = false, alert_battery = false; | ||
1201 | u8 ss_reg = 0, f_reg = 0; | 1203 | u8 ss_reg = 0, f_reg = 0; |
1202 | int ret; | 1204 | int ret; |
1203 | 1205 | ||
@@ -1225,8 +1227,12 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) | |||
1225 | ret); | 1227 | ret); |
1226 | } | 1228 | } |
1227 | 1229 | ||
1230 | if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss)) | ||
1231 | alert_battery = true; | ||
1232 | if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss)) | ||
1233 | alert_charger = true; | ||
1234 | |||
1228 | bdi->ss_reg = ss_reg; | 1235 | bdi->ss_reg = ss_reg; |
1229 | alert_userspace = true; | ||
1230 | } | 1236 | } |
1231 | 1237 | ||
1232 | mutex_lock(&bdi->f_reg_lock); | 1238 | mutex_lock(&bdi->f_reg_lock); |
@@ -1239,33 +1245,23 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) | |||
1239 | } | 1245 | } |
1240 | 1246 | ||
1241 | if (f_reg != bdi->f_reg) { | 1247 | if (f_reg != bdi->f_reg) { |
1248 | if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f)) | ||
1249 | alert_battery = true; | ||
1250 | if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f)) | ||
1251 | alert_charger = true; | ||
1252 | |||
1242 | bdi->f_reg = f_reg; | 1253 | bdi->f_reg = f_reg; |
1243 | bdi->charger_health_valid = true; | 1254 | bdi->charger_health_valid = true; |
1244 | bdi->battery_health_valid = true; | 1255 | bdi->battery_health_valid = true; |
1245 | bdi->battery_status_valid = true; | 1256 | bdi->battery_status_valid = true; |
1246 | |||
1247 | alert_userspace = true; | ||
1248 | } | 1257 | } |
1249 | 1258 | ||
1250 | mutex_unlock(&bdi->f_reg_lock); | 1259 | mutex_unlock(&bdi->f_reg_lock); |
1251 | 1260 | ||
1252 | /* | 1261 | if (alert_charger) |
1253 | * Sometimes bq24190 gives a steady trickle of interrupts even | 1262 | power_supply_changed(bdi->charger); |
1254 | * though the watchdog timer is turned off and neither the STATUS | 1263 | if (alert_battery) |
1255 | * nor FAULT registers have changed. Weed out these sprurious | 1264 | power_supply_changed(bdi->battery); |
1256 | * interrupts so userspace isn't alerted for no reason. | ||
1257 | * In addition, the chip always generates an interrupt after | ||
1258 | * register reset so we should ignore that one (the very first | ||
1259 | * interrupt received). | ||
1260 | */ | ||
1261 | if (alert_userspace) { | ||
1262 | if (!bdi->first_time) { | ||
1263 | power_supply_changed(bdi->charger); | ||
1264 | power_supply_changed(bdi->battery); | ||
1265 | } else { | ||
1266 | bdi->first_time = false; | ||
1267 | } | ||
1268 | } | ||
1269 | 1265 | ||
1270 | out: | 1266 | out: |
1271 | pm_runtime_put_sync(bdi->dev); | 1267 | pm_runtime_put_sync(bdi->dev); |
@@ -1300,6 +1296,10 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi) | |||
1300 | goto out; | 1296 | goto out; |
1301 | 1297 | ||
1302 | ret = bq24190_set_mode_host(bdi); | 1298 | ret = bq24190_set_mode_host(bdi); |
1299 | if (ret < 0) | ||
1300 | goto out; | ||
1301 | |||
1302 | ret = bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); | ||
1303 | out: | 1303 | out: |
1304 | pm_runtime_put_sync(bdi->dev); | 1304 | pm_runtime_put_sync(bdi->dev); |
1305 | return ret; | 1305 | return ret; |
@@ -1375,7 +1375,8 @@ static int bq24190_probe(struct i2c_client *client, | |||
1375 | bdi->model = id->driver_data; | 1375 | bdi->model = id->driver_data; |
1376 | strncpy(bdi->model_name, id->name, I2C_NAME_SIZE); | 1376 | strncpy(bdi->model_name, id->name, I2C_NAME_SIZE); |
1377 | mutex_init(&bdi->f_reg_lock); | 1377 | mutex_init(&bdi->f_reg_lock); |
1378 | bdi->first_time = true; | 1378 | bdi->f_reg = 0; |
1379 | bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ | ||
1379 | bdi->charger_health_valid = false; | 1380 | bdi->charger_health_valid = false; |
1380 | bdi->battery_health_valid = false; | 1381 | bdi->battery_health_valid = false; |
1381 | bdi->battery_status_valid = false; | 1382 | bdi->battery_status_valid = false; |
@@ -1489,6 +1490,8 @@ static int bq24190_pm_resume(struct device *dev) | |||
1489 | struct i2c_client *client = to_i2c_client(dev); | 1490 | struct i2c_client *client = to_i2c_client(dev); |
1490 | struct bq24190_dev_info *bdi = i2c_get_clientdata(client); | 1491 | struct bq24190_dev_info *bdi = i2c_get_clientdata(client); |
1491 | 1492 | ||
1493 | bdi->f_reg = 0; | ||
1494 | bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ | ||
1492 | bdi->charger_health_valid = false; | 1495 | bdi->charger_health_valid = false; |
1493 | bdi->battery_health_valid = false; | 1496 | bdi->battery_health_valid = false; |
1494 | bdi->battery_status_valid = false; | 1497 | bdi->battery_status_valid = false; |
@@ -1496,6 +1499,7 @@ static int bq24190_pm_resume(struct device *dev) | |||
1496 | pm_runtime_get_sync(bdi->dev); | 1499 | pm_runtime_get_sync(bdi->dev); |
1497 | bq24190_register_reset(bdi); | 1500 | bq24190_register_reset(bdi); |
1498 | bq24190_set_mode_host(bdi); | 1501 | bq24190_set_mode_host(bdi); |
1502 | bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); | ||
1499 | pm_runtime_put_sync(bdi->dev); | 1503 | pm_runtime_put_sync(bdi->dev); |
1500 | 1504 | ||
1501 | /* Things may have changed while suspended so alert upper layer */ | 1505 | /* Things may have changed while suspended so alert upper layer */ |