qcom-pon.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (c) 2017-18 Linaro Limited
  3. #include <linux/delay.h>
  4. #include <linux/errno.h>
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/of.h>
  8. #include <linux/of_platform.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/reboot.h>
  11. #include <linux/reboot-mode.h>
  12. #include <linux/regmap.h>
  13. #define PON_SOFT_RB_SPARE 0x8f
  14. struct pm8916_pon {
  15. struct device *dev;
  16. struct regmap *regmap;
  17. u32 baseaddr;
  18. struct reboot_mode_driver reboot_mode;
  19. };
  20. static int pm8916_reboot_mode_write(struct reboot_mode_driver *reboot,
  21. unsigned int magic)
  22. {
  23. struct pm8916_pon *pon = container_of
  24. (reboot, struct pm8916_pon, reboot_mode);
  25. int ret;
  26. ret = regmap_update_bits(pon->regmap,
  27. pon->baseaddr + PON_SOFT_RB_SPARE,
  28. 0xfc, magic << 2);
  29. if (ret < 0)
  30. dev_err(pon->dev, "update reboot mode bits failed\n");
  31. return ret;
  32. }
  33. static int pm8916_pon_probe(struct platform_device *pdev)
  34. {
  35. struct pm8916_pon *pon;
  36. int error;
  37. pon = devm_kzalloc(&pdev->dev, sizeof(*pon), GFP_KERNEL);
  38. if (!pon)
  39. return -ENOMEM;
  40. pon->dev = &pdev->dev;
  41. pon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
  42. if (!pon->regmap) {
  43. dev_err(&pdev->dev, "failed to locate regmap\n");
  44. return -ENODEV;
  45. }
  46. error = of_property_read_u32(pdev->dev.of_node, "reg",
  47. &pon->baseaddr);
  48. if (error)
  49. return error;
  50. pon->reboot_mode.dev = &pdev->dev;
  51. pon->reboot_mode.write = pm8916_reboot_mode_write;
  52. error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode);
  53. if (error) {
  54. dev_err(&pdev->dev, "can't register reboot mode\n");
  55. return error;
  56. }
  57. platform_set_drvdata(pdev, pon);
  58. return devm_of_platform_populate(&pdev->dev);
  59. }
  60. static const struct of_device_id pm8916_pon_id_table[] = {
  61. { .compatible = "qcom,pm8916-pon" },
  62. { }
  63. };
  64. MODULE_DEVICE_TABLE(of, pm8916_pon_id_table);
  65. static struct platform_driver pm8916_pon_driver = {
  66. .probe = pm8916_pon_probe,
  67. .driver = {
  68. .name = "pm8916-pon",
  69. .of_match_table = of_match_ptr(pm8916_pon_id_table),
  70. },
  71. };
  72. module_platform_driver(pm8916_pon_driver);
  73. MODULE_DESCRIPTION("pm8916 Power On driver");
  74. MODULE_LICENSE("GPL v2");