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 ret = devm_serdev_device_open(dev, serdev); 203 if (ret) 204 return dev_err_probe(dev, ret, "opening UART device\n"); 205 206 serdev_device_set_baudrate(serdev, 600); 207 serdev_device_set_flow_control(serdev, false); 208 serdev_device_set_drvdata(serdev, fc); 209 serdev_device_set_client_ops(serdev, &yt2_1380_fc_serdev_ops); 210 211 ret = devm_extcon_register_notifier_all(dev, fc->extcon, &fc->nb); 212 if (ret) 213 return dev_err_probe(dev, ret, "registering extcon notifier\n"); 214 215 /* In case the extcon already has detected a DCP charger */ 216 schedule_work(&fc->work); 217 218 return 0; 219 } 220 221 struct serdev_device_driver yt2_1380_fc_serdev_driver = { 222 .probe = yt2_1380_fc_serdev_probe, 223 .driver = { 224 .name = KBUILD_MODNAME, 225 }, 226 }; 227 228 static const struct pinctrl_map yt2_1380_fc_pinctrl_map[] = { 229 PIN_MAP_MUX_GROUP(YT2_1380_FC_SERDEV_NAME, "uart3_uart", 230 "INT33FC:00", "uart3_grp", "uart"), 231 PIN_MAP_MUX_GROUP(YT2_1380_FC_SERDEV_NAME, "uart3_gpio", 232 "INT33FC:00", "uart3_grp_gpio", "gpio"), 233 }; 234 235 static int yt2_1380_fc_pdev_probe(struct platform_device *pdev) 236 { 237 struct serdev_device *serdev; 238 struct device *ctrl_dev; 239 int ret; 240 241 /* Register pinctrl mappings for setting the UART3 pins mode */ 242 ret = pinctrl_register_mappings(yt2_1380_fc_pinctrl_map, 243 ARRAY_SIZE(yt2_1380_fc_pinctrl_map)); 244 if (ret) 245 return ret; 246 247 /* And create the serdev to talk to the charger over the UART3 pins */ 248 ctrl_dev = get_serdev_controller("PNP0501", "1", 0, YT2_1380_FC_SERDEV_CTRL); 249 if (IS_ERR(ctrl_dev)) { 250 ret = PTR_ERR(ctrl_dev); 251 goto out_pinctrl_unregister_mappings; 252 } 253 254 serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev)); 255 put_device(ctrl_dev); 256 if (!serdev) { 257 ret = -ENOMEM; 258 goto out_pinctrl_unregister_mappings; 259 } 260 261 ret = serdev_device_add(serdev); 262 if (ret) { 263 dev_err_probe(&pdev->dev, ret, "adding serdev\n"); 264 serdev_device_put(serdev); 265 goto out_pinctrl_unregister_mappings; 266 } 267 268 /* 269 * serdev device <-> driver matching relies on OF or ACPI matches and 270 * neither is available here, manually bind the driver. 271 */ 272 ret = device_driver_attach(&yt2_1380_fc_serdev_driver.driver, &serdev->dev); 273 if (ret) { 274 /* device_driver_attach() maps EPROBE_DEFER to EAGAIN, map it back */ 275 ret = (ret == -EAGAIN) ? -EPROBE_DEFER : ret; 276 dev_err_probe(&pdev->dev, ret, "attaching serdev driver\n"); 277 goto out_serdev_device_remove; 278 } 279 280 /* So that yt2_1380_fc_pdev_remove() can remove the serdev */ 281 platform_set_drvdata(pdev, serdev); 282 return 0; 283 284 out_serdev_device_remove: 285 serdev_device_remove(serdev); 286 out_pinctrl_unregister_mappings: 287 pinctrl_unregister_mappings(yt2_1380_fc_pinctrl_map); 288 return ret; 289 } 290 291 static void yt2_1380_fc_pdev_remove(struct platform_device *pdev) 292 { 293 struct serdev_device *serdev = platform_get_drvdata(pdev); 294 295 serdev_device_remove(serdev); 296 pinctrl_unregister_mappings(yt2_1380_fc_pinctrl_map); 297 } 298 299 static struct platform_driver yt2_1380_fc_pdev_driver = { 300 .probe = yt2_1380_fc_pdev_probe, 301 .remove_new = yt2_1380_fc_pdev_remove, 302 .driver = { 303 .name = YT2_1380_FC_PDEV_NAME, 304 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 305 }, 306 }; 307 308 static int __init yt2_1380_fc_module_init(void) 309 { 310 int ret; 311 312 /* 313 * serdev driver MUST be registered first because pdev driver calls 314 * device_driver_attach() on the serdev, serdev-driver pair. 315 */ 316 ret = serdev_device_driver_register(&yt2_1380_fc_serdev_driver); 317 if (ret) 318 return ret; 319 320 ret = platform_driver_register(&yt2_1380_fc_pdev_driver); 321 if (ret) 322 serdev_device_driver_unregister(&yt2_1380_fc_serdev_driver); 323 324 return ret; 325 } 326 module_init(yt2_1380_fc_module_init); 327 328 static void __exit yt2_1380_fc_module_exit(void) 329 { 330 platform_driver_unregister(&yt2_1380_fc_pdev_driver); 331 serdev_device_driver_unregister(&yt2_1380_fc_serdev_driver); 332 } 333 module_exit(yt2_1380_fc_module_exit); 334 335 MODULE_ALIAS("platform:" YT2_1380_FC_PDEV_NAME); 336 MODULE_DESCRIPTION("Lenovo Yoga Tablet 2 1380 fast charge driver"); 337 MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 338 MODULE_LICENSE("GPL"); 339