diff options
author | Pali Rohár <pali.rohar@gmail.com> | 2013-11-19 11:18:04 +0100 |
---|---|---|
committer | Anton Vorontsov <anton@enomsg.org> | 2013-12-23 17:58:03 -0800 |
commit | 32260308b4cafcd71b1c0aac35675dc68120c33d (patch) | |
tree | 9d8b0c54b2e89b9ccf94b8143099da369af46e02 /drivers/power | |
parent | 56fb8de53e20a853e1a919bf9fb25148ef7560cb (diff) | |
download | op-kernel-dev-32260308b4cafcd71b1c0aac35675dc68120c33d.zip op-kernel-dev-32260308b4cafcd71b1c0aac35675dc68120c33d.tar.gz |
bq2415x_charger: Use power_supply notifier for automode
This patch removing set_mode_hook function from board data and replacing
it with new string variable of notifier power supply device. After this
change it is possible to add DT support because driver does not need
specific board function anymore. Only static data and name of power supply
device is required.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Anton Vorontsov <anton@enomsg.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/bq2415x_charger.c | 77 |
1 files changed, 60 insertions, 17 deletions
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c index df893dd..0bece70 100644 --- a/drivers/power/bq2415x_charger.c +++ b/drivers/power/bq2415x_charger.c @@ -1,7 +1,7 @@ /* * bq2415x charger driver * - * Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com> + * Copyright (C) 2011-2013 Pali Rohár <pali.rohar@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -170,6 +170,7 @@ struct bq2415x_device { struct bq2415x_platform_data init_data; struct power_supply charger; struct delayed_work work; + struct notifier_block nb; enum bq2415x_mode reported_mode;/* mode reported by hook function */ enum bq2415x_mode mode; /* current configured mode */ enum bq2415x_chip chip; @@ -795,24 +796,53 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode) } -/* hook function called by other driver which set reported mode */ -static void bq2415x_hook_function(enum bq2415x_mode mode, void *data) +static int bq2415x_notifier_call(struct notifier_block *nb, + unsigned long val, void *v) { - struct bq2415x_device *bq = data; + struct bq2415x_device *bq = + container_of(nb, struct bq2415x_device, nb); + struct power_supply *psy = v; + enum bq2415x_mode mode; + union power_supply_propval prop; + int ret; + int mA; - if (!bq) - return; + if (val != PSY_EVENT_PROP_CHANGED) + return NOTIFY_OK; + + if (strcmp(psy->name, bq->init_data.notify_device) != 0) + return NOTIFY_OK; + + dev_dbg(bq->dev, "notifier call was called\n"); + + ret = psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &prop); + if (ret != 0) + return NOTIFY_OK; + + mA = prop.intval; + + if (mA == 0) + mode = BQ2415X_MODE_OFF; + else if (mA < 500) + mode = BQ2415X_MODE_NONE; + else if (mA < 1800) + mode = BQ2415X_MODE_HOST_CHARGER; + else + mode = BQ2415X_MODE_DEDICATED_CHARGER; + + if (bq->reported_mode == mode) + return NOTIFY_OK; - dev_dbg(bq->dev, "hook function was called\n"); bq->reported_mode = mode; /* if automode is not enabled do not tell about reported_mode */ if (bq->automode < 1) - return; + return NOTIFY_OK; sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); bq2415x_set_mode(bq, bq->reported_mode); + return NOTIFY_OK; } /**** timer functions ****/ @@ -1512,6 +1542,7 @@ static int bq2415x_probe(struct i2c_client *client, int num; char *name; struct bq2415x_device *bq; + struct power_supply *psy; if (!client->dev.platform_data) { dev_err(&client->dev, "platform data not set\n"); @@ -1573,16 +1604,27 @@ static int bq2415x_probe(struct i2c_client *client, goto error_4; } - if (bq->init_data.set_mode_hook) { - if (bq->init_data.set_mode_hook( - bq2415x_hook_function, bq)) { - bq->automode = 1; + if (bq->init_data.notify_device) { + bq->nb.notifier_call = bq2415x_notifier_call; + ret = power_supply_reg_notifier(&bq->nb); + if (ret) { + dev_err(bq->dev, "failed to reg notifier: %d\n", ret); + goto error_5; + } + psy = power_supply_get_by_name(bq->init_data.notify_device); + if (psy) { + /* Query for initial reported_mode and set it */ + bq2415x_notifier_call(&bq->nb, + PSY_EVENT_PROP_CHANGED, psy); bq2415x_set_mode(bq, bq->reported_mode); - dev_info(bq->dev, "automode enabled\n"); } else { - bq->automode = -1; - dev_info(bq->dev, "automode failed\n"); + dev_info(bq->dev, "notifier power supply device (%s) " + "for automode is not registred yet... " + "automode will not work without that device\n", + bq->init_data.notify_device); } + bq->automode = 1; + dev_info(bq->dev, "automode enabled\n"); } else { bq->automode = -1; dev_info(bq->dev, "automode not supported\n"); @@ -1594,6 +1636,7 @@ static int bq2415x_probe(struct i2c_client *client, dev_info(bq->dev, "driver registered\n"); return 0; +error_5: error_4: bq2415x_sysfs_exit(bq); error_3: @@ -1614,8 +1657,8 @@ static int bq2415x_remove(struct i2c_client *client) { struct bq2415x_device *bq = i2c_get_clientdata(client); - if (bq->init_data.set_mode_hook) - bq->init_data.set_mode_hook(NULL, NULL); + if (bq->init_data.notify_device) + power_supply_unreg_notifier(&bq->nb); bq2415x_sysfs_exit(bq); bq2415x_power_supply_exit(bq); |