Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Yauhen Kharuzhy and committed by
Chanwoo Choi
a72a1be0 3137301b

+33 -1
+33 -1
drivers/extcon/extcon-intel-cht-wc.c
··· 56 56 #define CHT_WC_USBSRC_TYPE_OTHER 8 57 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 66 #define CHT_WC_PWRSRC_IRQ 0x6e03 60 67 #define CHT_WC_PWRSRC_IRQ_MASK 0x6e0f 61 68 #define CHT_WC_PWRSRC_STS 0x6e1e ··· 225 218 dev_err(ext->dev, "Error updating CHGRCTRL1 reg: %d\n", ret); 226 219 } 227 220 221 + static void cht_wc_extcon_enable_charging(struct cht_wc_extcon_data *ext, 222 + bool enable) 223 + { 224 + unsigned int val = enable ? 0 : CHT_WC_CHGDISCTRL_OUT; 225 + int ret; 226 + 227 + ret = regmap_update_bits(ext->regmap, CHT_WC_CHGDISCTRL, 228 + CHT_WC_CHGDISCTRL_OUT, val); 229 + if (ret) 230 + dev_err(ext->dev, "Error updating CHGDISCTRL reg: %d\n", ret); 231 + } 232 + 228 233 /* Small helper to sync EXTCON_CHG_USB_SDP and EXTCON_USB state */ 229 234 static void cht_wc_extcon_set_state(struct cht_wc_extcon_data *ext, 230 235 unsigned int cable, bool state) ··· 261 242 262 243 id = cht_wc_extcon_get_id(ext, pwrsrc_sts); 263 244 if (id == USB_ID_GND) { 245 + cht_wc_extcon_enable_charging(ext, false); 264 246 cht_wc_extcon_set_otgmode(ext, true); 265 247 266 248 /* The 5v boost causes a false VBUS / SDP detect, skip */ ··· 269 249 } 270 250 271 251 cht_wc_extcon_set_otgmode(ext, false); 252 + cht_wc_extcon_enable_charging(ext, true); 272 253 273 254 /* Plugged into a host/charger or not connected? */ 274 255 if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) { ··· 323 302 { 324 303 int ret, mask, val; 325 304 305 + val = enable ? 0 : CHT_WC_CHGDISCTRL_FN; 306 + ret = regmap_update_bits(ext->regmap, CHT_WC_CHGDISCTRL, 307 + CHT_WC_CHGDISCTRL_FN, val); 308 + if (ret) 309 + dev_err(ext->dev, 310 + "Error setting sw control for CHGDIS pin: %d\n", 311 + ret); 312 + 326 313 mask = CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF; 327 314 val = enable ? mask : 0; 328 315 ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0, mask, val); ··· 382 353 /* Enable sw control */ 383 354 ret = cht_wc_extcon_sw_control(ext, true); 384 355 if (ret) 385 - return ret; 356 + goto disable_sw_control; 357 + 358 + /* Disable charging by external battery charger */ 359 + cht_wc_extcon_enable_charging(ext, false); 386 360 387 361 /* Register extcon device */ 388 362 ret = devm_extcon_dev_register(ext->dev, ext->edev);