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/list.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_pci_dev {
23 struct serdev_device *serdev;
24 struct of_changeset *ocs;
25 struct pci_dev *pdev;
26 struct list_head list;
27 };
28
29 struct pwrseq_pcie_m2_pdata {
30 const struct pwrseq_target_data **targets;
31 };
32
33 struct pwrseq_pcie_m2_ctx {
34 struct pwrseq_device *pwrseq;
35 struct device_node *of_node;
36 const struct pwrseq_pcie_m2_pdata *pdata;
37 struct regulator_bulk_data *regs;
38 size_t num_vregs;
39 struct notifier_block nb;
40 struct gpio_desc *w_disable1_gpio;
41 struct gpio_desc *w_disable2_gpio;
42 struct device *dev;
43 struct list_head pci_devices;
44 struct mutex list_lock;
45 };
46
pwrseq_pcie_m2_vregs_enable(struct pwrseq_device * pwrseq)47 static int pwrseq_pcie_m2_vregs_enable(struct pwrseq_device *pwrseq)
48 {
49 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
50
51 return regulator_bulk_enable(ctx->num_vregs, ctx->regs);
52 }
53
pwrseq_pcie_m2_vregs_disable(struct pwrseq_device * pwrseq)54 static int pwrseq_pcie_m2_vregs_disable(struct pwrseq_device *pwrseq)
55 {
56 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
57
58 return regulator_bulk_disable(ctx->num_vregs, ctx->regs);
59 }
60
61 static const struct pwrseq_unit_data pwrseq_pcie_m2_vregs_unit_data = {
62 .name = "regulators-enable",
63 .enable = pwrseq_pcie_m2_vregs_enable,
64 .disable = pwrseq_pcie_m2_vregs_disable,
65 };
66
67 static const struct pwrseq_unit_data *pwrseq_pcie_m2_unit_deps[] = {
68 &pwrseq_pcie_m2_vregs_unit_data,
69 NULL
70 };
71
pwrseq_pci_m2_e_uart_enable(struct pwrseq_device * pwrseq)72 static int pwrseq_pci_m2_e_uart_enable(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, 0);
77 }
78
pwrseq_pci_m2_e_uart_disable(struct pwrseq_device * pwrseq)79 static int pwrseq_pci_m2_e_uart_disable(struct pwrseq_device *pwrseq)
80 {
81 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
82
83 return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1);
84 }
85
86 static const struct pwrseq_unit_data pwrseq_pcie_m2_e_uart_unit_data = {
87 .name = "uart-enable",
88 .deps = pwrseq_pcie_m2_unit_deps,
89 .enable = pwrseq_pci_m2_e_uart_enable,
90 .disable = pwrseq_pci_m2_e_uart_disable,
91 };
92
pwrseq_pci_m2_e_pcie_enable(struct pwrseq_device * pwrseq)93 static int pwrseq_pci_m2_e_pcie_enable(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, 0);
98 }
99
pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device * pwrseq)100 static int pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device *pwrseq)
101 {
102 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
103
104 return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1);
105 }
106
107 static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = {
108 .name = "pcie-enable",
109 .deps = pwrseq_pcie_m2_unit_deps,
110 .enable = pwrseq_pci_m2_e_pcie_enable,
111 .disable = pwrseq_pci_m2_e_pcie_disable,
112 };
113
114 static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = {
115 .name = "pcie-enable",
116 .deps = pwrseq_pcie_m2_unit_deps,
117 };
118
pwrseq_pcie_m2_e_pwup_delay(struct pwrseq_device * pwrseq)119 static int pwrseq_pcie_m2_e_pwup_delay(struct pwrseq_device *pwrseq)
120 {
121 /*
122 * FIXME: This delay is only required for some Qcom WLAN/BT cards like
123 * WCN7850 and not for all devices. But currently, there is no way to
124 * identify the device model before enumeration.
125 */
126 msleep(50);
127
128 return 0;
129 }
130
131 static const struct pwrseq_target_data pwrseq_pcie_m2_e_uart_target_data = {
132 .name = "uart",
133 .unit = &pwrseq_pcie_m2_e_uart_unit_data,
134 .post_enable = pwrseq_pcie_m2_e_pwup_delay,
135 };
136
137 static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = {
138 .name = "pcie",
139 .unit = &pwrseq_pcie_m2_e_pcie_unit_data,
140 .post_enable = pwrseq_pcie_m2_e_pwup_delay,
141 };
142
143 static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
144 .name = "pcie",
145 .unit = &pwrseq_pcie_m2_m_pcie_unit_data,
146 };
147
148 static const struct pwrseq_target_data *pwrseq_pcie_m2_e_targets[] = {
149 &pwrseq_pcie_m2_e_pcie_target_data,
150 &pwrseq_pcie_m2_e_uart_target_data,
151 NULL
152 };
153
154 static const struct pwrseq_target_data *pwrseq_pcie_m2_m_targets[] = {
155 &pwrseq_pcie_m2_m_pcie_target_data,
156 NULL
157 };
158
159 static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_e_of_data = {
160 .targets = pwrseq_pcie_m2_e_targets,
161 };
162
163 static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data = {
164 .targets = pwrseq_pcie_m2_m_targets,
165 };
166
pwrseq_pcie_m2_match(struct pwrseq_device * pwrseq,struct device * dev)167 static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq,
168 struct device *dev)
169 {
170 struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
171 struct device_node *endpoint __free(device_node) = NULL;
172
173 /*
174 * Traverse the 'remote-endpoint' nodes and check if the remote node's
175 * parent matches the OF node of 'dev'.
176 */
177 for_each_endpoint_of_node(ctx->of_node, endpoint) {
178 struct device_node *remote __free(device_node) =
179 of_graph_get_remote_port_parent(endpoint);
180 if (remote && (remote == dev_of_node(dev)))
181 return PWRSEQ_MATCH_OK;
182 }
183
184 return PWRSEQ_NO_MATCH;
185 }
186
187 static const struct pci_device_id pwrseq_m2_pci_ids[] = {
188 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x2b43),
189 .driver_data = (kernel_ulong_t)"nxp,88w8987-bt" },
190 { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, 0x3003),
191 .driver_data = (kernel_ulong_t)"nxp,88w8987-bt" },
192 { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1103, PCI_VENDOR_ID_QCOM, 0x0108),
193 .driver_data = (kernel_ulong_t)"qcom,qca2066-bt" },
194 { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1103, PCI_VENDOR_ID_FOXCONN, 0xe105),
195 .driver_data = (kernel_ulong_t)"qcom,wcn6855-bt" },
196 { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1103, PCI_VENDOR_ID_QCOM, 0x337e),
197 .driver_data = (kernel_ulong_t)"qcom,wcn6855-bt" },
198 { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1107, PCI_VENDOR_ID_QCOM, 0x337c),
199 .driver_data = (kernel_ulong_t)"qcom,wcn7850-bt" },
200 { } /* Sentinel */
201 };
202
pwrseq_pcie_m2_create_bt_node(struct pwrseq_pcie_m2_ctx * ctx,struct pwrseq_pci_dev * pci_dev,struct device_node * parent,struct pci_dev * pdev)203 static int pwrseq_pcie_m2_create_bt_node(struct pwrseq_pcie_m2_ctx *ctx,
204 struct pwrseq_pci_dev *pci_dev,
205 struct device_node *parent,
206 struct pci_dev *pdev)
207 {
208 const struct pci_device_id *id;
209 struct device *dev = ctx->dev;
210 const char *compatible;
211 struct device_node *np;
212 int ret;
213
214 id = pci_match_id(pwrseq_m2_pci_ids, pdev);
215 if (WARN_ON_ONCE(!id)) /* Shouldn't happen */
216 return -ENODEV;
217
218 compatible = (const char *)id->driver_data;
219
220 pci_dev->ocs = kzalloc_obj(*pci_dev->ocs);
221 if (!pci_dev->ocs)
222 return -ENOMEM;
223
224 of_changeset_init(pci_dev->ocs);
225
226 np = of_changeset_create_node(pci_dev->ocs, parent, "bluetooth");
227 if (!np) {
228 dev_err(dev, "Failed to create bluetooth node\n");
229 ret = -ENODEV;
230 goto err_destroy_changeset;
231 }
232
233 ret = of_changeset_add_prop_string(pci_dev->ocs, np, "compatible", compatible);
234 if (ret) {
235 dev_err(dev, "Failed to add bluetooth compatible: %d\n", ret);
236 goto err_destroy_changeset;
237 }
238
239 ret = of_changeset_apply(pci_dev->ocs);
240 if (ret) {
241 dev_err(dev, "Failed to apply changeset: %d\n", ret);
242 goto err_destroy_changeset;
243 }
244
245 ret = device_add_of_node(&pci_dev->serdev->dev, np);
246 if (ret) {
247 dev_err(dev, "Failed to add OF node: %d\n", ret);
248 goto err_revert_changeset;
249 }
250
251 return 0;
252
253 err_revert_changeset:
254 of_changeset_revert(pci_dev->ocs);
255 err_destroy_changeset:
256 of_changeset_destroy(pci_dev->ocs);
257 kfree(pci_dev->ocs);
258 pci_dev->ocs = NULL;
259
260 return ret;
261 }
262
pwrseq_pcie_m2_create_serdev_one(struct pwrseq_pcie_m2_ctx * ctx,struct pci_dev * pdev)263 static int pwrseq_pcie_m2_create_serdev_one(struct pwrseq_pcie_m2_ctx *ctx,
264 struct pci_dev *pdev)
265 {
266 struct serdev_controller *serdev_ctrl;
267 struct device *dev = ctx->dev;
268 struct pwrseq_pci_dev *pci_dev;
269 int ret;
270
271 struct device_node *serdev_parent __free(device_node) =
272 of_graph_get_remote_node(dev_of_node(ctx->dev), 3, 0);
273 if (!serdev_parent)
274 return 0;
275
276 serdev_ctrl = of_find_serdev_controller_by_node(serdev_parent);
277 if (!serdev_ctrl)
278 return 0;
279
280 /* Bail out if the device was already attached to this controller */
281 if (serdev_ctrl->serdev) {
282 serdev_controller_put(serdev_ctrl);
283 return 0;
284 }
285
286 /* Bail out if the serdev device was already created for the PCI dev */
287 scoped_guard(mutex, &ctx->list_lock) {
288 list_for_each_entry(pci_dev, &ctx->pci_devices, list) {
289 if (pci_dev->pdev == pdev)
290 return 0;
291 }
292 }
293
294 pci_dev = kzalloc_obj(*pci_dev);
295 if (!pci_dev) {
296 ret = -ENOMEM;
297 goto err_put_ctrl;
298 }
299
300 pci_dev->serdev = serdev_device_alloc(serdev_ctrl);
301 if (!pci_dev->serdev) {
302 ret = -ENOMEM;
303 goto err_free_pci_dev;
304 }
305
306 ret = pwrseq_pcie_m2_create_bt_node(ctx, pci_dev, serdev_parent, pdev);
307 if (ret)
308 goto err_free_serdev;
309
310 ret = serdev_device_add(pci_dev->serdev);
311 if (ret) {
312 dev_err(dev, "Failed to add serdev for PCI device (%s): %d\n",
313 pci_name(pdev), ret);
314 goto err_free_dt_node;
315 }
316
317 serdev_controller_put(serdev_ctrl);
318
319 pci_dev->pdev = pci_dev_get(pdev);
320
321 mutex_lock(&ctx->list_lock);
322 list_add_tail(&pci_dev->list, &ctx->pci_devices);
323 mutex_unlock(&ctx->list_lock);
324
325 return 0;
326
327 err_free_dt_node:
328 device_remove_of_node(&pci_dev->serdev->dev);
329 of_changeset_revert(pci_dev->ocs);
330 of_changeset_destroy(pci_dev->ocs);
331 kfree(pci_dev->ocs);
332 pci_dev->ocs = NULL;
333 err_free_serdev:
334 serdev_device_put(pci_dev->serdev);
335 pci_dev->serdev = NULL;
336 err_free_pci_dev:
337 kfree(pci_dev);
338 err_put_ctrl:
339 serdev_controller_put(serdev_ctrl);
340
341 return ret;
342 }
343
__pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx * ctx,struct pwrseq_pci_dev * pci_dev)344 static void __pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx,
345 struct pwrseq_pci_dev *pci_dev)
346 {
347 if (pci_dev->serdev) {
348 device_remove_of_node(&pci_dev->serdev->dev);
349 serdev_device_remove(pci_dev->serdev);
350 }
351
352 if (pci_dev->ocs) {
353 of_changeset_revert(pci_dev->ocs);
354 of_changeset_destroy(pci_dev->ocs);
355 kfree(pci_dev->ocs);
356 }
357
358 pci_dev_put(pci_dev->pdev);
359 list_del(&pci_dev->list);
360 kfree(pci_dev);
361 }
362
pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx * ctx,struct pci_dev * pdev)363 static void pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx,
364 struct pci_dev *pdev)
365 {
366 struct pwrseq_pci_dev *pci_dev, *tmp;
367
368 mutex_lock(&ctx->list_lock);
369 list_for_each_entry_safe(pci_dev, tmp, &ctx->pci_devices, list) {
370 if (!pdev || pci_dev->pdev == pdev) {
371 __pwrseq_pcie_m2_remove_serdev(ctx, pci_dev);
372 if (pdev)
373 break;
374 }
375 }
376 mutex_unlock(&ctx->list_lock);
377 }
378
pwrseq_pcie_m2_notify(struct notifier_block * nb,unsigned long action,void * data)379 static int pwrseq_pcie_m2_notify(struct notifier_block *nb, unsigned long action,
380 void *data)
381 {
382 struct pwrseq_pcie_m2_ctx *ctx = container_of(nb, struct pwrseq_pcie_m2_ctx, nb);
383 struct pci_dev *pdev = to_pci_dev(data);
384 int ret;
385
386 /*
387 * Check whether the PCI device is associated with this M.2 connector or
388 * not, by comparing the OF node of the PCI device parent and the Port 0
389 * (PCIe) remote node parent OF node.
390 */
391 struct device_node *pci_parent __free(device_node) =
392 of_graph_get_remote_node(dev_of_node(ctx->dev), 0, 0);
393 if (!pci_parent || (pci_parent != pdev->dev.parent->of_node))
394 return NOTIFY_DONE;
395
396 switch (action) {
397 case BUS_NOTIFY_ADD_DEVICE:
398 if (pci_match_id(pwrseq_m2_pci_ids, pdev)) {
399 ret = pwrseq_pcie_m2_create_serdev_one(ctx, pdev);
400 if (ret)
401 return notifier_from_errno(ret);
402 }
403 break;
404 case BUS_NOTIFY_REMOVED_DEVICE:
405 if (pci_match_id(pwrseq_m2_pci_ids, pdev))
406 pwrseq_pcie_m2_remove_serdev(ctx, pdev);
407
408 break;
409 }
410
411 return NOTIFY_OK;
412 }
413
pwrseq_pcie_m2_check_remote_node(struct device * dev,u8 port,u8 endpoint,const char * node)414 static bool pwrseq_pcie_m2_check_remote_node(struct device *dev, u8 port, u8 endpoint,
415 const char *node)
416 {
417 struct device_node *remote __free(device_node) =
418 of_graph_get_remote_node(dev_of_node(dev), port, endpoint);
419
420 if (remote && of_node_name_eq(remote, node))
421 return true;
422
423 return false;
424 }
425
426 /*
427 * If the connector exposes a non-discoverable bus like UART, the respective
428 * protocol device needs to be created manually with the help of the notifier
429 * of the discoverable bus like PCIe.
430 */
pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx * ctx)431 static int pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx *ctx)
432 {
433 int ret;
434
435 /*
436 * Register a PCI notifier for Key E connector that has PCIe as Port
437 * 0/Endpoint 0 interface and Serial as Port 3/Endpoint 0 interface.
438 */
439 if (!pwrseq_pcie_m2_check_remote_node(ctx->dev, 3, 0, "serial") ||
440 !pwrseq_pcie_m2_check_remote_node(ctx->dev, 0, 0, "pcie"))
441 return 0;
442
443 ctx->nb.notifier_call = pwrseq_pcie_m2_notify;
444 ret = bus_register_notifier(&pci_bus_type, &ctx->nb);
445 if (ret)
446 return dev_err_probe(ctx->dev, ret,
447 "Failed to register notifier for serdev\n");
448 return 0;
449 }
450
pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx * ctx)451 static int pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx *ctx)
452 {
453 struct pci_dev *pdev = NULL;
454 int ret;
455
456 if (!pwrseq_pcie_m2_check_remote_node(ctx->dev, 3, 0, "serial") ||
457 !pwrseq_pcie_m2_check_remote_node(ctx->dev, 0, 0, "pcie"))
458 return 0;
459
460 struct device_node *pci_parent __free(device_node) =
461 of_graph_get_remote_node(dev_of_node(ctx->dev), 0, 0);
462 if (!pci_parent)
463 return 0;
464
465 /* Create serdev for existing PCI devices if required */
466 for_each_pci_dev(pdev) {
467 if (!pdev->dev.parent || pci_parent != pdev->dev.parent->of_node)
468 continue;
469
470 if (!pci_match_id(pwrseq_m2_pci_ids, pdev))
471 continue;
472
473 ret = pwrseq_pcie_m2_create_serdev_one(ctx, pdev);
474 if (ret) {
475 dev_err_probe(ctx->dev, ret,
476 "Failed to create serdev for PCI device (%s)\n",
477 pci_name(pdev));
478 pci_dev_put(pdev);
479 goto err_remove_serdev;
480 }
481 }
482
483 return 0;
484
485 err_remove_serdev:
486 pwrseq_pcie_m2_remove_serdev(ctx, NULL);
487
488 return ret;
489 }
490
pwrseq_pcie_m2_probe(struct platform_device * pdev)491 static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
492 {
493 struct device *dev = &pdev->dev;
494 struct pwrseq_pcie_m2_ctx *ctx;
495 struct pwrseq_config config = {};
496 int ret;
497
498 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
499 if (!ctx)
500 return -ENOMEM;
501
502 platform_set_drvdata(pdev, ctx);
503 ctx->of_node = dev_of_node(dev);
504 ctx->pdata = device_get_match_data(dev);
505 if (!ctx->pdata)
506 return dev_err_probe(dev, -ENODEV,
507 "Failed to obtain platform data\n");
508
509 /*
510 * Currently, of_regulator_bulk_get_all() is the only regulator API that
511 * allows to get all supplies in the devicetree node without manually
512 * specifying them.
513 */
514 ret = of_regulator_bulk_get_all(dev, dev_of_node(dev), &ctx->regs);
515 if (ret < 0)
516 return dev_err_probe(dev, ret,
517 "Failed to get all regulators\n");
518
519 ctx->num_vregs = ret;
520
521 ctx->w_disable1_gpio = devm_gpiod_get_optional(dev, "w-disable1", GPIOD_OUT_HIGH);
522 if (IS_ERR(ctx->w_disable1_gpio)) {
523 ret = dev_err_probe(dev, PTR_ERR(ctx->w_disable1_gpio),
524 "Failed to get the W_DISABLE_1# GPIO\n");
525 goto err_free_regulators;
526 }
527
528 ctx->w_disable2_gpio = devm_gpiod_get_optional(dev, "w-disable2", GPIOD_OUT_HIGH);
529 if (IS_ERR(ctx->w_disable2_gpio)) {
530 ret = dev_err_probe(dev, PTR_ERR(ctx->w_disable2_gpio),
531 "Failed to get the W_DISABLE_2# GPIO\n");
532 goto err_free_regulators;
533 }
534
535 config.parent = dev;
536 config.owner = THIS_MODULE;
537 config.drvdata = ctx;
538 config.match = pwrseq_pcie_m2_match;
539 config.targets = ctx->pdata->targets;
540
541 ctx->pwrseq = devm_pwrseq_device_register(dev, &config);
542 if (IS_ERR(ctx->pwrseq)) {
543 ret = dev_err_probe(dev, PTR_ERR(ctx->pwrseq),
544 "Failed to register the power sequencer\n");
545 goto err_free_regulators;
546 }
547
548 mutex_init(&ctx->list_lock);
549 INIT_LIST_HEAD(&ctx->pci_devices);
550 ctx->dev = dev;
551
552 /* Create serdev for available PCI devices (if required) */
553 ret = pwrseq_pcie_m2_create_serdev(ctx);
554 if (ret)
555 goto err_destroy_mutex;
556
557 /*
558 * Register a notifier for creating protocol devices for
559 * non-discoverable busses like UART.
560 */
561 ret = pwrseq_pcie_m2_register_notifier(ctx);
562 if (ret)
563 goto err_remove_serdev;
564
565 return 0;
566
567 err_remove_serdev:
568 pwrseq_pcie_m2_remove_serdev(ctx, NULL);
569 err_destroy_mutex:
570 mutex_destroy(&ctx->list_lock);
571 err_free_regulators:
572 regulator_bulk_free(ctx->num_vregs, ctx->regs);
573
574 return ret;
575 }
576
pwrseq_pcie_m2_remove(struct platform_device * pdev)577 static void pwrseq_pcie_m2_remove(struct platform_device *pdev)
578 {
579 struct pwrseq_pcie_m2_ctx *ctx = platform_get_drvdata(pdev);
580
581 bus_unregister_notifier(&pci_bus_type, &ctx->nb);
582 pwrseq_pcie_m2_remove_serdev(ctx, NULL);
583 mutex_destroy(&ctx->list_lock);
584
585 regulator_bulk_free(ctx->num_vregs, ctx->regs);
586 }
587
588 static const struct of_device_id pwrseq_pcie_m2_of_match[] = {
589 {
590 .compatible = "pcie-m2-m-connector",
591 .data = &pwrseq_pcie_m2_m_of_data,
592 },
593 {
594 .compatible = "pcie-m2-e-connector",
595 .data = &pwrseq_pcie_m2_e_of_data,
596 },
597 { }
598 };
599 MODULE_DEVICE_TABLE(of, pwrseq_pcie_m2_of_match);
600
601 static struct platform_driver pwrseq_pcie_m2_driver = {
602 .driver = {
603 .name = "pwrseq-pcie-m2",
604 .of_match_table = pwrseq_pcie_m2_of_match,
605 },
606 .probe = pwrseq_pcie_m2_probe,
607 .remove = pwrseq_pcie_m2_remove,
608 };
609 module_platform_driver(pwrseq_pcie_m2_driver);
610
611 MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>");
612 MODULE_DESCRIPTION("Power Sequencing driver for PCIe M.2 connector");
613 MODULE_LICENSE("GPL");
614