162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/module.h> 562306a36Sopenharmony_ci#include <linux/of.h> 662306a36Sopenharmony_ci#include <linux/of_platform.h> 762306a36Sopenharmony_ci#include <linux/platform_device.h> 862306a36Sopenharmony_ci#include <linux/rpmsg/qcom_smd.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistatic int rpm_proc_probe(struct platform_device *pdev) 1162306a36Sopenharmony_ci{ 1262306a36Sopenharmony_ci struct qcom_smd_edge *edge = NULL; 1362306a36Sopenharmony_ci struct device *dev = &pdev->dev; 1462306a36Sopenharmony_ci struct device_node *edge_node; 1562306a36Sopenharmony_ci int ret; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci edge_node = of_get_child_by_name(dev->of_node, "smd-edge"); 1862306a36Sopenharmony_ci if (edge_node) { 1962306a36Sopenharmony_ci edge = qcom_smd_register_edge(dev, edge_node); 2062306a36Sopenharmony_ci of_node_put(edge_node); 2162306a36Sopenharmony_ci if (IS_ERR(edge)) 2262306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(edge), 2362306a36Sopenharmony_ci "Failed to register smd-edge\n"); 2462306a36Sopenharmony_ci } 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci ret = devm_of_platform_populate(dev); 2762306a36Sopenharmony_ci if (ret) { 2862306a36Sopenharmony_ci dev_err(dev, "Failed to populate child devices: %d\n", ret); 2962306a36Sopenharmony_ci goto err; 3062306a36Sopenharmony_ci } 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci platform_set_drvdata(pdev, edge); 3362306a36Sopenharmony_ci return 0; 3462306a36Sopenharmony_cierr: 3562306a36Sopenharmony_ci if (edge) 3662306a36Sopenharmony_ci qcom_smd_unregister_edge(edge); 3762306a36Sopenharmony_ci return ret; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic void rpm_proc_remove(struct platform_device *pdev) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct qcom_smd_edge *edge = platform_get_drvdata(pdev); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (edge) 4562306a36Sopenharmony_ci qcom_smd_unregister_edge(edge); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic const struct of_device_id rpm_proc_of_match[] = { 4962306a36Sopenharmony_ci { .compatible = "qcom,rpm-proc", }, 5062306a36Sopenharmony_ci { /* sentinel */ } 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rpm_proc_of_match); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic struct platform_driver rpm_proc_driver = { 5562306a36Sopenharmony_ci .probe = rpm_proc_probe, 5662306a36Sopenharmony_ci .remove_new = rpm_proc_remove, 5762306a36Sopenharmony_ci .driver = { 5862306a36Sopenharmony_ci .name = "qcom-rpm-proc", 5962306a36Sopenharmony_ci .of_match_table = rpm_proc_of_match, 6062306a36Sopenharmony_ci }, 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic int __init rpm_proc_init(void) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci return platform_driver_register(&rpm_proc_driver); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ciarch_initcall(rpm_proc_init); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic void __exit rpm_proc_exit(void) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci platform_driver_unregister(&rpm_proc_driver); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_cimodule_exit(rpm_proc_exit); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm RPM processor/subsystem driver"); 7662306a36Sopenharmony_ciMODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>"); 7762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 78