Loading Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt +16 −6 Original line number Diff line number Diff line Loading @@ -13,12 +13,15 @@ Required Properties: Optional Properties: - interrupts This indicates the IRQ number of the GPIO connected to the STAT pin. - interrupts This indicates the IRQ numbers of the GPIOs connected to the STAT and usb-id pins. - interrupt-names The irq names should be smb1360_stat_irq and smb1360_usb_id_irq.The stat irq is mandatory and usb_id irq is optional. - pinctrl-names: The state name of the pin configuration. Only support: "default". - pinctrl-0: The phandle of the pin configuration node in pinctrl for smb_int_pin. - pinctrl-0: The phandles of the pin configuration node in pinctrl for smb_int_pin and usb-id pin. For details of pinctrl properties, please refer to: "Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt" - qcom,float-voltage-mv Float Voltage in mV - the maximum voltage up to which Loading Loading @@ -177,6 +180,8 @@ Optional Properties: Please go through the documentation for PMIC gpio configuration details: Documentation/devicetree/bindings/gpio/qpnp-pin.txt - qcom,usb-id-gpio GPIO for usb-id detection.This property is mandatory if usb-id irq is specified. - qcom,parallel-charging-enabled: A bool property which enables SMB1360 to operate in the parallel mode. SMB1360 acts as the primary charger. Loading @@ -192,9 +197,13 @@ Example: compatible = "qcom,smb1360-chg-fg"; reg = <0x1b>; interrupt-parent = <&spmi_bus>; interrupts = <0x00 0xcd 0>; interrupts = <0x00 0xcd 0>, <0 0xc3 0 3>; interrupt-names = "smb1360_stat_irq", "smb1360_usb_id_irq"; pinctrl-names = "default"; pinctrl-0 = <&smb_int_default>; pinctrl-0 = <&smb_int_default>, <&usb_id_default>; /* battery-profile selection properties */ qcom,batt-profile-select; Loading Loading @@ -242,5 +251,6 @@ Example: qcom,otg-fet-present; qcom,otg-fet-enable-gpio = <&pm8916_gpios 3 0>; qcom,usb-id-gpio = <&pm8916_gpios 4 0>; }; }; drivers/power/supply/qcom/smb1360-charger-fg.c +81 −3 Original line number Diff line number Diff line /* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2015, 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -31,6 +31,7 @@ #include <linux/qpnp/qpnp-adc.h> #include <linux/completion.h> #include <linux/pm_wakeup.h> #include <linux/of_irq.h> #define _SMB1360_MASK(BITS, POS) \ ((unsigned char)(((1 << (BITS)) - 1) << (POS))) Loading Loading @@ -405,6 +406,7 @@ struct smb1360_chip { bool otg_fet_present; bool fet_gain_enabled; int otg_fet_enable_gpio; int usb_id_gpio; /* status tracking */ int voltage_now; Loading Loading @@ -466,6 +468,7 @@ struct smb1360_chip { int cold_hysteresis; int hot_hysteresis; struct extcon_dev *extcon; int usb_id_irq; }; static int chg_time[] = { Loading Loading @@ -2885,6 +2888,28 @@ static irqreturn_t smb1360_stat_handler(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t smb1360_usb_id_irq_handler(int irq, void *dev_id) { struct smb1360_chip *chip = dev_id; int rc = 0; bool id_state; id_state = gpio_get_value(chip->usb_id_gpio); rc = smb1360_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT, !id_state ? CMD_OTG_EN_BIT : 0); if (rc) { pr_err("Couldn't enable OTG mode rc=%d\n", rc); return IRQ_HANDLED; } extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST, !id_state ? true : false); pr_debug("usb_id_irq triggered, id_state = %d\n", id_state); return IRQ_HANDLED; } static int show_irq_count(struct seq_file *m, void *data) { int i, j, total = 0; Loading Loading @@ -3421,6 +3446,10 @@ static int smb1360_regulator_init(struct smb1360_chip *chip) int rc = 0; struct regulator_config cfg = {}; /* OTG is enabled by SMB1360 if usb-id config is defined */ if (chip->usb_id_gpio > 0 && chip->usb_id_irq > 0) return 0; chip->otg_vreg.rdesc.owner = THIS_MODULE; chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE; chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops; Loading Loading @@ -3557,6 +3586,7 @@ static int determine_initial_status(struct smb1360_chip *chip) { int rc; u8 reg = 0; bool id_state; /* * It is okay to read the IRQ status as the irq's are Loading Loading @@ -3621,6 +3651,25 @@ static int determine_initial_status(struct smb1360_chip *chip) else extcon_set_cable_state_(chip->extcon, EXTCON_USB, true); pr_debug("usb %s at boot\n", chip->usb_present ? "present" : "absent"); /*check otg presence and notify*/ if (chip->usb_id_gpio != -EINVAL) { id_state = gpio_get_value(chip->usb_id_gpio); /* usb-id is low, enable OTG */ if (!id_state) { rc = smb1360_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT, CMD_OTG_EN_BIT); if (rc) { pr_err("Couldn't enable OTG mode rc=%d\n", rc); return rc; } extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST, true); pr_debug("OTG enabled at boot\n"); } } power_supply_changed(chip->usb_psy); return 0; } Loading Loading @@ -4752,6 +4801,11 @@ static int smb_parse_dt(struct smb1360_chip *chip) return rc; } } chip->usb_id_gpio = -EINVAL; if (of_find_property(node, "qcom,usb-id-gpio", NULL)) { chip->usb_id_gpio = of_get_named_gpio(node, "qcom,usb-id-gpio", 0); } chip->pulsed_irq = of_property_read_bool(node, "qcom,stat-pulsed-irq"); Loading Loading @@ -5073,6 +5127,28 @@ static int smb1360_probe(struct i2c_client *client, enable_irq_wake(client->irq); } chip->usb_id_irq = of_irq_get_byname(chip->dev->of_node, "smb1360_usb_id_irq"); if (chip->usb_id_irq > 0) { if (chip->usb_id_gpio == -EINVAL) { pr_err("usb-id gpio not defined\n"); } else { rc = devm_request_threaded_irq(&client->dev, chip->usb_id_irq, NULL, smb1360_usb_id_irq_handler, IRQF_ONESHOT | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "smb1360_usb_id_irq", chip); if (rc < 0) { dev_err(&client->dev, "usb-id request_irq for irq=%d failed rc = %d\n", chip->usb_id_irq, rc); goto unregister_batt_psy; } enable_irq_wake(chip->usb_id_irq); } } chip->debug_root = debugfs_create_dir("smb1360", NULL); if (!chip->debug_root) dev_err(chip->dev, "Couldn't create debug dir\n"); Loading Loading @@ -5201,6 +5277,7 @@ static int smb1360_probe(struct i2c_client *client, unregister_batt_psy: power_supply_unregister(chip->batt_psy); fail_hw_init: if (chip->otg_vreg.rdev) regulator_unregister(chip->otg_vreg.rdev); destroy_mutex: power_supply_unregister(chip->usb_psy); Loading @@ -5218,8 +5295,9 @@ static int smb1360_probe(struct i2c_client *client, static int smb1360_remove(struct i2c_client *client) { struct smb1360_chip *chip = i2c_get_clientdata(client); if (chip->otg_vreg.rdev) regulator_unregister(chip->otg_vreg.rdev); power_supply_unregister(chip->usb_psy); power_supply_unregister(chip->batt_psy); wakeup_source_trash(&chip->smb1360_ws.source); Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt +16 −6 Original line number Diff line number Diff line Loading @@ -13,12 +13,15 @@ Required Properties: Optional Properties: - interrupts This indicates the IRQ number of the GPIO connected to the STAT pin. - interrupts This indicates the IRQ numbers of the GPIOs connected to the STAT and usb-id pins. - interrupt-names The irq names should be smb1360_stat_irq and smb1360_usb_id_irq.The stat irq is mandatory and usb_id irq is optional. - pinctrl-names: The state name of the pin configuration. Only support: "default". - pinctrl-0: The phandle of the pin configuration node in pinctrl for smb_int_pin. - pinctrl-0: The phandles of the pin configuration node in pinctrl for smb_int_pin and usb-id pin. For details of pinctrl properties, please refer to: "Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt" - qcom,float-voltage-mv Float Voltage in mV - the maximum voltage up to which Loading Loading @@ -177,6 +180,8 @@ Optional Properties: Please go through the documentation for PMIC gpio configuration details: Documentation/devicetree/bindings/gpio/qpnp-pin.txt - qcom,usb-id-gpio GPIO for usb-id detection.This property is mandatory if usb-id irq is specified. - qcom,parallel-charging-enabled: A bool property which enables SMB1360 to operate in the parallel mode. SMB1360 acts as the primary charger. Loading @@ -192,9 +197,13 @@ Example: compatible = "qcom,smb1360-chg-fg"; reg = <0x1b>; interrupt-parent = <&spmi_bus>; interrupts = <0x00 0xcd 0>; interrupts = <0x00 0xcd 0>, <0 0xc3 0 3>; interrupt-names = "smb1360_stat_irq", "smb1360_usb_id_irq"; pinctrl-names = "default"; pinctrl-0 = <&smb_int_default>; pinctrl-0 = <&smb_int_default>, <&usb_id_default>; /* battery-profile selection properties */ qcom,batt-profile-select; Loading Loading @@ -242,5 +251,6 @@ Example: qcom,otg-fet-present; qcom,otg-fet-enable-gpio = <&pm8916_gpios 3 0>; qcom,usb-id-gpio = <&pm8916_gpios 4 0>; }; };
drivers/power/supply/qcom/smb1360-charger-fg.c +81 −3 Original line number Diff line number Diff line /* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2015, 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -31,6 +31,7 @@ #include <linux/qpnp/qpnp-adc.h> #include <linux/completion.h> #include <linux/pm_wakeup.h> #include <linux/of_irq.h> #define _SMB1360_MASK(BITS, POS) \ ((unsigned char)(((1 << (BITS)) - 1) << (POS))) Loading Loading @@ -405,6 +406,7 @@ struct smb1360_chip { bool otg_fet_present; bool fet_gain_enabled; int otg_fet_enable_gpio; int usb_id_gpio; /* status tracking */ int voltage_now; Loading Loading @@ -466,6 +468,7 @@ struct smb1360_chip { int cold_hysteresis; int hot_hysteresis; struct extcon_dev *extcon; int usb_id_irq; }; static int chg_time[] = { Loading Loading @@ -2885,6 +2888,28 @@ static irqreturn_t smb1360_stat_handler(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t smb1360_usb_id_irq_handler(int irq, void *dev_id) { struct smb1360_chip *chip = dev_id; int rc = 0; bool id_state; id_state = gpio_get_value(chip->usb_id_gpio); rc = smb1360_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT, !id_state ? CMD_OTG_EN_BIT : 0); if (rc) { pr_err("Couldn't enable OTG mode rc=%d\n", rc); return IRQ_HANDLED; } extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST, !id_state ? true : false); pr_debug("usb_id_irq triggered, id_state = %d\n", id_state); return IRQ_HANDLED; } static int show_irq_count(struct seq_file *m, void *data) { int i, j, total = 0; Loading Loading @@ -3421,6 +3446,10 @@ static int smb1360_regulator_init(struct smb1360_chip *chip) int rc = 0; struct regulator_config cfg = {}; /* OTG is enabled by SMB1360 if usb-id config is defined */ if (chip->usb_id_gpio > 0 && chip->usb_id_irq > 0) return 0; chip->otg_vreg.rdesc.owner = THIS_MODULE; chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE; chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops; Loading Loading @@ -3557,6 +3586,7 @@ static int determine_initial_status(struct smb1360_chip *chip) { int rc; u8 reg = 0; bool id_state; /* * It is okay to read the IRQ status as the irq's are Loading Loading @@ -3621,6 +3651,25 @@ static int determine_initial_status(struct smb1360_chip *chip) else extcon_set_cable_state_(chip->extcon, EXTCON_USB, true); pr_debug("usb %s at boot\n", chip->usb_present ? "present" : "absent"); /*check otg presence and notify*/ if (chip->usb_id_gpio != -EINVAL) { id_state = gpio_get_value(chip->usb_id_gpio); /* usb-id is low, enable OTG */ if (!id_state) { rc = smb1360_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT, CMD_OTG_EN_BIT); if (rc) { pr_err("Couldn't enable OTG mode rc=%d\n", rc); return rc; } extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST, true); pr_debug("OTG enabled at boot\n"); } } power_supply_changed(chip->usb_psy); return 0; } Loading Loading @@ -4752,6 +4801,11 @@ static int smb_parse_dt(struct smb1360_chip *chip) return rc; } } chip->usb_id_gpio = -EINVAL; if (of_find_property(node, "qcom,usb-id-gpio", NULL)) { chip->usb_id_gpio = of_get_named_gpio(node, "qcom,usb-id-gpio", 0); } chip->pulsed_irq = of_property_read_bool(node, "qcom,stat-pulsed-irq"); Loading Loading @@ -5073,6 +5127,28 @@ static int smb1360_probe(struct i2c_client *client, enable_irq_wake(client->irq); } chip->usb_id_irq = of_irq_get_byname(chip->dev->of_node, "smb1360_usb_id_irq"); if (chip->usb_id_irq > 0) { if (chip->usb_id_gpio == -EINVAL) { pr_err("usb-id gpio not defined\n"); } else { rc = devm_request_threaded_irq(&client->dev, chip->usb_id_irq, NULL, smb1360_usb_id_irq_handler, IRQF_ONESHOT | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "smb1360_usb_id_irq", chip); if (rc < 0) { dev_err(&client->dev, "usb-id request_irq for irq=%d failed rc = %d\n", chip->usb_id_irq, rc); goto unregister_batt_psy; } enable_irq_wake(chip->usb_id_irq); } } chip->debug_root = debugfs_create_dir("smb1360", NULL); if (!chip->debug_root) dev_err(chip->dev, "Couldn't create debug dir\n"); Loading Loading @@ -5201,6 +5277,7 @@ static int smb1360_probe(struct i2c_client *client, unregister_batt_psy: power_supply_unregister(chip->batt_psy); fail_hw_init: if (chip->otg_vreg.rdev) regulator_unregister(chip->otg_vreg.rdev); destroy_mutex: power_supply_unregister(chip->usb_psy); Loading @@ -5218,8 +5295,9 @@ static int smb1360_probe(struct i2c_client *client, static int smb1360_remove(struct i2c_client *client) { struct smb1360_chip *chip = i2c_get_clientdata(client); if (chip->otg_vreg.rdev) regulator_unregister(chip->otg_vreg.rdev); power_supply_unregister(chip->usb_psy); power_supply_unregister(chip->batt_psy); wakeup_source_trash(&chip->smb1360_ws.source); Loading