armada_thermal.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Marvell Armada 370/XP thermal sensor driver
  3. *
  4. * Copyright (C) 2013 Marvell
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/device.h>
  17. #include <linux/err.h>
  18. #include <linux/io.h>
  19. #include <linux/kernel.h>
  20. #include <linux/of.h>
  21. #include <linux/module.h>
  22. #include <linux/delay.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/of_device.h>
  25. #include <linux/thermal.h>
  26. #define THERMAL_VALID_OFFSET 9
  27. #define THERMAL_VALID_MASK 0x1
  28. #define THERMAL_TEMP_OFFSET 10
  29. #define THERMAL_TEMP_MASK 0x1ff
  30. /* Thermal Manager Control and Status Register */
  31. #define PMU_TDC0_SW_RST_MASK (0x1 << 1)
  32. #define PMU_TM_DISABLE_OFFS 0
  33. #define PMU_TM_DISABLE_MASK (0x1 << PMU_TM_DISABLE_OFFS)
  34. #define PMU_TDC0_REF_CAL_CNT_OFFS 11
  35. #define PMU_TDC0_REF_CAL_CNT_MASK (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS)
  36. #define PMU_TDC0_OTF_CAL_MASK (0x1 << 30)
  37. #define PMU_TDC0_START_CAL_MASK (0x1 << 25)
  38. struct armada_thermal_ops;
  39. /* Marvell EBU Thermal Sensor Dev Structure */
  40. struct armada_thermal_priv {
  41. void __iomem *sensor;
  42. void __iomem *control;
  43. struct armada_thermal_ops *ops;
  44. };
  45. struct armada_thermal_ops {
  46. /* Initialize the sensor */
  47. void (*init_sensor)(struct armada_thermal_priv *);
  48. /* Test for a valid sensor value (optional) */
  49. bool (*is_valid)(struct armada_thermal_priv *);
  50. };
  51. static void armadaxp_init_sensor(struct armada_thermal_priv *priv)
  52. {
  53. unsigned long reg;
  54. reg = readl_relaxed(priv->control);
  55. reg |= PMU_TDC0_OTF_CAL_MASK;
  56. writel(reg, priv->control);
  57. /* Reference calibration value */
  58. reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
  59. reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
  60. writel(reg, priv->control);
  61. /* Reset the sensor */
  62. reg = readl_relaxed(priv->control);
  63. writel((reg | PMU_TDC0_SW_RST_MASK), priv->control);
  64. writel(reg, priv->control);
  65. /* Enable the sensor */
  66. reg = readl_relaxed(priv->sensor);
  67. reg &= ~PMU_TM_DISABLE_MASK;
  68. writel(reg, priv->sensor);
  69. }
  70. static void armada370_init_sensor(struct armada_thermal_priv *priv)
  71. {
  72. unsigned long reg;
  73. reg = readl_relaxed(priv->control);
  74. reg |= PMU_TDC0_OTF_CAL_MASK;
  75. writel(reg, priv->control);
  76. /* Reference calibration value */
  77. reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
  78. reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
  79. writel(reg, priv->control);
  80. reg &= ~PMU_TDC0_START_CAL_MASK;
  81. writel(reg, priv->control);
  82. mdelay(10);
  83. }
  84. static bool armada_is_valid(struct armada_thermal_priv *priv)
  85. {
  86. unsigned long reg = readl_relaxed(priv->sensor);
  87. return (reg >> THERMAL_VALID_OFFSET) & THERMAL_VALID_MASK;
  88. }
  89. static int armada_get_temp(struct thermal_zone_device *thermal,
  90. unsigned long *temp)
  91. {
  92. struct armada_thermal_priv *priv = thermal->devdata;
  93. unsigned long reg;
  94. /* Valid check */
  95. if (priv->ops->is_valid && !priv->ops->is_valid(priv)) {
  96. dev_err(&thermal->device,
  97. "Temperature sensor reading not valid\n");
  98. return -EIO;
  99. }
  100. reg = readl_relaxed(priv->sensor);
  101. reg = (reg >> THERMAL_TEMP_OFFSET) & THERMAL_TEMP_MASK;
  102. *temp = (3153000000UL - (10000000UL*reg)) / 13825;
  103. return 0;
  104. }
  105. static struct thermal_zone_device_ops ops = {
  106. .get_temp = armada_get_temp,
  107. };
  108. static const struct armada_thermal_ops armadaxp_ops = {
  109. .init_sensor = armadaxp_init_sensor,
  110. };
  111. static const struct armada_thermal_ops armada370_ops = {
  112. .is_valid = armada_is_valid,
  113. .init_sensor = armada370_init_sensor,
  114. };
  115. static const struct of_device_id armada_thermal_id_table[] = {
  116. {
  117. .compatible = "marvell,armadaxp-thermal",
  118. .data = &armadaxp_ops,
  119. },
  120. {
  121. .compatible = "marvell,armada370-thermal",
  122. .data = &armada370_ops,
  123. },
  124. {
  125. /* sentinel */
  126. },
  127. };
  128. MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
  129. static int armada_thermal_probe(struct platform_device *pdev)
  130. {
  131. struct thermal_zone_device *thermal;
  132. const struct of_device_id *match;
  133. struct armada_thermal_priv *priv;
  134. struct resource *res;
  135. match = of_match_device(armada_thermal_id_table, &pdev->dev);
  136. if (!match)
  137. return -ENODEV;
  138. priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  139. if (!priv)
  140. return -ENOMEM;
  141. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  142. priv->sensor = devm_ioremap_resource(&pdev->dev, res);
  143. if (IS_ERR(priv->sensor))
  144. return PTR_ERR(priv->sensor);
  145. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  146. priv->control = devm_ioremap_resource(&pdev->dev, res);
  147. if (IS_ERR(priv->control))
  148. return PTR_ERR(priv->control);
  149. priv->ops = (struct armada_thermal_ops *)match->data;
  150. priv->ops->init_sensor(priv);
  151. thermal = thermal_zone_device_register("armada_thermal", 0, 0,
  152. priv, &ops, NULL, 0, 0);
  153. if (IS_ERR(thermal)) {
  154. dev_err(&pdev->dev,
  155. "Failed to register thermal zone device\n");
  156. return PTR_ERR(thermal);
  157. }
  158. platform_set_drvdata(pdev, thermal);
  159. return 0;
  160. }
  161. static int armada_thermal_exit(struct platform_device *pdev)
  162. {
  163. struct thermal_zone_device *armada_thermal =
  164. platform_get_drvdata(pdev);
  165. thermal_zone_device_unregister(armada_thermal);
  166. return 0;
  167. }
  168. static struct platform_driver armada_thermal_driver = {
  169. .probe = armada_thermal_probe,
  170. .remove = armada_thermal_exit,
  171. .driver = {
  172. .name = "armada_thermal",
  173. .owner = THIS_MODULE,
  174. .of_match_table = armada_thermal_id_table,
  175. },
  176. };
  177. module_platform_driver(armada_thermal_driver);
  178. MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
  179. MODULE_DESCRIPTION("Armada 370/XP thermal driver");
  180. MODULE_LICENSE("GPL v2");