mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
mfd: fusb302: add gpio control vbus discharge
When type-c vbus output power down or disconnect charging input, the type-c vbus voltage discharge to 0V take a long time, during this time residual voltage would affect charge circuit in some platforms(e.g. rk3399-tve1205g board). So we need add fast discharge circuit, then use a gpio control it. Change-Id: I4c8eebc0cf10c6c38c7db9d9d5c71c4f6769e7fc Signed-off-by: Bin Yang <yangbin@rock-chips.com>
This commit is contained in:
@@ -300,6 +300,9 @@ static void fusb_timer_start(struct hrtimer *timer, int ms)
|
||||
static void platform_set_vbus_lvl_enable(struct fusb30x_chip *chip, int vbus_5v,
|
||||
int vbus_other)
|
||||
{
|
||||
bool gpio_vbus_value = 0;
|
||||
|
||||
gpio_vbus_value = gpiod_get_value(chip->gpio_vbus_5v);
|
||||
if (chip->gpio_vbus_5v) {
|
||||
gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_5v);
|
||||
/* Only set state here, don't sync notifier to PMIC */
|
||||
@@ -312,6 +315,12 @@ static void platform_set_vbus_lvl_enable(struct fusb30x_chip *chip, int vbus_5v,
|
||||
|
||||
if (chip->gpio_vbus_other)
|
||||
gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_other);
|
||||
|
||||
if (chip->gpio_discharge && !vbus_5v && gpio_vbus_value) {
|
||||
gpiod_set_value(chip->gpio_discharge, 1);
|
||||
msleep(20);
|
||||
gpiod_set_value(chip->gpio_discharge, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_state(struct fusb30x_chip *chip, enum connection_state state)
|
||||
@@ -786,7 +795,11 @@ static void set_state_unattached(struct fusb30x_chip *chip)
|
||||
memset(&chip->notify, 0, sizeof(struct notify_info));
|
||||
platform_fusb_notify(chip);
|
||||
|
||||
if (chip->gpio_discharge)
|
||||
gpiod_set_value(chip->gpio_discharge, 1);
|
||||
msleep(100);
|
||||
if (chip->gpio_discharge)
|
||||
gpiod_set_value(chip->gpio_discharge, 0);
|
||||
}
|
||||
|
||||
static int tcpm_check_vbus(struct fusb30x_chip *chip)
|
||||
@@ -2278,6 +2291,14 @@ static int fusb_initialize_gpio(struct fusb30x_chip *chip)
|
||||
else
|
||||
gpiod_set_raw_value(chip->gpio_vbus_other, 0);
|
||||
|
||||
chip->gpio_discharge = devm_gpiod_get_optional(chip->dev, "discharge",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(chip->gpio_discharge)) {
|
||||
dev_warn(chip->dev,
|
||||
"Could not get named GPIO for discharge!\n");
|
||||
chip->gpio_discharge = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2503,6 +2524,19 @@ static int fusb30x_remove(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fusb30x_shutdown(struct i2c_client *client)
|
||||
{
|
||||
struct fusb30x_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
if (chip->gpio_vbus_5v)
|
||||
gpiod_set_value(chip->gpio_vbus_5v, 0);
|
||||
if (chip->gpio_discharge) {
|
||||
gpiod_set_value(chip->gpio_discharge, 1);
|
||||
msleep(100);
|
||||
gpiod_set_value(chip->gpio_discharge, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct of_device_id fusb30x_dt_match[] = {
|
||||
{ .compatible = FUSB30X_I2C_DEVICETREE_NAME },
|
||||
{},
|
||||
@@ -2522,6 +2556,7 @@ static struct i2c_driver fusb30x_driver = {
|
||||
},
|
||||
.probe = fusb30x_probe,
|
||||
.remove = fusb30x_remove,
|
||||
.shutdown = fusb30x_shutdown,
|
||||
.id_table = fusb30x_i2c_device_id,
|
||||
};
|
||||
|
||||
|
||||
@@ -378,6 +378,7 @@ struct fusb30x_chip {
|
||||
struct gpio_desc *gpio_vbus_5v;
|
||||
struct gpio_desc *gpio_vbus_other;
|
||||
struct gpio_desc *gpio_int;
|
||||
struct gpio_desc *gpio_discharge;
|
||||
int timer_state;
|
||||
int timer_mux;
|
||||
int port_num;
|
||||
|
||||
Reference in New Issue
Block a user