msm_popmem-tm.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /* Copyright (c) 2010, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/err.h>
  16. #include <linux/thermal.h>
  17. #include <linux/slab.h>
  18. #include <linux/io.h>
  19. #include <mach/msm_memtypes.h>
  20. #define POP_MEM_LPDDR1_REFRESH_MASK 0x00000700
  21. #define POP_MEM_LPDDR1_REFRESH_SHIFT 0x8
  22. #define POP_MEM_LPDDR2_REFRESH_MASK 0x00000007
  23. #define POP_MEM_LPDDR2_REFRESH_SHIFT 0x0
  24. #define POP_MEM_REFRESH_REG 0x3C
  25. #define POP_MEM_LOW_TEMPERATURE 25000
  26. #define POP_MEM_NORMAL_TEMPERATURE 50000
  27. #define POP_MEM_HIGH_TEMPERATURE 85000
  28. #define POP_MEM_TRIP_OUT_OF_SPEC 0
  29. #define POP_MEM_TRIP_NUM 1
  30. struct pop_mem_tm_device {
  31. unsigned long baseaddr;
  32. struct thermal_zone_device *tz_dev;
  33. unsigned long refresh_mask;
  34. unsigned int refresh_shift;
  35. };
  36. static int pop_mem_tm_read_refresh(struct pop_mem_tm_device *tm,
  37. unsigned int *ref_rate){
  38. unsigned int ref;
  39. ref = __raw_readl(tm->baseaddr + POP_MEM_REFRESH_REG);
  40. *ref_rate = (ref & tm->refresh_mask) >> tm->refresh_shift;
  41. return 0;
  42. }
  43. static int pop_mem_tm_get_temperature(struct thermal_zone_device *thermal,
  44. unsigned long *temperature)
  45. {
  46. struct pop_mem_tm_device *tm = thermal->devdata;
  47. unsigned int ref_rate;
  48. int rc;
  49. if (!tm || !temperature)
  50. return -EINVAL;
  51. rc = pop_mem_tm_read_refresh(tm, &ref_rate);
  52. if (rc < 0)
  53. return rc;
  54. switch (ref_rate) {
  55. case 0:
  56. case 1:
  57. case 2:
  58. *temperature = POP_MEM_LOW_TEMPERATURE;
  59. break;
  60. case 3:
  61. case 4:
  62. *temperature = POP_MEM_NORMAL_TEMPERATURE;
  63. break;
  64. case 5:
  65. case 6:
  66. case 7:
  67. *temperature = POP_MEM_HIGH_TEMPERATURE;
  68. break;
  69. default:
  70. return -EINVAL;
  71. }
  72. return 0;
  73. }
  74. static int pop_mem_tm_get_trip_type(struct thermal_zone_device *thermal,
  75. int trip, enum thermal_trip_type *type)
  76. {
  77. struct pop_mem_tm_device *tm = thermal->devdata;
  78. if (!tm || trip < 0 || !type)
  79. return -EINVAL;
  80. if (trip == POP_MEM_TRIP_OUT_OF_SPEC)
  81. *type = THERMAL_TRIP_CRITICAL;
  82. else
  83. return -EINVAL;
  84. return 0;
  85. }
  86. static int pop_mem_tm_get_trip_temperature(struct thermal_zone_device *thermal,
  87. int trip, unsigned long *temperature)
  88. {
  89. struct pop_mem_tm_device *tm = thermal->devdata;
  90. if (!tm || trip < 0 || !temperature)
  91. return -EINVAL;
  92. if (trip == POP_MEM_TRIP_OUT_OF_SPEC)
  93. *temperature = POP_MEM_HIGH_TEMPERATURE;
  94. else
  95. return -EINVAL;
  96. return 0;
  97. }
  98. static int pop_mem_tm_get_crit_temperature(struct thermal_zone_device *thermal,
  99. unsigned long *temperature)
  100. {
  101. struct pop_mem_tm_device *tm = thermal->devdata;
  102. if (!tm || !temperature)
  103. return -EINVAL;
  104. *temperature = POP_MEM_HIGH_TEMPERATURE;
  105. return 0;
  106. }
  107. static struct thermal_zone_device_ops pop_mem_thermal_zone_ops = {
  108. .get_temp = pop_mem_tm_get_temperature,
  109. .get_trip_type = pop_mem_tm_get_trip_type,
  110. .get_trip_temp = pop_mem_tm_get_trip_temperature,
  111. .get_crit_temp = pop_mem_tm_get_crit_temperature,
  112. };
  113. static int __devinit pop_mem_tm_probe(struct platform_device *pdev)
  114. {
  115. int rc, len, numcontrollers;
  116. struct resource *controller_mem = NULL;
  117. struct resource *res_mem = NULL;
  118. struct pop_mem_tm_device *tmdev = NULL;
  119. void __iomem *base = NULL;
  120. rc = len = 0;
  121. numcontrollers = get_num_populated_chipselects();
  122. if (pdev->id >= numcontrollers) {
  123. pr_err("%s: memory controller %d does not exist", __func__,
  124. pdev->id);
  125. rc = -ENODEV;
  126. goto fail;
  127. }
  128. controller_mem = platform_get_resource_byname(pdev,
  129. IORESOURCE_MEM, "physbase");
  130. if (!controller_mem) {
  131. pr_err("%s: could not get resources for controller %d",
  132. __func__, pdev->id);
  133. rc = -EFAULT;
  134. goto fail;
  135. }
  136. len = controller_mem->end - controller_mem->start + 1;
  137. res_mem = request_mem_region(controller_mem->start, len,
  138. controller_mem->name);
  139. if (!res_mem) {
  140. pr_err("%s: Could not request memory region: "
  141. "start=%p, len=%d\n", __func__,
  142. (void *) controller_mem->start, len);
  143. rc = -EBUSY;
  144. goto fail;
  145. }
  146. base = ioremap(res_mem->start, len);
  147. if (!base) {
  148. pr_err("%s: Could not ioremap: start=%p, len=%d\n",
  149. __func__, (void *) controller_mem->start, len);
  150. rc = -EBUSY;
  151. goto fail;
  152. }
  153. tmdev = kzalloc(sizeof(*tmdev), GFP_KERNEL);
  154. if (tmdev == NULL) {
  155. pr_err("%s: kzalloc() failed.\n", __func__);
  156. rc = -ENOMEM;
  157. goto fail;
  158. }
  159. if (numcontrollers == 1) {
  160. tmdev->refresh_mask = POP_MEM_LPDDR1_REFRESH_MASK;
  161. tmdev->refresh_shift = POP_MEM_LPDDR1_REFRESH_SHIFT;
  162. } else {
  163. tmdev->refresh_mask = POP_MEM_LPDDR2_REFRESH_MASK;
  164. tmdev->refresh_shift = POP_MEM_LPDDR2_REFRESH_SHIFT;
  165. }
  166. tmdev->baseaddr = (unsigned long) base;
  167. tmdev->tz_dev = thermal_zone_device_register("msm_popmem_tz",
  168. POP_MEM_TRIP_NUM, tmdev,
  169. &pop_mem_thermal_zone_ops,
  170. 0, 0, 0, 0);
  171. if (tmdev->tz_dev == NULL) {
  172. pr_err("%s: thermal_zone_device_register() failed.\n",
  173. __func__);
  174. goto fail;
  175. }
  176. platform_set_drvdata(pdev, tmdev);
  177. pr_notice("%s: device %d probed successfully\n", __func__, pdev->id);
  178. return rc;
  179. fail:
  180. if (base)
  181. iounmap(base);
  182. if (res_mem)
  183. release_mem_region(controller_mem->start, len);
  184. kfree(tmdev);
  185. return rc;
  186. }
  187. static int __devexit pop_mem_tm_remove(struct platform_device *pdev)
  188. {
  189. int len;
  190. struct pop_mem_tm_device *tmdev = platform_get_drvdata(pdev);
  191. struct resource *controller_mem;
  192. iounmap((void __iomem *)tmdev->baseaddr);
  193. controller_mem = platform_get_resource_byname(pdev,
  194. IORESOURCE_MEM, "physbase");
  195. len = controller_mem->end - controller_mem->start + 1;
  196. release_mem_region(controller_mem->start, len);
  197. thermal_zone_device_unregister(tmdev->tz_dev);
  198. platform_set_drvdata(pdev, NULL);
  199. kfree(tmdev);
  200. return 0;
  201. }
  202. static struct platform_driver pop_mem_tm_driver = {
  203. .probe = pop_mem_tm_probe,
  204. .remove = pop_mem_tm_remove,
  205. .driver = {
  206. .name = "msm_popmem-tm",
  207. .owner = THIS_MODULE
  208. },
  209. };
  210. static int __init pop_mem_tm_init(void)
  211. {
  212. return platform_driver_register(&pop_mem_tm_driver);
  213. }
  214. static void __exit pop_mem_tm_exit(void)
  215. {
  216. platform_driver_unregister(&pop_mem_tm_driver);
  217. }
  218. module_init(pop_mem_tm_init);
  219. module_exit(pop_mem_tm_exit);
  220. MODULE_LICENSE("GPL v2");
  221. MODULE_DESCRIPTION("Pop memory thermal manager driver");
  222. MODULE_VERSION("1.0");
  223. MODULE_ALIAS("platform:popmem-tm");