sec_param.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * COPYRIGHT(C) 2011-2023 Samsung Electronics Co., Ltd. All Right Reserved.
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ":%s() " fmt, __func__
  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <linux/mutex.h>
  9. #include <linux/of.h>
  10. #include <linux/of_platform.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/samsung/builder_pattern.h>
  13. #include <linux/samsung/bsp/sec_param.h>
  14. struct sec_param_drvdata {
  15. struct builder bd;
  16. struct sec_param_operations *ops;
  17. };
  18. static struct sec_param_drvdata *sec_param;
  19. static __always_inline bool __param_is_probed(void)
  20. {
  21. return !!sec_param;
  22. }
  23. static bool __param_get(size_t index, void *value)
  24. {
  25. struct sec_param_operations *ops = sec_param->ops;
  26. if (!ops || !ops->read)
  27. return false;
  28. return ops->read(index, value);
  29. }
  30. bool sec_param_get(size_t index, void *value)
  31. {
  32. if (!__param_is_probed())
  33. return false;
  34. return __param_get(index, value);
  35. }
  36. EXPORT_SYMBOL_GPL(sec_param_get);
  37. static bool __param_set(size_t index, const void *value)
  38. {
  39. struct sec_param_operations *ops = sec_param->ops;
  40. if (!ops || !ops->write)
  41. return false;
  42. return ops->write(index, value);
  43. }
  44. bool sec_param_set(size_t index, const void *value)
  45. {
  46. if (!__param_is_probed())
  47. return false;
  48. return __param_set(index, value);
  49. }
  50. EXPORT_SYMBOL_GPL(sec_param_set);
  51. int sec_param_register_operations(struct sec_param_operations *ops)
  52. {
  53. if (!__param_is_probed())
  54. return -EBUSY;
  55. if (sec_param->ops) {
  56. dev_warn(sec_param->bd.dev, "ops is already set (%p)\n",
  57. sec_param->ops);
  58. return -EPERM;
  59. }
  60. sec_param->ops = ops;
  61. return 0;
  62. }
  63. EXPORT_SYMBOL_GPL(sec_param_register_operations);
  64. void sec_param_unregister_operations(struct sec_param_operations *ops)
  65. {
  66. if (ops != sec_param->ops) {
  67. dev_warn(sec_param->bd.dev,
  68. "%p is not a registered ops.\n", ops);
  69. return;
  70. }
  71. sec_param->ops = NULL;
  72. }
  73. EXPORT_SYMBOL_GPL(sec_param_unregister_operations);
  74. static noinline int __param_probe_epilog(struct builder *bd)
  75. {
  76. struct sec_param_drvdata *drvdata =
  77. container_of(bd, struct sec_param_drvdata, bd);
  78. struct device *dev = bd->dev;
  79. dev_set_drvdata(dev, drvdata);
  80. sec_param = drvdata;
  81. return 0;
  82. }
  83. static noinline void __param_remove_prolog(struct builder *bd)
  84. {
  85. /* FIXME: This is not a graceful exit. */
  86. sec_param = NULL;
  87. }
  88. static const struct dev_builder __param_dev_builder[] = {
  89. DEVICE_BUILDER(__param_probe_epilog, __param_remove_prolog),
  90. };
  91. static int __param_probe(struct platform_device *pdev,
  92. const struct dev_builder *builder, ssize_t n)
  93. {
  94. struct device *dev = &pdev->dev;
  95. struct sec_param_drvdata *drvdata;
  96. drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
  97. if (!drvdata)
  98. return -ENOMEM;
  99. drvdata->bd.dev = dev;
  100. return sec_director_probe_dev(&drvdata->bd, builder, n);
  101. }
  102. static int __param_remove(struct platform_device *pdev,
  103. const struct dev_builder *builder, ssize_t n)
  104. {
  105. struct sec_param_drvdata *drvdata = platform_get_drvdata(pdev);
  106. sec_director_destruct_dev(&drvdata->bd, builder, n, n);
  107. return 0;
  108. }
  109. static int sec_param_probe(struct platform_device *pdev)
  110. {
  111. return __param_probe(pdev, __param_dev_builder,
  112. ARRAY_SIZE(__param_dev_builder));
  113. }
  114. static int sec_param_remove(struct platform_device *pdev)
  115. {
  116. return __param_remove(pdev, __param_dev_builder,
  117. ARRAY_SIZE(__param_dev_builder));
  118. }
  119. static const struct of_device_id sec_param_match_table[] = {
  120. { .compatible = "samsung,param" },
  121. {},
  122. };
  123. MODULE_DEVICE_TABLE(of, sec_param_match_table);
  124. static struct platform_driver sec_param_driver = {
  125. .driver = {
  126. .name = "sec,param",
  127. .of_match_table = of_match_ptr(sec_param_match_table),
  128. },
  129. .probe = sec_param_probe,
  130. .remove = sec_param_remove,
  131. };
  132. static int __init sec_param_init(void)
  133. {
  134. return platform_driver_register(&sec_param_driver);
  135. }
  136. module_init(sec_param_init);
  137. static void __exit sec_param_exit(void)
  138. {
  139. platform_driver_unregister(&sec_param_driver);
  140. }
  141. module_exit(sec_param_exit);
  142. MODULE_AUTHOR("Samsung Electronics");
  143. MODULE_DESCRIPTION("SEC PARAM driver");
  144. MODULE_LICENSE("GPL v2");