thermal_mmio.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. */
  5. #include <linux/module.h>
  6. #include <linux/of_address.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/thermal.h>
  9. struct thermal_mmio {
  10. void __iomem *mmio_base;
  11. u32 (*read_mmio)(void __iomem *mmio_base);
  12. u32 mask;
  13. int factor;
  14. };
  15. static u32 thermal_mmio_readb(void __iomem *mmio_base)
  16. {
  17. return readb(mmio_base);
  18. }
  19. static int thermal_mmio_get_temperature(void *private, int *temp)
  20. {
  21. int t;
  22. struct thermal_mmio *sensor =
  23. (struct thermal_mmio *)private;
  24. t = sensor->read_mmio(sensor->mmio_base) & sensor->mask;
  25. t *= sensor->factor;
  26. *temp = t;
  27. return 0;
  28. }
  29. static struct thermal_zone_of_device_ops thermal_mmio_ops = {
  30. .get_temp = thermal_mmio_get_temperature,
  31. };
  32. static int thermal_mmio_probe(struct platform_device *pdev)
  33. {
  34. struct resource *resource;
  35. struct thermal_mmio *sensor;
  36. int (*sensor_init_func)(struct platform_device *pdev,
  37. struct thermal_mmio *sensor);
  38. struct thermal_zone_device *thermal_zone;
  39. int ret;
  40. int temperature;
  41. sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
  42. if (!sensor)
  43. return -ENOMEM;
  44. resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  45. sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource);
  46. if (IS_ERR(sensor->mmio_base)) {
  47. dev_err(&pdev->dev, "failed to ioremap memory (%ld)\n",
  48. PTR_ERR(sensor->mmio_base));
  49. return PTR_ERR(sensor->mmio_base);
  50. }
  51. sensor_init_func = device_get_match_data(&pdev->dev);
  52. if (sensor_init_func) {
  53. ret = sensor_init_func(pdev, sensor);
  54. if (ret) {
  55. dev_err(&pdev->dev,
  56. "failed to initialize sensor (%d)\n",
  57. ret);
  58. return ret;
  59. }
  60. }
  61. thermal_zone = devm_thermal_zone_of_sensor_register(&pdev->dev,
  62. 0,
  63. sensor,
  64. &thermal_mmio_ops);
  65. if (IS_ERR(thermal_zone)) {
  66. dev_err(&pdev->dev,
  67. "failed to register sensor (%ld)\n",
  68. PTR_ERR(thermal_zone));
  69. return PTR_ERR(thermal_zone);
  70. }
  71. thermal_mmio_get_temperature(sensor, &temperature);
  72. dev_info(&pdev->dev,
  73. "thermal mmio sensor %s registered, current temperature: %d\n",
  74. pdev->name, temperature);
  75. return 0;
  76. }
  77. static int al_thermal_init(struct platform_device *pdev,
  78. struct thermal_mmio *sensor)
  79. {
  80. sensor->read_mmio = thermal_mmio_readb;
  81. sensor->mask = 0xff;
  82. sensor->factor = 1000;
  83. return 0;
  84. }
  85. static const struct of_device_id thermal_mmio_id_table[] = {
  86. { .compatible = "amazon,al-thermal", .data = al_thermal_init},
  87. {}
  88. };
  89. MODULE_DEVICE_TABLE(of, thermal_mmio_id_table);
  90. static struct platform_driver thermal_mmio_driver = {
  91. .probe = thermal_mmio_probe,
  92. .driver = {
  93. .name = "thermal-mmio",
  94. .of_match_table = of_match_ptr(thermal_mmio_id_table),
  95. },
  96. };
  97. module_platform_driver(thermal_mmio_driver);
  98. MODULE_AUTHOR("Talel Shenhar <talel@amazon.com>");
  99. MODULE_DESCRIPTION("Thermal MMIO Driver");
  100. MODULE_LICENSE("GPL v2");