diff mbox series

[1/3] extcon: max8997: Add CHGINS and CHGRM interrupt handling

Message ID 20201202203516.43053-1-timon.baetz@protonmail.com
State Superseded
Headers show
Series [1/3] extcon: max8997: Add CHGINS and CHGRM interrupt handling | expand

Commit Message

Timon Baetz Dec. 2, 2020, 9:07 p.m. UTC
Allows the MAX8997 charger to set the current limit depending on
the detected extcon charger type.

Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>
---
 drivers/extcon/extcon-max8997.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Krzysztof Kozlowski Dec. 2, 2020, 9:50 p.m. UTC | #1
On Wed, Dec 02, 2020 at 09:07:19PM +0000, Timon Baetz wrote:
> Register for extcon notification and set charging current depending on
> the detected cable type. Current values are taken from i9100 kernel
> fork.
> 
> Enable and disable the CHARGER regulator based on extcon events and
> remove regulator-always-on from the device tree.
> 
> Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>
> ---
>  arch/arm/boot/dts/exynos4210-i9100.dts |  1 -
>  drivers/power/supply/max8997_charger.c | 92 ++++++++++++++++++++++++++
>  2 files changed, 92 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/exynos4210-i9100.dts b/arch/arm/boot/dts/exynos4210-i9100.dts
> index 6d0c04d77a39..9f8d927e0d21 100644
> --- a/arch/arm/boot/dts/exynos4210-i9100.dts
> +++ b/arch/arm/boot/dts/exynos4210-i9100.dts
> @@ -560,7 +560,6 @@ charger_reg: CHARGER {
>  				regulator-name = "CHARGER";
>  				regulator-min-microamp = <60000>;
>  				regulator-max-microamp = <2580000>;
> -				regulator-always-on;

Thanks for the patch.

The DTS changes always go separately.

>  			};
>  
>  			chargercv_reg: CHARGER_CV {
> diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c
> index 1947af25879a..26cd271576ec 100644
> --- a/drivers/power/supply/max8997_charger.c
> +++ b/drivers/power/supply/max8997_charger.c
> @@ -6,6 +6,7 @@
>  //  MyungJoo Ham <myungjoo.ham@samsung.com>
>  
>  #include <linux/err.h>
> +#include <linux/extcon.h>
>  #include <linux/module.h>
>  #include <linux/slab.h>
>  #include <linux/platform_device.h>
> @@ -31,6 +32,12 @@ struct charger_data {
>  	struct device *dev;
>  	struct max8997_dev *iodev;
>  	struct power_supply *battery;
> +	struct regulator *reg;

You need to include regulator consumer.h.

> +	struct {

It makes all dereferences longer. Just add a comment that these are
related to the extcon.

> +		struct extcon_dev *edev;
> +		struct notifier_block nb;
> +		struct work_struct work;
> +	} extcon;
>  };
>  
>  static enum power_supply_property max8997_battery_props[] = {
> @@ -88,6 +95,63 @@ static int max8997_battery_get_property(struct power_supply *psy,
>  	return 0;
>  }
>  
> +static void max8997_battery_extcon_evt_stop_work(void *data)
> +{
> +	struct charger_data *charger = data;
> +
> +	cancel_work_sync(&charger->extcon.work);
> +}
> +
> +static void max8997_battery_extcon_evt_worker(struct work_struct *work)
> +{
> +	struct charger_data *charger =
> +	    container_of(work, struct charger_data, extcon.work);
> +	int ret, current_limit;
> +	struct extcon_dev *edev = charger->extcon.edev;
> +

It would be useful to report the current with POWER_SUPPLY_PROP_* but
it is a different patch.

> +	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
> +		dev_dbg(charger->dev, "USB SDP charger is connected\n");
> +		current_limit = 450000;
> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
> +		dev_dbg(charger->dev, "USB DCP charger is connected\n");
> +		current_limit = 650000;
> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {
> +		dev_dbg(charger->dev, "USB FAST charger is connected\n");
> +		current_limit = 650000;
> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) {
> +		dev_dbg(charger->dev, "USB SLOW charger is connected\n");
> +		current_limit = 650000;

The charger provides 500 mA, so I wonder whether 650 here is correct. Is
it at different voltage?

> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
> +		dev_dbg(charger->dev, "USB CDP charger is connected\n");
> +		current_limit = 650000;
> +	} else {
> +		dev_dbg(charger->dev, "USB charger is diconnected\n");
> +		current_limit = -1;
> +	}
> +
> +	if (current_limit > 0) {

ret should be declared here.

> +		ret = regulator_set_current_limit(charger->reg, current_limit, current_limit);
> +		if (ret)
> +			dev_err(charger->dev, "failed to set current limit: %d\n", ret);

Failure of setting the current should rather disable the charging.

> +		ret = regulator_enable(charger->reg);
> +		if (ret)
> +			dev_err(charger->dev, "failed to enable regulator: %d\n", ret);
> +	} else {

ret should be declared here.

> +		ret = regulator_disable(charger->reg);
> +		if (ret)
> +			dev_err(charger->dev, "failed to disable regulator: %d\n", ret);
> +	}

What about top-off charging?

> +}
> +
> +static int max8997_battery_extcon_evt(struct notifier_block *nb,
> +				unsigned long event, void *param)
> +{
> +	struct charger_data *charger =
> +		container_of(nb, struct charger_data, extcon.nb);
> +	schedule_work(&charger->extcon.work);
> +	return NOTIFY_OK;
> +}
> +
>  static const struct power_supply_desc max8997_battery_desc = {
>  	.name		= "max8997_pmic",
>  	.type		= POWER_SUPPLY_TYPE_BATTERY,
> @@ -104,6 +168,7 @@ static int max8997_battery_probe(struct platform_device *pdev)
>  	struct i2c_client *i2c = iodev->i2c;
>  	struct max8997_platform_data *pdata = iodev->pdata;
>  	struct power_supply_config psy_cfg = {};
> +	struct extcon_dev *edev;
>  
>  	if (!pdata) {
>  		dev_err(&pdev->dev, "No platform data supplied.\n");
> @@ -151,6 +216,12 @@ static int max8997_battery_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> +	edev = extcon_get_extcon_dev("max8997-muic");

Store it directly under charger->edev.

> +	if (edev == NULL) {

if (!edev) {

> +		dev_info(&pdev->dev, "extcon is not ready, probe deferred\n");

Do not print anything on deferrals.

> +		return -EPROBE_DEFER;
> +	}
> +
>  	charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
>  	if (!charger)
>  		return -ENOMEM;
> @@ -170,6 +241,27 @@ static int max8997_battery_probe(struct platform_device *pdev)
>  		return PTR_ERR(charger->battery);
>  	}
>  
> +	charger->reg = regulator_get(&pdev->dev, "CHARGER");

Here and in extcon_get_extcon_dev() - you make all these devices tightly
coupled. It will work, but I am afraid it's easy to break later.

Instead you should have a device node in DTS to which the charger could
bind and where the driver will find regulator supply and extcon
phandles (with extcon_get_edev_by_phandle() for example).

> +	if (IS_ERR(charger->reg)) {
> +		dev_err(&pdev->dev, "couldn't get CHARGER regulator\n");
> +		return PTR_ERR(charger->reg);
> +	}
> +
> +	INIT_WORK(&charger->extcon.work, max8997_battery_extcon_evt_worker);
> +	ret = devm_add_action(&pdev->dev, max8997_battery_extcon_evt_stop_work, charger);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to add extcon evt stop action: %d\n", ret);

Missing regulator_put() here and in other places. Use devm-().

> +		return ret;
> +	}
> +	charger->extcon.edev = edev;
> +	charger->extcon.nb.notifier_call = max8997_battery_extcon_evt;
> +	ret = devm_extcon_register_notifier_all(&pdev->dev, charger->extcon.edev,
> +			&charger->extcon.nb);

Align the arguments with opening '('.

Best regards,
Krzysztof
Timon Baetz Dec. 5, 2020, 7:54 a.m. UTC | #2
On Wed, 2 Dec 2020 23:50:57 +0200, Krzysztof Kozlowski wrote:
> On Wed, Dec 02, 2020 at 09:07:19PM +0000, Timon Baetz wrote:

> > Register for extcon notification and set charging current depending on

> > the detected cable type. Current values are taken from i9100 kernel

> > fork.

> >

> > Enable and disable the CHARGER regulator based on extcon events and

> > remove regulator-always-on from the device tree.

> >

> > Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>

> > ---

> >  arch/arm/boot/dts/exynos4210-i9100.dts |  1 -

> >  drivers/power/supply/max8997_charger.c | 92 ++++++++++++++++++++++++++

> >  2 files changed, 92 insertions(+), 1 deletion(-)

> >

> > diff --git a/arch/arm/boot/dts/exynos4210-i9100.dts b/arch/arm/boot/dts/exynos4210-i9100.dts

> > index 6d0c04d77a39..9f8d927e0d21 100644

> > --- a/arch/arm/boot/dts/exynos4210-i9100.dts

> > +++ b/arch/arm/boot/dts/exynos4210-i9100.dts

> > @@ -560,7 +560,6 @@ charger_reg: CHARGER {

> >  				regulator-name = "CHARGER";

> >  				regulator-min-microamp = <60000>;

> >  				regulator-max-microamp = <2580000>;

> > -				regulator-always-on;  

> 

> Thanks for the patch.

> 

> The DTS changes always go separately.

> 

> >  			};

> >

> >  			chargercv_reg: CHARGER_CV {

> > diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c

> > index 1947af25879a..26cd271576ec 100644

> > --- a/drivers/power/supply/max8997_charger.c

> > +++ b/drivers/power/supply/max8997_charger.c

> > @@ -6,6 +6,7 @@

> >  //  MyungJoo Ham <myungjoo.ham@samsung.com>

> >

> >  #include <linux/err.h>

> > +#include <linux/extcon.h>

> >  #include <linux/module.h>

> >  #include <linux/slab.h>

> >  #include <linux/platform_device.h>

> > @@ -31,6 +32,12 @@ struct charger_data {

> >  	struct device *dev;

> >  	struct max8997_dev *iodev;

> >  	struct power_supply *battery;

> > +	struct regulator *reg;  

> 

> You need to include regulator consumer.h.

> 

> > +	struct {  

> 

> It makes all dereferences longer. Just add a comment that these are

> related to the extcon.

> 

> > +		struct extcon_dev *edev;

> > +		struct notifier_block nb;

> > +		struct work_struct work;

> > +	} extcon;

> >  };

> >

> >  static enum power_supply_property max8997_battery_props[] = {

> > @@ -88,6 +95,63 @@ static int max8997_battery_get_property(struct power_supply *psy,

> >  	return 0;

> >  }

> >

> > +static void max8997_battery_extcon_evt_stop_work(void *data)

> > +{

> > +	struct charger_data *charger = data;

> > +

> > +	cancel_work_sync(&charger->extcon.work);

> > +}

> > +

> > +static void max8997_battery_extcon_evt_worker(struct work_struct *work)

> > +{

> > +	struct charger_data *charger =

> > +	    container_of(work, struct charger_data, extcon.work);

> > +	int ret, current_limit;

> > +	struct extcon_dev *edev = charger->extcon.edev;

> > +  

> 

> It would be useful to report the current with POWER_SUPPLY_PROP_* but

> it is a different patch.

> 

> > +	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {

> > +		dev_dbg(charger->dev, "USB SDP charger is connected\n");

> > +		current_limit = 450000;

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {

> > +		dev_dbg(charger->dev, "USB DCP charger is connected\n");

> > +		current_limit = 650000;

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {

> > +		dev_dbg(charger->dev, "USB FAST charger is connected\n");

> > +		current_limit = 650000;

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) {

> > +		dev_dbg(charger->dev, "USB SLOW charger is connected\n");

> > +		current_limit = 650000;  

> 

> The charger provides 500 mA, so I wonder whether 650 here is correct. Is

> it at different voltage?

> 


I was wondering about that as well but as far as I can tell
https://github.com/krzk/linux-vendor-backup/blob/samsung/galaxy-s2-epic-4g-touch-sph-d710-exynos4210-dump/drivers/misc/max8997-muic.c#L1675-L1678
treats all 4 charger types as MUIC_CHG_TYPE_TA which ends up settings
650 mA. Voltage doesn't seem to change in vendor kernel.  

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {

> > +		dev_dbg(charger->dev, "USB CDP charger is connected\n");

> > +		current_limit = 650000;

> > +	} else {

> > +		dev_dbg(charger->dev, "USB charger is diconnected\n");

> > +		current_limit = -1;

> > +	}

> > +

> > +	if (current_limit > 0) {  

> 

> ret should be declared here.

> 

> > +		ret = regulator_set_current_limit(charger->reg, current_limit, current_limit);

> > +		if (ret)

> > +			dev_err(charger->dev, "failed to set current limit: %d\n", ret);  

> 

> Failure of setting the current should rather disable the charging.

> 

> > +		ret = regulator_enable(charger->reg);

> > +		if (ret)

> > +			dev_err(charger->dev, "failed to enable regulator: %d\n", ret);

> > +	} else {  

> 

> ret should be declared here.

> 

> > +		ret = regulator_disable(charger->reg);

> > +		if (ret)

> > +			dev_err(charger->dev, "failed to disable regulator: %d\n", ret);

> > +	}  

> 

> What about top-off charging?

> 

> > +}

> > +

> > +static int max8997_battery_extcon_evt(struct notifier_block *nb,

> > +				unsigned long event, void *param)

> > +{

> > +	struct charger_data *charger =

> > +		container_of(nb, struct charger_data, extcon.nb);

> > +	schedule_work(&charger->extcon.work);

> > +	return NOTIFY_OK;

> > +}

> > +

> >  static const struct power_supply_desc max8997_battery_desc = {

> >  	.name		= "max8997_pmic",

> >  	.type		= POWER_SUPPLY_TYPE_BATTERY,

> > @@ -104,6 +168,7 @@ static int max8997_battery_probe(struct platform_device *pdev)

> >  	struct i2c_client *i2c = iodev->i2c;

> >  	struct max8997_platform_data *pdata = iodev->pdata;

> >  	struct power_supply_config psy_cfg = {};

> > +	struct extcon_dev *edev;

> >

> >  	if (!pdata) {

> >  		dev_err(&pdev->dev, "No platform data supplied.\n");

> > @@ -151,6 +216,12 @@ static int max8997_battery_probe(struct platform_device *pdev)

> >  		return ret;

> >  	}

> >

> > +	edev = extcon_get_extcon_dev("max8997-muic");  

> 

> Store it directly under charger->edev.

> 

> > +	if (edev == NULL) {  

> 

> if (!edev) {

> 

> > +		dev_info(&pdev->dev, "extcon is not ready, probe deferred\n");  

> 

> Do not print anything on deferrals.

> 

> > +		return -EPROBE_DEFER;

> > +	}

> > +

> >  	charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);

> >  	if (!charger)

> >  		return -ENOMEM;

> > @@ -170,6 +241,27 @@ static int max8997_battery_probe(struct platform_device *pdev)

> >  		return PTR_ERR(charger->battery);

> >  	}

> >

> > +	charger->reg = regulator_get(&pdev->dev, "CHARGER");  

> 

> Here and in extcon_get_extcon_dev() - you make all these devices tightly

> coupled. It will work, but I am afraid it's easy to break later.

> 

> Instead you should have a device node in DTS to which the charger could

> bind and where the driver will find regulator supply and extcon

> phandles (with extcon_get_edev_by_phandle() for example).

> 

> > +	if (IS_ERR(charger->reg)) {

> > +		dev_err(&pdev->dev, "couldn't get CHARGER regulator\n");

> > +		return PTR_ERR(charger->reg);

> > +	}

> > +

> > +	INIT_WORK(&charger->extcon.work, max8997_battery_extcon_evt_worker);

> > +	ret = devm_add_action(&pdev->dev, max8997_battery_extcon_evt_stop_work, charger);

> > +	if (ret) {

> > +		dev_err(&pdev->dev, "failed to add extcon evt stop action: %d\n", ret);  

> 

> Missing regulator_put() here and in other places. Use devm-().

> 

> > +		return ret;

> > +	}

> > +	charger->extcon.edev = edev;

> > +	charger->extcon.nb.notifier_call = max8997_battery_extcon_evt;

> > +	ret = devm_extcon_register_notifier_all(&pdev->dev, charger->extcon.edev,

> > +			&charger->extcon.nb);  

> 

> Align the arguments with opening '('.

> 

> Best regards,

> Krzysztof
Krzysztof Kozlowski Dec. 21, 2020, 2:11 p.m. UTC | #3
On Mon, Dec 21, 2020 at 09:53:08AM +0000, Timon Baetz wrote:
> This allows the MAX8997 charger to set the current limit depending on

> the detected extcon charger type.

> 

> Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>


Don't do this:
	In-Reply-To: <20201202203516.43053-1-timon.baetz@protonmail.com>

It's a v2, so new thread. If you want to reference previous work, paste
a link from lore.kernel.org.

Best regards,
Krzysztof
Krzysztof Kozlowski Dec. 21, 2020, 2:16 p.m. UTC | #4
On Mon, Dec 21, 2020 at 09:53:15AM +0000, Timon Baetz wrote:
> Register for extcon notification and set charging current depending on

> the detected cable type. Current values are taken from vendor kernel,

> where most charger types end up setting 650mA [0].

> 

> Also enable and disable the CHARGER regulator based on extcon events.

> 

> [0] https://github.com/krzk/linux-vendor-backup/blob/samsung/galaxy-s2-epic-4g-touch-sph-d710-exynos4210-dump/drivers/misc/max8997-muic.c#L1675-L1678

> 

> Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>

> ---

>  drivers/mfd/max8997.c                  |  4 +-

>  drivers/power/supply/max8997_charger.c | 94 ++++++++++++++++++++++++++

>  2 files changed, 96 insertions(+), 2 deletions(-)

> 

> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c

> index 68d8f2b95287..55d3a6f97783 100644

> --- a/drivers/mfd/max8997.c

> +++ b/drivers/mfd/max8997.c

> @@ -29,9 +29,9 @@

>  static const struct mfd_cell max8997_devs[] = {

>  	{ .name = "max8997-pmic", },

>  	{ .name = "max8997-rtc", },

> -	{ .name = "max8997-battery", },

> +	{ .name = "max8997-battery", .of_compatible = "maxim,max8997-battery", },

>  	{ .name = "max8997-haptic", },

> -	{ .name = "max8997-muic", },

> +	{ .name = "max8997-muic", .of_compatible = "maxim,max8997-muic", },


Undocumented bindings. The checkpatch should complain about it, so I
assume you did not run it. Please run the checkpatch.

>  	{ .name = "max8997-led", .id = 1 },

>  	{ .name = "max8997-led", .id = 2 },

>  };

> diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c

> index 1947af25879a..6e8750e455ea 100644

> --- a/drivers/power/supply/max8997_charger.c

> +++ b/drivers/power/supply/max8997_charger.c

> @@ -6,12 +6,14 @@

>  //  MyungJoo Ham <myungjoo.ham@samsung.com>

>  

>  #include <linux/err.h>

> +#include <linux/extcon.h>

>  #include <linux/module.h>

>  #include <linux/slab.h>

>  #include <linux/platform_device.h>

>  #include <linux/power_supply.h>

>  #include <linux/mfd/max8997.h>

>  #include <linux/mfd/max8997-private.h>

> +#include <linux/regulator/consumer.h>

>  

>  /* MAX8997_REG_STATUS4 */

>  #define DCINOK_SHIFT		1

> @@ -31,6 +33,10 @@ struct charger_data {

>  	struct device *dev;

>  	struct max8997_dev *iodev;

>  	struct power_supply *battery;

> +	struct regulator *reg;

> +	struct extcon_dev *edev;

> +	struct notifier_block extcon_nb;

> +	struct work_struct extcon_work;

>  };

>  

>  static enum power_supply_property max8997_battery_props[] = {

> @@ -88,6 +94,67 @@ static int max8997_battery_get_property(struct power_supply *psy,

>  	return 0;

>  }

>  

> +static void max8997_battery_extcon_evt_stop_work(void *data)

> +{

> +	struct charger_data *charger = data;

> +

> +	cancel_work_sync(&charger->extcon_work);

> +}

> +

> +static void max8997_battery_extcon_evt_worker(struct work_struct *work)

> +{

> +	struct charger_data *charger =

> +	    container_of(work, struct charger_data, extcon_work);

> +	struct extcon_dev *edev = charger->edev;

> +	int current_limit, ret;

> +

> +	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {

> +		dev_dbg(charger->dev, "USB SDP charger is connected\n");

> +		current_limit = 450000;

> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {

> +		dev_dbg(charger->dev, "USB DCP charger is connected\n");

> +		current_limit = 650000;

> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {

> +		dev_dbg(charger->dev, "USB FAST charger is connected\n");

> +		current_limit = 650000;

> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) {

> +		dev_dbg(charger->dev, "USB SLOW charger is connected\n");

> +		current_limit = 650000;

> +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {

> +		dev_dbg(charger->dev, "USB CDP charger is connected\n");

> +		current_limit = 650000;

> +	} else {

> +		dev_dbg(charger->dev, "USB charger is diconnected\n");

> +		current_limit = -1;

> +	}

> +

> +	if (current_limit > 0) {

> +		ret = regulator_set_current_limit(charger->reg, current_limit, current_limit);

> +		if (ret) {

> +			dev_err(charger->dev, "failed to set current limit: %d\n", ret);

> +			goto regulator_disable;


Unusual error path... if regulator was not enabled before and
regulator_set_current_limit() failed, you disable the regulator? Why?
Wasn't it already disabled?

Best regards,
Krzysztof
Krzysztof Kozlowski Dec. 21, 2020, 2:19 p.m. UTC | #5
On Mon, Dec 21, 2020 at 09:53:22AM +0000, Timon Baetz wrote:
> Set CHARGER current and CHARGER_CV voltage according to Galaxy S2 vendor
> sources [0,1].

Mention that the vendor sources are for Galaxy S2 Epic 4G Touch SPH-D710
Android.

This seems to depend on driver changes, so it will have to wait till
they reach mainline.

Best regards,
Krzysztof
Krzysztof Kozlowski Dec. 21, 2020, 2:20 p.m. UTC | #6
On Mon, Dec 21, 2020 at 09:53:28AM +0000, Timon Baetz wrote:
> muic node is only used for extcon consumers.

> charger node is used to specify muic and regulator.

> 

> Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>

> ---

>  arch/arm/boot/dts/exynos4210-i9100.dts | 10 ++++++++++

>  1 file changed, 10 insertions(+)


Arrange your patches within the patchset in a way preserving
bisectability. If 3/7 is applied, the charger will be off because kernel
disables unused regulators.

Best regards,
Krzysztof
Krzysztof Kozlowski Dec. 21, 2020, 2:23 p.m. UTC | #7
On Mon, Dec 21, 2020 at 09:53:35AM +0000, Timon Baetz wrote:
> Value taken from Galaxy S2 vendor kernel [0] which always sets 200mA.


Subject: "Add", not "Added", as in Linux coding style.

> 

> Also rearrange regulators based on definition in max8997.h.

> 

> [0] https://github.com/krzk/linux-vendor-backup/blob/samsung/galaxy-s2-epic-4g-touch-sph-d710-exynos4210-dump/drivers/power/sec_battery_u1.c#L1525

> 

> Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>

> ---

>  arch/arm/boot/dts/exynos4210-i9100.dts | 21 ++++++++++++++-------

>  1 file changed, 14 insertions(+), 7 deletions(-)

> 

> diff --git a/arch/arm/boot/dts/exynos4210-i9100.dts b/arch/arm/boot/dts/exynos4210-i9100.dts

> index 586d801af0b5..fec6da64f7c1 100644

> --- a/arch/arm/boot/dts/exynos4210-i9100.dts

> +++ b/arch/arm/boot/dts/exynos4210-i9100.dts

> @@ -560,6 +560,16 @@ safe2_sreg: ESAFEOUT2 {

>  				regulator-boot-on;

>  			};

>  

> +			EN32KHZ_AP {

> +				regulator-name = "EN32KHZ_AP";

> +				regulator-always-on;

> +			};

> +

> +			EN32KHZ_CP {

> +				regulator-name = "EN32KHZ_CP";

> +				regulator-always-on;

> +			};

> +

>  			charger_reg: CHARGER {

>  				regulator-name = "CHARGER";

>  				regulator-min-microamp = <200000>;

> @@ -573,13 +583,10 @@ chargercv_reg: CHARGER_CV {

>  				regulator-always-on;

>  			};

>  

> -			EN32KHZ_AP {

> -				regulator-name = "EN32KHZ_AP";

> -				regulator-always-on;

> -			};

> -

> -			EN32KHZ_CP {

> -				regulator-name = "EN32KHZ_CP";

> +			chargertopoff_reg: CHARGER_TOPOFF {


No need for label "chargertopoff_reg".

Best regards,
Krzysztof
Krzysztof Kozlowski Dec. 21, 2020, 2:24 p.m. UTC | #8
On Mon, Dec 21, 2020 at 09:53:41AM +0000, Timon Baetz wrote:
> Add maxim,max8997-battery and maxim,max8997-muic optional nodes.

> 

> Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>

> ---

>  .../bindings/regulator/max8997-regulator.txt          | 11 +++++++++++

>  1 file changed, 11 insertions(+)


I see you updated the bindings. However if you run scripts/checkpatch,
it would say that bindings go as first patch, so please re-order.

Best regards,
Krzysztof
Timon Baetz Dec. 21, 2020, 3:35 p.m. UTC | #9
On Mon, 21 Dec 2020 15:16:27 +0100, Krzysztof Kozlowski wrote:
> On Mon, Dec 21, 2020 at 09:53:15AM +0000, Timon Baetz wrote:

> > Register for extcon notification and set charging current depending on

> > the detected cable type. Current values are taken from vendor kernel,

> > where most charger types end up setting 650mA [0].

> >

> > Also enable and disable the CHARGER regulator based on extcon events.

> >

> > [0] https://github.com/krzk/linux-vendor-backup/blob/samsung/galaxy-s2-epic-4g-touch-sph-d710-exynos4210-dump/drivers/misc/max8997-muic.c#L1675-L1678

> >

> > Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>

> > ---

> >  drivers/mfd/max8997.c                  |  4 +-

> >  drivers/power/supply/max8997_charger.c | 94 ++++++++++++++++++++++++++

> >  2 files changed, 96 insertions(+), 2 deletions(-)

> >

> > diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c

> > index 68d8f2b95287..55d3a6f97783 100644

> > --- a/drivers/mfd/max8997.c

> > +++ b/drivers/mfd/max8997.c

> > @@ -29,9 +29,9 @@

> >  static const struct mfd_cell max8997_devs[] = {

> >  	{ .name = "max8997-pmic", },

> >  	{ .name = "max8997-rtc", },

> > -	{ .name = "max8997-battery", },

> > +	{ .name = "max8997-battery", .of_compatible = "maxim,max8997-battery", },

> >  	{ .name = "max8997-haptic", },

> > -	{ .name = "max8997-muic", },

> > +	{ .name = "max8997-muic", .of_compatible = "maxim,max8997-muic", },  

> 

> Undocumented bindings. The checkpatch should complain about it, so I

> assume you did not run it. Please run the checkpatch.

> 

> >  	{ .name = "max8997-led", .id = 1 },

> >  	{ .name = "max8997-led", .id = 2 },

> >  };

> > diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c

> > index 1947af25879a..6e8750e455ea 100644

> > --- a/drivers/power/supply/max8997_charger.c

> > +++ b/drivers/power/supply/max8997_charger.c

> > @@ -6,12 +6,14 @@

> >  //  MyungJoo Ham <myungjoo.ham@samsung.com>

> >

> >  #include <linux/err.h>

> > +#include <linux/extcon.h>

> >  #include <linux/module.h>

> >  #include <linux/slab.h>

> >  #include <linux/platform_device.h>

> >  #include <linux/power_supply.h>

> >  #include <linux/mfd/max8997.h>

> >  #include <linux/mfd/max8997-private.h>

> > +#include <linux/regulator/consumer.h>

> >

> >  /* MAX8997_REG_STATUS4 */

> >  #define DCINOK_SHIFT		1

> > @@ -31,6 +33,10 @@ struct charger_data {

> >  	struct device *dev;

> >  	struct max8997_dev *iodev;

> >  	struct power_supply *battery;

> > +	struct regulator *reg;

> > +	struct extcon_dev *edev;

> > +	struct notifier_block extcon_nb;

> > +	struct work_struct extcon_work;

> >  };

> >

> >  static enum power_supply_property max8997_battery_props[] = {

> > @@ -88,6 +94,67 @@ static int max8997_battery_get_property(struct power_supply *psy,

> >  	return 0;

> >  }

> >

> > +static void max8997_battery_extcon_evt_stop_work(void *data)

> > +{

> > +	struct charger_data *charger = data;

> > +

> > +	cancel_work_sync(&charger->extcon_work);

> > +}

> > +

> > +static void max8997_battery_extcon_evt_worker(struct work_struct *work)

> > +{

> > +	struct charger_data *charger =

> > +	    container_of(work, struct charger_data, extcon_work);

> > +	struct extcon_dev *edev = charger->edev;

> > +	int current_limit, ret;

> > +

> > +	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {

> > +		dev_dbg(charger->dev, "USB SDP charger is connected\n");

> > +		current_limit = 450000;

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {

> > +		dev_dbg(charger->dev, "USB DCP charger is connected\n");

> > +		current_limit = 650000;

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {

> > +		dev_dbg(charger->dev, "USB FAST charger is connected\n");

> > +		current_limit = 650000;

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) {

> > +		dev_dbg(charger->dev, "USB SLOW charger is connected\n");

> > +		current_limit = 650000;

> > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {

> > +		dev_dbg(charger->dev, "USB CDP charger is connected\n");

> > +		current_limit = 650000;

> > +	} else {

> > +		dev_dbg(charger->dev, "USB charger is diconnected\n");

> > +		current_limit = -1;

> > +	}

> > +

> > +	if (current_limit > 0) {

> > +		ret = regulator_set_current_limit(charger->reg, current_limit, current_limit);

> > +		if (ret) {

> > +			dev_err(charger->dev, "failed to set current limit: %d\n", ret);

> > +			goto regulator_disable;  

> 

> Unusual error path... if regulator was not enabled before and

> regulator_set_current_limit() failed, you disable the regulator? Why?

> Wasn't it already disabled?


Because I thought you asked me to in v1 of this patch:
> Failure of setting the current should rather disable the charging.


I probably misunderstood you comment then. So I guess it should just
return?

Thanks for reviewing,
Timon
Krzysztof Kozlowski Dec. 21, 2020, 3:43 p.m. UTC | #10
On Mon, Dec 21, 2020 at 03:35:07PM +0000, Timon Baetz wrote:
> On Mon, 21 Dec 2020 15:16:27 +0100, Krzysztof Kozlowski wrote:
> > On Mon, Dec 21, 2020 at 09:53:15AM +0000, Timon Baetz wrote:
> > > Register for extcon notification and set charging current depending on
> > > the detected cable type. Current values are taken from vendor kernel,
> > > where most charger types end up setting 650mA [0].
> > >
> > > Also enable and disable the CHARGER regulator based on extcon events.
> > >
> > > [0] https://github.com/krzk/linux-vendor-backup/blob/samsung/galaxy-s2-epic-4g-touch-sph-d710-exynos4210-dump/drivers/misc/max8997-muic.c#L1675-L1678
> > >
> > > Signed-off-by: Timon Baetz <timon.baetz@protonmail.com>
> > > ---
> > >  drivers/mfd/max8997.c                  |  4 +-
> > >  drivers/power/supply/max8997_charger.c | 94 ++++++++++++++++++++++++++
> > >  2 files changed, 96 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
> > > index 68d8f2b95287..55d3a6f97783 100644
> > > --- a/drivers/mfd/max8997.c
> > > +++ b/drivers/mfd/max8997.c
> > > @@ -29,9 +29,9 @@
> > >  static const struct mfd_cell max8997_devs[] = {
> > >  	{ .name = "max8997-pmic", },
> > >  	{ .name = "max8997-rtc", },
> > > -	{ .name = "max8997-battery", },
> > > +	{ .name = "max8997-battery", .of_compatible = "maxim,max8997-battery", },
> > >  	{ .name = "max8997-haptic", },
> > > -	{ .name = "max8997-muic", },
> > > +	{ .name = "max8997-muic", .of_compatible = "maxim,max8997-muic", },  
> > 
> > Undocumented bindings. The checkpatch should complain about it, so I
> > assume you did not run it. Please run the checkpatch.
> > 
> > >  	{ .name = "max8997-led", .id = 1 },
> > >  	{ .name = "max8997-led", .id = 2 },
> > >  };
> > > diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c
> > > index 1947af25879a..6e8750e455ea 100644
> > > --- a/drivers/power/supply/max8997_charger.c
> > > +++ b/drivers/power/supply/max8997_charger.c
> > > @@ -6,12 +6,14 @@
> > >  //  MyungJoo Ham <myungjoo.ham@samsung.com>
> > >
> > >  #include <linux/err.h>
> > > +#include <linux/extcon.h>
> > >  #include <linux/module.h>
> > >  #include <linux/slab.h>
> > >  #include <linux/platform_device.h>
> > >  #include <linux/power_supply.h>
> > >  #include <linux/mfd/max8997.h>
> > >  #include <linux/mfd/max8997-private.h>
> > > +#include <linux/regulator/consumer.h>
> > >
> > >  /* MAX8997_REG_STATUS4 */
> > >  #define DCINOK_SHIFT		1
> > > @@ -31,6 +33,10 @@ struct charger_data {
> > >  	struct device *dev;
> > >  	struct max8997_dev *iodev;
> > >  	struct power_supply *battery;
> > > +	struct regulator *reg;
> > > +	struct extcon_dev *edev;
> > > +	struct notifier_block extcon_nb;
> > > +	struct work_struct extcon_work;
> > >  };
> > >
> > >  static enum power_supply_property max8997_battery_props[] = {
> > > @@ -88,6 +94,67 @@ static int max8997_battery_get_property(struct power_supply *psy,
> > >  	return 0;
> > >  }
> > >
> > > +static void max8997_battery_extcon_evt_stop_work(void *data)
> > > +{
> > > +	struct charger_data *charger = data;
> > > +
> > > +	cancel_work_sync(&charger->extcon_work);
> > > +}
> > > +
> > > +static void max8997_battery_extcon_evt_worker(struct work_struct *work)
> > > +{
> > > +	struct charger_data *charger =
> > > +	    container_of(work, struct charger_data, extcon_work);
> > > +	struct extcon_dev *edev = charger->edev;
> > > +	int current_limit, ret;
> > > +
> > > +	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
> > > +		dev_dbg(charger->dev, "USB SDP charger is connected\n");
> > > +		current_limit = 450000;
> > > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
> > > +		dev_dbg(charger->dev, "USB DCP charger is connected\n");
> > > +		current_limit = 650000;
> > > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {
> > > +		dev_dbg(charger->dev, "USB FAST charger is connected\n");
> > > +		current_limit = 650000;
> > > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) {
> > > +		dev_dbg(charger->dev, "USB SLOW charger is connected\n");
> > > +		current_limit = 650000;
> > > +	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
> > > +		dev_dbg(charger->dev, "USB CDP charger is connected\n");
> > > +		current_limit = 650000;
> > > +	} else {
> > > +		dev_dbg(charger->dev, "USB charger is diconnected\n");
> > > +		current_limit = -1;
> > > +	}
> > > +
> > > +	if (current_limit > 0) {
> > > +		ret = regulator_set_current_limit(charger->reg, current_limit, current_limit);
> > > +		if (ret) {
> > > +			dev_err(charger->dev, "failed to set current limit: %d\n", ret);
> > > +			goto regulator_disable;  
> > 
> > Unusual error path... if regulator was not enabled before and
> > regulator_set_current_limit() failed, you disable the regulator? Why?
> > Wasn't it already disabled?
> 
> Because I thought you asked me to in v1 of this patch:
> > Failure of setting the current should rather disable the charging.
> 
> I probably misunderstood you comment then. So I guess it should just
> return?

Yes, I was not specific enough. In v1 you enabled the charging even in
case of regulator_set_current_limit() error. Instead, the charging
should not be enabled, so just return here with error.

Best regards,
Krzysztof
diff mbox series

Patch

diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 172e116ac1ce..70ffcef12e3e 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -44,6 +44,8 @@  static struct max8997_muic_irq muic_irqs[] = {
 	{ MAX8997_MUICIRQ_ChgDetRun,	"muic-CHGDETRUN" },
 	{ MAX8997_MUICIRQ_ChgTyp,	"muic-CHGTYP" },
 	{ MAX8997_MUICIRQ_OVP,		"muic-OVP" },
+	{ MAX8997_PMICIRQ_CHGINS,	"pmic-CHGINS" },
+	{ MAX8997_PMICIRQ_CHGRM,	"pmic-CHGRM" },
 };
 
 /* Define supported cable type */
@@ -538,6 +540,9 @@  static void max8997_muic_irq_work(struct work_struct *work)
 	case MAX8997_MUICIRQ_DCDTmr:
 	case MAX8997_MUICIRQ_ChgDetRun:
 	case MAX8997_MUICIRQ_ChgTyp:
+	case MAX8997_PMICIRQ_CHGINS:
+	case MAX8997_PMICIRQ_CHGRM:
+
 		/* Handle charger cable */
 		ret = max8997_muic_chg_handler(info);
 		break;