1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4 * Author: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com> 5 */ 6 7 #include <linux/device.h> 8 #include <linux/delay.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/mod_devicetable.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_graph.h> 14 #include <linux/of_platform.h> 15 #include <linux/pci.h> 16 #include <linux/platform_device.h> 17 #include <linux/pwrseq/provider.h> 18 #include <linux/regulator/consumer.h> 19 #include <linux/serdev.h> 20 #include <linux/slab.h> 21 22 struct pwrseq_pcie_m2_pdata { 23 const struct pwrseq_target_data **targets; 24 }; 25 26 struct pwrseq_pcie_m2_ctx { 27 struct pwrseq_device *pwrseq; 28 struct device_node *of_node; 29 const struct pwrseq_pcie_m2_pdata *pdata; 30 struct regulator_bulk_data *regs; 31 size_t num_vregs; 32 struct notifier_block nb; 33 struct gpio_desc *w_disable1_gpio; 34 struct gpio_desc *w_disable2_gpio; 35 struct serdev_device *serdev; 36 struct of_changeset *ocs; 37 struct device *dev; 38 }; 39 40 static int pwrseq_pcie_m2_vregs_enable(struct pwrseq_device *pwrseq) 41 { 42 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 43 44 return regulator_bulk_enable(ctx->num_vregs, ctx->regs); 45 } 46 47 static int pwrseq_pcie_m2_vregs_disable(struct pwrseq_device *pwrseq) 48 { 49 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 50 51 return regulator_bulk_disable(ctx->num_vregs, ctx->regs); 52 } 53 54 static const struct pwrseq_unit_data pwrseq_pcie_m2_vregs_unit_data = { 55 .name = "regulators-enable", 56 .enable = pwrseq_pcie_m2_vregs_enable, 57 .disable = pwrseq_pcie_m2_vregs_disable, 58 }; 59 60 static const struct pwrseq_unit_data *pwrseq_pcie_m2_unit_deps[] = { 61 &pwrseq_pcie_m2_vregs_unit_data, 62 NULL 63 }; 64 65 static int pwrseq_pci_m2_e_uart_enable(struct pwrseq_device *pwrseq) 66 { 67 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 68 69 return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0); 70 } 71 72 static int pwrseq_pci_m2_e_uart_disable(struct pwrseq_device *pwrseq) 73 { 74 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 75 76 return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1); 77 } 78 79 static const struct pwrseq_unit_data pwrseq_pcie_m2_e_uart_unit_data = { 80 .name = "uart-enable", 81 .deps = pwrseq_pcie_m2_unit_deps, 82 .enable = pwrseq_pci_m2_e_uart_enable, 83 .disable = pwrseq_pci_m2_e_uart_disable, 84 }; 85 86 static int pwrseq_pci_m2_e_pcie_enable(struct pwrseq_device *pwrseq) 87 { 88 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 89 90 return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 0); 91 } 92 93 static int pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device *pwrseq) 94 { 95 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 96 97 return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1); 98 } 99 100 static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = { 101 .name = "pcie-enable", 102 .deps = pwrseq_pcie_m2_unit_deps, 103 .enable = pwrseq_pci_m2_e_pcie_enable, 104 .disable = pwrseq_pci_m2_e_pcie_disable, 105 }; 106 107 static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = { 108 .name = "pcie-enable", 109 .deps = pwrseq_pcie_m2_unit_deps, 110 }; 111 112 static int pwrseq_pcie_m2_e_pwup_delay(struct pwrseq_device *pwrseq) 113 { 114 /* 115 * FIXME: This delay is only required for some Qcom WLAN/BT cards like 116 * WCN7850 and not for all devices. But currently, there is no way to 117 * identify the device model before enumeration. 118 */ 119 msleep(50); 120 121 return 0; 122 } 123 124 static const struct pwrseq_target_data pwrseq_pcie_m2_e_uart_target_data = { 125 .name = "uart", 126 .unit = &pwrseq_pcie_m2_e_uart_unit_data, 127 .post_enable = pwrseq_pcie_m2_e_pwup_delay, 128 }; 129 130 static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = { 131 .name = "pcie", 132 .unit = &pwrseq_pcie_m2_e_pcie_unit_data, 133 .post_enable = pwrseq_pcie_m2_e_pwup_delay, 134 }; 135 136 static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = { 137 .name = "pcie", 138 .unit = &pwrseq_pcie_m2_m_pcie_unit_data, 139 }; 140 141 static const struct pwrseq_target_data *pwrseq_pcie_m2_e_targets[] = { 142 &pwrseq_pcie_m2_e_pcie_target_data, 143 &pwrseq_pcie_m2_e_uart_target_data, 144 NULL 145 }; 146 147 static const struct pwrseq_target_data *pwrseq_pcie_m2_m_targets[] = { 148 &pwrseq_pcie_m2_m_pcie_target_data, 149 NULL 150 }; 151 152 static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_e_of_data = { 153 .targets = pwrseq_pcie_m2_e_targets, 154 }; 155 156 static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data = { 157 .targets = pwrseq_pcie_m2_m_targets, 158 }; 159 160 static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq, 161 struct device *dev) 162 { 163 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 164 struct device_node *endpoint __free(device_node) = NULL; 165 166 /* 167 * Traverse the 'remote-endpoint' nodes and check if the remote node's 168 * parent matches the OF node of 'dev'. 169 */ 170 for_each_endpoint_of_node(ctx->of_node, endpoint) { 171 struct device_node *remote __free(device_node) = 172 of_graph_get_remote_port_parent(endpoint); 173 if (remote && (remote == dev_of_node(dev))) 174 return PWRSEQ_MATCH_OK; 175 } 176 177 return PWRSEQ_NO_MATCH; 178 } 179 180 static int pwrseq_m2_pcie_create_bt_node(struct pwrseq_pcie_m2_ctx *ctx, 181 struct device_node *parent) 182 { 183 struct device *dev = ctx->dev; 184 struct device_node *np; 185 int ret; 186 187 ctx->ocs = kzalloc_obj(*ctx->ocs); 188 if (!ctx->ocs) 189 return -ENOMEM; 190 191 of_changeset_init(ctx->ocs); 192 193 np = of_changeset_create_node(ctx->ocs, parent, "bluetooth"); 194 if (!np) { 195 dev_err(dev, "Failed to create bluetooth node\n"); 196 ret = -ENODEV; 197 goto err_destroy_changeset; 198 } 199 200 ret = of_changeset_add_prop_string(ctx->ocs, np, "compatible", "qcom,wcn7850-bt"); 201 if (ret) { 202 dev_err(dev, "Failed to add bluetooth compatible: %d\n", ret); 203 goto err_destroy_changeset; 204 } 205 206 ret = of_changeset_apply(ctx->ocs); 207 if (ret) { 208 dev_err(dev, "Failed to apply changeset: %d\n", ret); 209 goto err_destroy_changeset; 210 } 211 212 ret = device_add_of_node(&ctx->serdev->dev, np); 213 if (ret) { 214 dev_err(dev, "Failed to add OF node: %d\n", ret); 215 goto err_revert_changeset; 216 } 217 218 return 0; 219 220 err_revert_changeset: 221 of_changeset_revert(ctx->ocs); 222 err_destroy_changeset: 223 of_changeset_destroy(ctx->ocs); 224 kfree(ctx->ocs); 225 ctx->ocs = NULL; 226 227 return ret; 228 } 229 230 static int pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx *ctx) 231 { 232 struct serdev_controller *serdev_ctrl; 233 struct device *dev = ctx->dev; 234 int ret; 235 236 struct device_node *serdev_parent __free(device_node) = 237 of_graph_get_remote_node(dev_of_node(ctx->dev), 3, 0); 238 if (!serdev_parent) 239 return 0; 240 241 serdev_ctrl = of_find_serdev_controller_by_node(serdev_parent); 242 if (!serdev_ctrl) 243 return 0; 244 245 /* Bail out if the device was already attached to this controller */ 246 if (serdev_ctrl->serdev) { 247 serdev_controller_put(serdev_ctrl); 248 return 0; 249 } 250 251 ctx->serdev = serdev_device_alloc(serdev_ctrl); 252 if (!ctx->serdev) { 253 ret = -ENOMEM; 254 goto err_put_ctrl; 255 } 256 257 ret = pwrseq_m2_pcie_create_bt_node(ctx, serdev_parent); 258 if (ret) 259 goto err_free_serdev; 260 261 ret = serdev_device_add(ctx->serdev); 262 if (ret) { 263 dev_err(dev, "Failed to add serdev for WCN7850: %d\n", ret); 264 goto err_free_dt_node; 265 } 266 267 serdev_controller_put(serdev_ctrl); 268 269 return 0; 270 271 err_free_dt_node: 272 device_remove_of_node(&ctx->serdev->dev); 273 of_changeset_revert(ctx->ocs); 274 of_changeset_destroy(ctx->ocs); 275 kfree(ctx->ocs); 276 ctx->ocs = NULL; 277 err_free_serdev: 278 serdev_device_put(ctx->serdev); 279 ctx->serdev = NULL; 280 err_put_ctrl: 281 serdev_controller_put(serdev_ctrl); 282 283 return ret; 284 } 285 286 static void pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx) 287 { 288 if (ctx->serdev) { 289 device_remove_of_node(&ctx->serdev->dev); 290 serdev_device_remove(ctx->serdev); 291 ctx->serdev = NULL; 292 } 293 294 if (ctx->ocs) { 295 of_changeset_revert(ctx->ocs); 296 of_changeset_destroy(ctx->ocs); 297 kfree(ctx->ocs); 298 ctx->ocs = NULL; 299 } 300 } 301 302 static int pwrseq_m2_pcie_notify(struct notifier_block *nb, unsigned long action, 303 void *data) 304 { 305 struct pwrseq_pcie_m2_ctx *ctx = container_of(nb, struct pwrseq_pcie_m2_ctx, nb); 306 struct pci_dev *pdev = to_pci_dev(data); 307 int ret; 308 309 /* 310 * Check whether the PCI device is associated with this M.2 connector or 311 * not, by comparing the OF node of the PCI device parent and the Port 0 312 * (PCIe) remote node parent OF node. 313 */ 314 struct device_node *pci_parent __free(device_node) = 315 of_graph_get_remote_node(dev_of_node(ctx->dev), 0, 0); 316 if (!pci_parent || (pci_parent != pdev->dev.parent->of_node)) 317 return NOTIFY_DONE; 318 319 switch (action) { 320 case BUS_NOTIFY_ADD_DEVICE: 321 /* Create serdev device for WCN7850 */ 322 if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107) { 323 ret = pwrseq_pcie_m2_create_serdev(ctx); 324 if (ret) 325 return notifier_from_errno(ret); 326 } 327 break; 328 case BUS_NOTIFY_REMOVED_DEVICE: 329 /* Destroy serdev device for WCN7850 */ 330 if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107) 331 pwrseq_pcie_m2_remove_serdev(ctx); 332 333 break; 334 } 335 336 return NOTIFY_OK; 337 } 338 339 static bool pwrseq_pcie_m2_check_remote_node(struct device *dev, u8 port, u8 endpoint, 340 const char *node) 341 { 342 struct device_node *remote __free(device_node) = 343 of_graph_get_remote_node(dev_of_node(dev), port, endpoint); 344 345 if (remote && of_node_name_eq(remote, node)) 346 return true; 347 348 return false; 349 } 350 351 /* 352 * If the connector exposes a non-discoverable bus like UART, the respective 353 * protocol device needs to be created manually with the help of the notifier 354 * of the discoverable bus like PCIe. 355 */ 356 static int pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx *ctx, struct device *dev) 357 { 358 int ret; 359 360 /* 361 * Register a PCI notifier for Key E connector that has PCIe as Port 362 * 0/Endpoint 0 interface and Serial as Port 3/Endpoint 0 interface. 363 */ 364 if (pwrseq_pcie_m2_check_remote_node(dev, 3, 0, "serial")) { 365 if (pwrseq_pcie_m2_check_remote_node(dev, 0, 0, "pcie")) { 366 ctx->dev = dev; 367 ctx->nb.notifier_call = pwrseq_m2_pcie_notify; 368 ret = bus_register_notifier(&pci_bus_type, &ctx->nb); 369 if (ret) 370 return dev_err_probe(dev, ret, 371 "Failed to register notifier for serdev\n"); 372 } 373 } 374 375 return 0; 376 } 377 378 static int pwrseq_pcie_m2_probe(struct platform_device *pdev) 379 { 380 struct device *dev = &pdev->dev; 381 struct pwrseq_pcie_m2_ctx *ctx; 382 struct pwrseq_config config = {}; 383 int ret; 384 385 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 386 if (!ctx) 387 return -ENOMEM; 388 389 platform_set_drvdata(pdev, ctx); 390 ctx->of_node = of_node_get(dev->of_node); 391 ctx->pdata = device_get_match_data(dev); 392 if (!ctx->pdata) 393 return dev_err_probe(dev, -ENODEV, 394 "Failed to obtain platform data\n"); 395 396 /* 397 * Currently, of_regulator_bulk_get_all() is the only regulator API that 398 * allows to get all supplies in the devicetree node without manually 399 * specifying them. 400 */ 401 ret = of_regulator_bulk_get_all(dev, dev_of_node(dev), &ctx->regs); 402 if (ret < 0) 403 return dev_err_probe(dev, ret, 404 "Failed to get all regulators\n"); 405 406 ctx->num_vregs = ret; 407 408 ctx->w_disable1_gpio = devm_gpiod_get_optional(dev, "w-disable1", GPIOD_OUT_HIGH); 409 if (IS_ERR(ctx->w_disable1_gpio)) { 410 ret = dev_err_probe(dev, PTR_ERR(ctx->w_disable1_gpio), 411 "Failed to get the W_DISABLE_1# GPIO\n"); 412 goto err_free_regulators; 413 } 414 415 ctx->w_disable2_gpio = devm_gpiod_get_optional(dev, "w-disable2", GPIOD_OUT_HIGH); 416 if (IS_ERR(ctx->w_disable2_gpio)) { 417 ret = dev_err_probe(dev, PTR_ERR(ctx->w_disable2_gpio), 418 "Failed to get the W_DISABLE_2# GPIO\n"); 419 goto err_free_regulators; 420 } 421 422 config.parent = dev; 423 config.owner = THIS_MODULE; 424 config.drvdata = ctx; 425 config.match = pwrseq_pcie_m2_match; 426 config.targets = ctx->pdata->targets; 427 428 ctx->pwrseq = devm_pwrseq_device_register(dev, &config); 429 if (IS_ERR(ctx->pwrseq)) { 430 ret = dev_err_probe(dev, PTR_ERR(ctx->pwrseq), 431 "Failed to register the power sequencer\n"); 432 goto err_free_regulators; 433 } 434 435 /* 436 * Register a notifier for creating protocol devices for 437 * non-discoverable busses like UART. 438 */ 439 ret = pwrseq_pcie_m2_register_notifier(ctx, dev); 440 if (ret) 441 goto err_free_regulators; 442 443 return 0; 444 445 err_free_regulators: 446 regulator_bulk_free(ctx->num_vregs, ctx->regs); 447 448 return ret; 449 } 450 451 static void pwrseq_pcie_m2_remove(struct platform_device *pdev) 452 { 453 struct pwrseq_pcie_m2_ctx *ctx = platform_get_drvdata(pdev); 454 455 bus_unregister_notifier(&pci_bus_type, &ctx->nb); 456 pwrseq_pcie_m2_remove_serdev(ctx); 457 458 regulator_bulk_free(ctx->num_vregs, ctx->regs); 459 } 460 461 static const struct of_device_id pwrseq_pcie_m2_of_match[] = { 462 { 463 .compatible = "pcie-m2-m-connector", 464 .data = &pwrseq_pcie_m2_m_of_data, 465 }, 466 { 467 .compatible = "pcie-m2-e-connector", 468 .data = &pwrseq_pcie_m2_e_of_data, 469 }, 470 { } 471 }; 472 MODULE_DEVICE_TABLE(of, pwrseq_pcie_m2_of_match); 473 474 static struct platform_driver pwrseq_pcie_m2_driver = { 475 .driver = { 476 .name = "pwrseq-pcie-m2", 477 .of_match_table = pwrseq_pcie_m2_of_match, 478 }, 479 .probe = pwrseq_pcie_m2_probe, 480 .remove = pwrseq_pcie_m2_remove, 481 }; 482 module_platform_driver(pwrseq_pcie_m2_driver); 483 484 MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>"); 485 MODULE_DESCRIPTION("Power Sequencing driver for PCIe M.2 connector"); 486 MODULE_LICENSE("GPL"); 487