power: smb1351-charger: Add support for OTG IRQ

SMB1351 does not have a USB_ID detection logic. Add support
for handling the ID detection over a dedicated GPIO.

Change-Id: Iadaf9344ab00bec1b173516a5004187e98e89302
Signed-off-by: Kavya Nunna <knunna@codeaurora.org>
This commit is contained in:
Kavya Nunna 2020-12-24 17:44:47 +05:30
commit dfc409f9b1

View file

@ -11,12 +11,15 @@
#include <linux/extcon-provider.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/power_supply.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/pinctrl/consumer.h>
@ -493,6 +496,8 @@ struct smb1351_charger {
struct regulator *dpdm_reg;
enum power_supply_type charger_type;
bool otg_enable;
int usb_id_gpio;
int usb_id_irq;
};
struct smb_irq_info {
@ -2087,6 +2092,27 @@ static irqreturn_t smb1351_chg_stat_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
irqreturn_t smb1351_usb_id_irq_handler(int irq, void *data)
{
struct smb1351_charger *chip = data;
bool id_state;
int rc = 0;
id_state = gpio_get_value(chip->usb_id_gpio);
pr_debug("id_state=%d\n", id_state);
rc = smb1351_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT,
id_state ? 0 : CMD_OTG_EN_BIT);
if (rc < 0)
pr_err("Failed to %s OTG\n", id_state ? "disable" : "enable");
else
pr_debug("SMB1351 OTG %s\n", id_state ? "disabled" : "enabled");
extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST, !id_state);
return IRQ_HANDLED;
}
#define LAST_CNFG_REG 0x16
static int show_cnfg_regs(struct seq_file *m, void *data)
{
@ -2425,6 +2451,9 @@ static int smb1351_determine_initial_state(struct smb1351_charger *chip)
smb1351_apsd_complete_handler(chip, 1);
}
if (chip->usb_id_gpio > 0)
smb1351_usb_id_irq_handler(0, chip);
return 0;
fail_init_status:
@ -2486,6 +2515,24 @@ static int create_debugfs_entries(struct smb1351_charger *chip)
return 0;
}
static int smb1351_init_otg(struct smb1351_charger *chip)
{
chip->usb_id_gpio = chip->usb_id_irq = -EINVAL;
if (of_find_property(chip->dev->of_node, "qcom,usb-id-gpio", NULL))
chip->usb_id_gpio = of_get_named_gpio(chip->dev->of_node,
"qcom,usb-id-gpio", 0);
chip->usb_id_irq = of_irq_get_byname(chip->dev->of_node,
"smb1351_usb_id_irq");
if (chip->usb_id_irq < 0 || chip->usb_id_gpio < 0)
pr_err("OTG irq (%d) / gpio (%d) not defined\n",
chip->usb_id_irq, chip->usb_id_gpio);
return 0;
}
static int smb1351_main_charger_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -2607,6 +2654,12 @@ static int smb1351_main_charger_probe(struct i2c_client *client,
goto fail_smb1351_hw_init;
}
rc = smb1351_init_otg(chip);
if (rc < 0) {
dev_err(chip->dev, "Couldn't init otg rc=%d\n", rc);
return rc;
}
rc = smb1351_determine_initial_state(chip);
if (rc) {
pr_err("Couldn't determine initial state rc=%d\n", rc);
@ -2627,6 +2680,22 @@ static int smb1351_main_charger_probe(struct i2c_client *client,
enable_irq_wake(client->irq);
}
if (chip->usb_id_irq > 0 && chip->usb_id_gpio > 0) {
rc = devm_request_threaded_irq(chip->dev,
chip->usb_id_irq, NULL,
smb1351_usb_id_irq_handler,
IRQF_ONESHOT
| IRQF_TRIGGER_FALLING
| IRQF_TRIGGER_RISING,
"smb1351_usb_id_irq", chip);
if (rc < 0) {
pr_err("Failed to register id-irq rc=%d\n", rc);
return rc;
}
enable_irq_wake(chip->usb_id_irq);
}
create_debugfs_entries(chip);
dump_regs(chip);