summaryrefslogtreecommitdiffstats
path: root/drivers/extcon/extcon-intel-cht-wc.c
diff options
context:
space:
mode:
authorYauhen Kharuzhy <jekhor@gmail.com>2019-03-03 15:16:13 -0500
committerChanwoo Choi <cw00.choi@samsung.com>2019-04-04 21:21:41 -0400
commita72a1be0de71b3bdab3d8b2e708267f32ea33ee2 (patch)
treea3db62d00170ffa816290bd9704322ccfea79086 /drivers/extcon/extcon-intel-cht-wc.c
parent3137301b6d970219706d887eb6bdcabbf54f1f3b (diff)
extcon: intel-cht-wc: Enable external charger
In some configuration external charger "#charge enable" signal is connected to PMIC. Enable it at device probing to allow charging. Save CHGRCTRL0 and CHGDISCTR registers at driver probing and restore them at driver unbind to re-enable hardware charging control if it was enabled before. Tested at Lenovo Yoga Book (YB1-X91L). Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Tested-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Diffstat (limited to 'drivers/extcon/extcon-intel-cht-wc.c')
-rw-r--r--drivers/extcon/extcon-intel-cht-wc.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/extcon/extcon-intel-cht-wc.c b/drivers/extcon/extcon-intel-cht-wc.c
index 8d20e913536f..53b28ecc4ad1 100644
--- a/drivers/extcon/extcon-intel-cht-wc.c
+++ b/drivers/extcon/extcon-intel-cht-wc.c
@@ -56,6 +56,13 @@
56#define CHT_WC_USBSRC_TYPE_OTHER 8 56#define CHT_WC_USBSRC_TYPE_OTHER 8
57#define CHT_WC_USBSRC_TYPE_DCP_EXTPHY 9 57#define CHT_WC_USBSRC_TYPE_DCP_EXTPHY 9
58 58
59#define CHT_WC_CHGDISCTRL 0x5e2f
60#define CHT_WC_CHGDISCTRL_OUT BIT(0)
61/* 0 - open drain, 1 - regular push-pull output */
62#define CHT_WC_CHGDISCTRL_DRV BIT(4)
63/* 0 - pin is controlled by SW, 1 - by HW */
64#define CHT_WC_CHGDISCTRL_FN BIT(6)
65
59#define CHT_WC_PWRSRC_IRQ 0x6e03 66#define CHT_WC_PWRSRC_IRQ 0x6e03
60#define CHT_WC_PWRSRC_IRQ_MASK 0x6e0f 67#define CHT_WC_PWRSRC_IRQ_MASK 0x6e0f
61#define CHT_WC_PWRSRC_STS 0x6e1e 68#define CHT_WC_PWRSRC_STS 0x6e1e
@@ -218,6 +225,18 @@ static void cht_wc_extcon_set_otgmode(struct cht_wc_extcon_data *ext,
218 dev_err(ext->dev, "Error updating CHGRCTRL1 reg: %d\n", ret); 225 dev_err(ext->dev, "Error updating CHGRCTRL1 reg: %d\n", ret);
219} 226}
220 227
228static void cht_wc_extcon_enable_charging(struct cht_wc_extcon_data *ext,
229 bool enable)
230{
231 unsigned int val = enable ? 0 : CHT_WC_CHGDISCTRL_OUT;
232 int ret;
233
234 ret = regmap_update_bits(ext->regmap, CHT_WC_CHGDISCTRL,
235 CHT_WC_CHGDISCTRL_OUT, val);
236 if (ret)
237 dev_err(ext->dev, "Error updating CHGDISCTRL reg: %d\n", ret);
238}
239
221/* Small helper to sync EXTCON_CHG_USB_SDP and EXTCON_USB state */ 240/* Small helper to sync EXTCON_CHG_USB_SDP and EXTCON_USB state */
222static void cht_wc_extcon_set_state(struct cht_wc_extcon_data *ext, 241static void cht_wc_extcon_set_state(struct cht_wc_extcon_data *ext,
223 unsigned int cable, bool state) 242 unsigned int cable, bool state)
@@ -242,6 +261,7 @@ static void cht_wc_extcon_pwrsrc_event(struct cht_wc_extcon_data *ext)
242 261
243 id = cht_wc_extcon_get_id(ext, pwrsrc_sts); 262 id = cht_wc_extcon_get_id(ext, pwrsrc_sts);
244 if (id == USB_ID_GND) { 263 if (id == USB_ID_GND) {
264 cht_wc_extcon_enable_charging(ext, false);
245 cht_wc_extcon_set_otgmode(ext, true); 265 cht_wc_extcon_set_otgmode(ext, true);
246 266
247 /* The 5v boost causes a false VBUS / SDP detect, skip */ 267 /* The 5v boost causes a false VBUS / SDP detect, skip */
@@ -249,6 +269,7 @@ static void cht_wc_extcon_pwrsrc_event(struct cht_wc_extcon_data *ext)
249 } 269 }
250 270
251 cht_wc_extcon_set_otgmode(ext, false); 271 cht_wc_extcon_set_otgmode(ext, false);
272 cht_wc_extcon_enable_charging(ext, true);
252 273
253 /* Plugged into a host/charger or not connected? */ 274 /* Plugged into a host/charger or not connected? */
254 if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) { 275 if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) {
@@ -302,6 +323,14 @@ static int cht_wc_extcon_sw_control(struct cht_wc_extcon_data *ext, bool enable)
302{ 323{
303 int ret, mask, val; 324 int ret, mask, val;
304 325
326 val = enable ? 0 : CHT_WC_CHGDISCTRL_FN;
327 ret = regmap_update_bits(ext->regmap, CHT_WC_CHGDISCTRL,
328 CHT_WC_CHGDISCTRL_FN, val);
329 if (ret)
330 dev_err(ext->dev,
331 "Error setting sw control for CHGDIS pin: %d\n",
332 ret);
333
305 mask = CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF; 334 mask = CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF;
306 val = enable ? mask : 0; 335 val = enable ? mask : 0;
307 ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0, mask, val); 336 ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0, mask, val);
@@ -353,7 +382,10 @@ static int cht_wc_extcon_probe(struct platform_device *pdev)
353 /* Enable sw control */ 382 /* Enable sw control */
354 ret = cht_wc_extcon_sw_control(ext, true); 383 ret = cht_wc_extcon_sw_control(ext, true);
355 if (ret) 384 if (ret)
356 return ret; 385 goto disable_sw_control;
386
387 /* Disable charging by external battery charger */
388 cht_wc_extcon_enable_charging(ext, false);
357 389
358 /* Register extcon device */ 390 /* Register extcon device */
359 ret = devm_extcon_dev_register(ext->dev, ext->edev); 391 ret = devm_extcon_dev_register(ext->dev, ext->edev);