1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Support for the custom fast charging protocol found on the Lenovo Yoga 4 * Tablet 2 1380F / 1380L models. 5 * 6 * Copyright (C) 2024 Hans de Goede <hansg@kernel.org> 7 */ 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10 #include <linux/delay.h> 11 #include <linux/err.h> 12 #include <linux/errno.h> 13 #include <linux/extcon.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/module.h> 16 #include <linux/notifier.h> 17 #include <linux/pinctrl/consumer.h> 18 #include <linux/pinctrl/machine.h> 19 #include <linux/platform_device.h> 20 #include <linux/serdev.h> 21 #include <linux/time.h> 22 #include <linux/types.h> 23 #include <linux/workqueue.h> 24 #include "serdev_helpers.h" 25 26 #define YT2_1380_FC_PDEV_NAME "lenovo-yoga-tab2-pro-1380-fastcharger" 27 #define YT2_1380_FC_SERDEV_CTRL "serial0" 28 #define YT2_1380_FC_SERDEV_NAME "serial0-0" 29 #define YT2_1380_FC_EXTCON_NAME "i2c-lc824206xa" 30 31 #define YT2_1380_FC_MAX_TRIES 5 32 #define YT2_1380_FC_PIN_SW_DELAY_US (10 * USEC_PER_MSEC) 33 #define YT2_1380_FC_UART_DRAIN_DELAY_US (50 * USEC_PER_MSEC) 34 #define YT2_1380_FC_VOLT_SW_DELAY_US (1000 * USEC_PER_MSEC) 35 36 struct yt2_1380_fc { 37 struct device *dev; 38 struct pinctrl *pinctrl; 39 struct pinctrl_state *gpio_state; 40 struct pinctrl_state *uart_state; 41 struct gpio_desc *uart3_txd; 42 struct gpio_desc *uart3_rxd; 43 struct extcon_dev *extcon; 44 struct notifier_block nb; 45 struct work_struct work; 46 bool fast_charging; 47 }; 48 49 static int yt2_1380_fc_set_gpio_mode(struct yt2_1380_fc *fc, bool enable) 50 { 51 struct pinctrl_state *state = enable ? fc->gpio_state : fc->uart_state; 52 int ret; 53 54 ret = pinctrl_select_state(fc->pinctrl, state); 55 if (ret) { 56 dev_err(fc->dev, "Error %d setting pinctrl state\n", ret); 57 return ret; 58 } 59 60 fsleep(YT2_1380_FC_PIN_SW_DELAY_US); 61 return 0; 62 } 63 64 static bool yt2_1380_fc_dedicated_charger_connected(struct yt2_1380_fc *fc) 65 { 66 return extcon_get_state(fc->extcon, EXTCON_CHG_USB_DCP) > 0; 67 } 68 69 static bool yt2_1380_fc_fast_charger_connected(struct yt2_1380_fc *fc) 70 { 71 return extcon_get_state(fc->extcon, EXTCON_CHG_USB_FAST) > 0; 72 } 73 74 static void yt2_1380_fc_worker(struct work_struct *work) 75 { 76 struct yt2_1380_fc *fc = container_of(work, struct yt2_1380_fc, work); 77 int i, ret; 78 79 /* Do nothing if already fast charging */ 80 if (yt2_1380_fc_fast_charger_connected(fc)) 81 return; 82 83 for (i = 0; i < YT2_1380_FC_MAX_TRIES; i++) { 84 /* Set pins to UART mode (for charger disconnect and retries) */ 85 ret = yt2_1380_fc_set_gpio_mode(fc, false); 86 if (ret) 87 return; 88 89 /* Only try 12V charging if a dedicated charger is detected */ 90 if (!yt2_1380_fc_dedicated_charger_connected(fc)) 91 return; 92 93 /* Send the command to switch to 12V charging */ 94 ret = serdev_device_write_buf(to_serdev_device(fc->dev), "SC", strlen("SC")); 95 if (ret != strlen("SC")) { 96 dev_err(fc->dev, "Error %d writing to uart\n", ret); 97 return; 98 } 99 100 fsleep(YT2_1380_FC_UART_DRAIN_DELAY_US); 101 102 /* Re-check a charger is still connected */ 103 if (!yt2_1380_fc_dedicated_charger_connected(fc)) 104 return; 105 106 /* 107 * Now switch the lines to GPIO (output, high). The charger 108 * expects the lines being driven high after the command. 109 * Presumably this is used to detect the tablet getting 110 * unplugged (to switch back to 5V output on unplug). 111 */ 112 ret = yt2_1380_fc_set_gpio_mode(fc, true); 113 if (ret) 114 return; 115 116 fsleep(YT2_1380_FC_VOLT_SW_DELAY_US); 117 118 if (yt2_1380_fc_fast_charger_connected(fc)) 119 return; /* Success */ 120 } 121 122 dev_dbg(fc->dev, "Failed to switch to 12V charging (not the original charger?)\n"); 123 /* Failed to enable 12V fast charging, reset pins to default UART mode */ 124 yt2_1380_fc_set_gpio_mode(fc, false); 125 } 126 127 static int yt2_1380_fc_extcon_evt(struct notifier_block *nb, 128 unsigned long event, void *param) 129 { 130 struct yt2_1380_fc *fc = container_of(nb, struct yt2_1380_fc, nb); 131 132 schedule_work(&fc->work); 133 return NOTIFY_OK; 134 } 135 136 static size_t yt2_1380_fc_receive(struct serdev_device *serdev, const u8 *data, size_t len) 137 { 138 /* 139 * Since the USB data lines are shorted for DCP detection, echos of 140 * the "SC" command send in yt2_1380_fc_worker() will be received. 141 */ 142 dev_dbg(&serdev->dev, "recv: %*ph\n", (int)len, data); 143 return len; 144 } 145 146 static const struct serdev_device_ops yt2_1380_fc_serdev_ops = { 147 .receive_buf = yt2_1380_fc_receive, 148 .write_wakeup = serdev_device_write_wakeup, 149 }; 150 151 static int yt2_1380_fc_serdev_probe(struct serdev_device *serdev) 152 { 153 struct device *dev = &serdev->dev; 154 struct yt2_1380_fc *fc; 155 int ret; 156 157 fc = devm_kzalloc(dev, sizeof(*fc), GFP_KERNEL); 158 if (!fc) 159 return -ENOMEM; 160 161 fc->dev = dev; 162 fc->nb.notifier_call = yt2_1380_fc_extcon_evt; 163 INIT_WORK(&fc->work, yt2_1380_fc_worker); 164 165 /* 166 * Do this first since it may return -EPROBE_DEFER. 167 * There is no extcon_put(), so there is no need to free this. 168 */ 169 fc->extcon = extcon_get_extcon_dev(YT2_1380_FC_EXTCON_NAME); 170 if (IS_ERR(fc->extcon)) 171 return dev_err_probe(dev, PTR_ERR(fc->extcon), "getting extcon\n"); 172 173 fc->pinctrl = devm_pinctrl_get(dev); 174 if (IS_ERR(fc->pinctrl)) 175 return dev_err_probe(dev, PTR_ERR(fc->pinctrl), "getting pinctrl\n"); 176 177 /* 178 * To switch the UART3 pins connected to the USB data lines between 179 * UART and GPIO modes. 180 */ 181 fc->gpio_state = pinctrl_lookup_state(fc->pinctrl, "uart3_gpio"); 182 fc->uart_state = pinctrl_lookup_state(fc->pinctrl, "uart3_uart"); 183 if (IS_ERR(fc->gpio_state) || IS_ERR(fc->uart_state)) 184 return dev_err_probe(dev, -EINVAL, "getting pinctrl states\n"); 185 186 ret = yt2_1380_fc_set_gpio_mode(fc, true); 187 if (ret) 188 return ret; 189 190 fc->uart3_txd = devm_gpiod_get(dev, "uart3_txd", GPIOD_OUT_HIGH); 191 if (IS_ERR(fc->uart3_txd)) 192 return dev_err_probe(dev, PTR_ERR(fc->uart3_txd), "getting uart3_txd gpio\n"); 193 194 fc->uart3_rxd = devm_gpiod_get(dev, "uart3_rxd", GPIOD_OUT_HIGH); 195 if (IS_ERR(fc->uart3_rxd)) 196 return dev_err_probe(dev, PTR_ERR(fc->uart3_rxd), "getting uart3_rxd gpio\n"); 197 198 ret = yt2_1380_fc_set_gpio_mode(fc, false); 199 if (ret) 200 return ret; 201 202 serdev_device_set_drvdata(serdev, fc); 203 serdev_device_set_client_ops(serdev, &yt2_1380_fc_serdev_ops); 204 205 ret = devm_serdev_device_open(dev, serdev); 206 if (ret) 207 return dev_err_probe(dev, ret, "opening UART device\n"); 208 209 serdev_device_set_baudrate(serdev, 600); 210 serdev_device_set_flow_control(serdev, false); 211 212 ret = devm_extcon_register_notifier_all(dev, fc->extcon, &fc->nb); 213 if (ret) 214 return dev_err_probe(dev, ret, "registering extcon notifier\n"); 215 216 /* In case the extcon already has detected a DCP charger */ 217 schedule_work(&fc->work); 218 219 return 0; 220 } 221 222 struct serdev_device_driver yt2_1380_fc_serdev_driver = { 223 .probe = yt2_1380_fc_serdev_probe, 224 .driver = { 225 .name = KBUILD_MODNAME, 226 }, 227 }; 228 229 static const struct pinctrl_map yt2_1380_fc_pinctrl_map[] = { 230 PIN_MAP_MUX_GROUP(YT2_1380_FC_SERDEV_NAME, "uart3_uart", 231 "INT33FC:00", "uart3_grp", "uart"), 232 PIN_MAP_MUX_GROUP(YT2_1380_FC_SERDEV_NAME, "uart3_gpio", 233 "INT33FC:00", "uart3_grp_gpio", "gpio"), 234 }; 235 236 static int yt2_1380_fc_pdev_probe(struct platform_device *pdev) 237 { 238 struct serdev_device *serdev; 239 struct device *ctrl_dev; 240 int ret; 241 242 /* Register pinctrl mappings for setting the UART3 pins mode */ 243 ret = pinctrl_register_mappings(yt2_1380_fc_pinctrl_map, 244 ARRAY_SIZE(yt2_1380_fc_pinctrl_map)); 245 if (ret) 246 return ret; 247 248 /* And create the serdev to talk to the charger over the UART3 pins */ 249 ctrl_dev = get_serdev_controller("PNP0501", "1", 0, YT2_1380_FC_SERDEV_CTRL); 250 if (IS_ERR(ctrl_dev)) { 251 ret = PTR_ERR(ctrl_dev); 252 goto out_pinctrl_unregister_mappings; 253 } 254 255 serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev)); 256 put_device(ctrl_dev); 257 if (!serdev) { 258 ret = -ENOMEM; 259 goto out_pinctrl_unregister_mappings; 260 } 261 262 ret = serdev_device_add(serdev); 263 if (ret) { 264 dev_err_probe(&pdev->dev, ret, "adding serdev\n"); 265 serdev_device_put(serdev); 266 goto out_pinctrl_unregister_mappings; 267 } 268 269 /* 270 * serdev device <-> driver matching relies on OF or ACPI matches and 271 * neither is available here, manually bind the driver. 272 */ 273 ret = device_driver_attach(&yt2_1380_fc_serdev_driver.driver, &serdev->dev); 274 if (ret) { 275 /* device_driver_attach() maps EPROBE_DEFER to EAGAIN, map it back */ 276 ret = (ret == -EAGAIN) ? -EPROBE_DEFER : ret; 277 dev_err_probe(&pdev->dev, ret, "attaching serdev driver\n"); 278 goto out_serdev_device_remove; 279 } 280 281 /* So that yt2_1380_fc_pdev_remove() can remove the serdev */ 282 platform_set_drvdata(pdev, serdev); 283 return 0; 284 285 out_serdev_device_remove: 286 serdev_device_remove(serdev); 287 out_pinctrl_unregister_mappings: 288 pinctrl_unregister_mappings(yt2_1380_fc_pinctrl_map); 289 return ret; 290 } 291 292 static void yt2_1380_fc_pdev_remove(struct platform_device *pdev) 293 { 294 struct serdev_device *serdev = platform_get_drvdata(pdev); 295 296 serdev_device_remove(serdev); 297 pinctrl_unregister_mappings(yt2_1380_fc_pinctrl_map); 298 } 299 300 static struct platform_driver yt2_1380_fc_pdev_driver = { 301 .probe = yt2_1380_fc_pdev_probe, 302 .remove = yt2_1380_fc_pdev_remove, 303 .driver = { 304 .name = YT2_1380_FC_PDEV_NAME, 305 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 306 }, 307 }; 308 309 static int __init yt2_1380_fc_module_init(void) 310 { 311 int ret; 312 313 /* 314 * serdev driver MUST be registered first because pdev driver calls 315 * device_driver_attach() on the serdev, serdev-driver pair. 316 */ 317 ret = serdev_device_driver_register(&yt2_1380_fc_serdev_driver); 318 if (ret) 319 return ret; 320 321 ret = platform_driver_register(&yt2_1380_fc_pdev_driver); 322 if (ret) 323 serdev_device_driver_unregister(&yt2_1380_fc_serdev_driver); 324 325 return ret; 326 } 327 module_init(yt2_1380_fc_module_init); 328 329 static void __exit yt2_1380_fc_module_exit(void) 330 { 331 platform_driver_unregister(&yt2_1380_fc_pdev_driver); 332 serdev_device_driver_unregister(&yt2_1380_fc_serdev_driver); 333 } 334 module_exit(yt2_1380_fc_module_exit); 335 336 MODULE_ALIAS("platform:" YT2_1380_FC_PDEV_NAME); 337 MODULE_DESCRIPTION("Lenovo Yoga Tablet 2 1380 fast charge driver"); 338 MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 339 MODULE_LICENSE("GPL"); 340