mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
power: rk817_charger: support otg device get power from DC
Change-Id: I9490dc97edaf64b9d3264c0a8a0988ff1ea9d25f Signed-off-by: Shengfei Xu <xsf@rock-chips.com>
This commit is contained in:
@@ -48,7 +48,7 @@ module_param_named(dbg_level, dbg_enable, int, 0644);
|
||||
|
||||
#define DISABLE 0x00
|
||||
#define ENABLE 0x01
|
||||
#define OTG_SLP_ENABLE 0x03
|
||||
#define OTG_SLP_ENABLE 0x01
|
||||
#define OTG_SLP_DISABLE 0x00
|
||||
#define OTG_ENABLE 0x11
|
||||
#define OTG_DISABLE 0x10
|
||||
@@ -192,6 +192,11 @@ enum charger_t {
|
||||
DC_TYPE_NONE_CHARGER,
|
||||
};
|
||||
|
||||
enum charger_state {
|
||||
OFFLINE = 0,
|
||||
ONLINE
|
||||
};
|
||||
|
||||
enum rk817_charge_fields {
|
||||
BOOST_EN, OTG_EN, OTG_SLP_EN, CHRG_CLK_SEL,
|
||||
CHRG_EN, CHRG_VOL_SEL, CHRG_CT_EN, CHRG_CUR_SEL,
|
||||
@@ -216,7 +221,7 @@ static const struct reg_field rk817_charge_reg_fields[] = {
|
||||
[SOC_REG2] = REG_FIELD(0x9C, 0, 7),
|
||||
[BOOST_EN] = REG_FIELD(0xB4, 1, 5),
|
||||
[OTG_EN] = REG_FIELD(0xB4, 2, 6),
|
||||
[OTG_SLP_EN] = REG_FIELD(0xB5, 5, 6),
|
||||
[OTG_SLP_EN] = REG_FIELD(0xB5, 6, 6),
|
||||
[CHRG_EN] = REG_FIELD(0xE4, 7, 7),
|
||||
[CHRG_VOL_SEL] = REG_FIELD(0xE4, 4, 6),
|
||||
[CHRG_CT_EN] = REG_FIELD(0xE4, 3, 3),
|
||||
@@ -305,6 +310,7 @@ struct rk817_charger {
|
||||
unsigned int bc_event;
|
||||
enum charger_t usb_charger;
|
||||
enum charger_t dc_charger;
|
||||
struct regulator *otg5v_rdev;
|
||||
u8 ac_in;
|
||||
u8 usb_in;
|
||||
u8 otg_in;
|
||||
@@ -356,7 +362,7 @@ static int rk817_charge_ac_get_property(struct power_supply *psy,
|
||||
else
|
||||
val->intval = (charge->ac_in | charge->dc_in);
|
||||
|
||||
DBG("report online: %d\n", val->intval);
|
||||
DBG("ac report online: %d\n", val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (charge->pdata->virtual_power)
|
||||
@@ -367,10 +373,10 @@ static int rk817_charge_ac_get_property(struct power_supply *psy,
|
||||
DBG("report prop: %d\n", val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
|
||||
val->intval = charge->max_chrg_voltage;
|
||||
val->intval = charge->max_chrg_voltage * 1000; /* uV */
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
val->intval = charge->max_chrg_current;
|
||||
val->intval = charge->max_chrg_current * 1000; /* uA */
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@@ -394,7 +400,7 @@ static int rk817_charge_usb_get_property(struct power_supply *psy,
|
||||
else
|
||||
val->intval = charge->usb_in;
|
||||
|
||||
DBG("report online: %d\n", val->intval);
|
||||
DBG("usb report online: %d\n", val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (charge->pdata->virtual_power)
|
||||
@@ -478,8 +484,7 @@ static int rk817_charge_field_write(struct rk817_charger *charge,
|
||||
|
||||
static int rk817_charge_get_otg_state(struct rk817_charger *charge)
|
||||
{
|
||||
return ((rk817_charge_field_read(charge, OTG_EN) &
|
||||
OTG_MODE) == OTG_MODE_ON);
|
||||
return regulator_is_enabled(charge->otg5v_rdev);
|
||||
}
|
||||
|
||||
static void rk817_charge_boost_disable(struct rk817_charger *charge)
|
||||
@@ -494,12 +499,30 @@ static void rk817_charge_boost_enable(struct rk817_charger *charge)
|
||||
|
||||
static void rk817_charge_otg_disable(struct rk817_charger *charge)
|
||||
{
|
||||
rk817_charge_field_write(charge, OTG_EN, OTG_DISABLE);
|
||||
int ret;
|
||||
|
||||
ret = regulator_disable(charge->otg5v_rdev);
|
||||
|
||||
if (ret) {
|
||||
DBG("disable otg5v failed:%d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void rk817_charge_otg_enable(struct rk817_charger *charge)
|
||||
{
|
||||
rk817_charge_field_write(charge, OTG_EN, OTG_ENABLE);
|
||||
int ret;
|
||||
|
||||
ret = regulator_enable(charge->otg5v_rdev);
|
||||
|
||||
if (ret) {
|
||||
DBG("enable otg5v failed:%d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@@ -754,6 +777,11 @@ static int rk817_charge_get_dsoc(struct rk817_charger *charge)
|
||||
return soc_save / 1000;
|
||||
}
|
||||
|
||||
static void rk817_charge_set_otg_in(struct rk817_charger *charge, int online)
|
||||
{
|
||||
charge->otg_in = online;
|
||||
}
|
||||
|
||||
static void rk817_charge_set_chrg_param(struct rk817_charger *charge,
|
||||
enum charger_t charger)
|
||||
{
|
||||
@@ -830,7 +858,6 @@ static void rk817_charge_set_otg_state(struct rk817_charger *charge, int state)
|
||||
if (charge->otg_in) {
|
||||
DBG("otg5v is on yet, ignore..\n");
|
||||
} else {
|
||||
charge->otg_in = 1;
|
||||
|
||||
if (!rk817_charge_get_otg_state(charge)) {
|
||||
rk817_charge_otg_enable(charge);
|
||||
@@ -849,7 +876,6 @@ static void rk817_charge_set_otg_state(struct rk817_charger *charge, int state)
|
||||
if (!charge->otg_in) {
|
||||
DBG("otg5v is off yet, ignore..\n");
|
||||
} else {
|
||||
charge->otg_in = 0;
|
||||
|
||||
if (rk817_charge_get_otg_state(charge)) {
|
||||
rk817_charge_otg_disable(charge);
|
||||
@@ -907,13 +933,20 @@ static void rk817_charge_dc_det_worker(struct work_struct *work)
|
||||
if (charger == DC_TYPE_DC_CHARGER) {
|
||||
DBG("detect dc charger in..\n");
|
||||
rk817_charge_set_chrg_param(charge, DC_TYPE_DC_CHARGER);
|
||||
rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF);
|
||||
/* check otg supply */
|
||||
if (charge->otg_in && charge->pdata->power_dc2otg) {
|
||||
DBG("otg power from dc adapter\n");
|
||||
rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF);
|
||||
}
|
||||
|
||||
rk817_charge_boost_disable(charge);
|
||||
} else {
|
||||
DBG("detect dc charger out..\n");
|
||||
rk817_charge_set_chrg_param(charge, DC_TYPE_NONE_CHARGER);
|
||||
rk817_charge_boost_enable(charge);
|
||||
rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF);
|
||||
/* check otg supply, power on anyway */
|
||||
if (charge->otg_in)
|
||||
rk817_charge_set_otg_state(charge, USB_OTG_POWER_ON);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,16 +1013,22 @@ static void rk817_charge_host_evt_worker(struct work_struct *work)
|
||||
struct rk817_charger, host_work.work);
|
||||
struct extcon_dev *edev = charge->cable_edev;
|
||||
|
||||
/* Determine charger type */
|
||||
/* Determine cable/charger type */
|
||||
if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) > 0) {
|
||||
DBG("receive type-c notifier event: OTG ON...\n");
|
||||
if (charge->dc_in && charge->pdata->power_dc2otg)
|
||||
if (charge->dc_in && charge->pdata->power_dc2otg) {
|
||||
if (charge->otg_in)
|
||||
rk817_charge_set_otg_state(charge,
|
||||
USB_OTG_POWER_OFF);
|
||||
DBG("otg power from dc adapter\n");
|
||||
else
|
||||
} else {
|
||||
rk817_charge_set_otg_state(charge, USB_OTG_POWER_ON);
|
||||
}
|
||||
rk817_charge_set_otg_in(charge, ONLINE);
|
||||
} else if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) == 0) {
|
||||
DBG("receive type-c notifier event: OTG OFF...\n");
|
||||
rk817_charge_set_otg_state(charge, USB_OTG_POWER_OFF);
|
||||
rk817_charge_set_otg_in(charge, OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1002,7 +1041,7 @@ static void rk817_charger_evt_worker(struct work_struct *work)
|
||||
static const char * const event[] = {"UN", "NONE", "USB",
|
||||
"AC", "CDP1.5A"};
|
||||
|
||||
/* Determine charger type */
|
||||
/* Determine cable/charger type */
|
||||
if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0)
|
||||
charger = USB_TYPE_USB_CHARGER;
|
||||
else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0)
|
||||
@@ -1265,7 +1304,10 @@ static void rk817_charge_pre_init(struct rk817_charger *charge)
|
||||
|
||||
rk817_charge_set_chrg_finish_condition(charge);
|
||||
|
||||
rk817_charge_otg_disable(charge);
|
||||
if (rk817_charge_get_otg_state(charge))
|
||||
rk817_charge_otg_disable(charge);
|
||||
rk817_charge_field_write(charge, OTG_EN, OTG_DISABLE);
|
||||
rk817_charge_set_otg_in(charge, OFFLINE);
|
||||
rk817_charge_sys_can_sd_disable(charge);
|
||||
rk817_charge_usb_to_sys_enable(charge);
|
||||
rk817_charge_enable_charge(charge);
|
||||
@@ -1292,6 +1334,19 @@ static void rk817_chage_debug(struct rk817_charger *charge)
|
||||
charge->chrg_term_mode);
|
||||
}
|
||||
|
||||
static int rk817_charge_get_otg5v_regulator(struct rk817_charger *charge)
|
||||
{
|
||||
int ret;
|
||||
|
||||
charge->otg5v_rdev = devm_regulator_get(charge->dev, "otg_switch");
|
||||
if (IS_ERR(charge->otg5v_rdev)) {
|
||||
ret = PTR_ERR(charge->otg5v_rdev);
|
||||
dev_warn(charge->dev, "failed to get otg regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int rk817_charge_parse_dt(struct rk817_charger *charge)
|
||||
{
|
||||
@@ -1555,6 +1610,7 @@ static int rk817_charge_probe(struct platform_device *pdev)
|
||||
dev_err(charge->dev, "charge parse dt failed!\n");
|
||||
return ret;
|
||||
}
|
||||
rk817_charge_get_otg5v_regulator(charge);
|
||||
|
||||
rk817_charge_pre_init(charge);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user