voltage_sysfs.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/kobject.h>
  5. #include <linux/sysfs.h>
  6. #include <linux/acpi.h>
  7. #include <linux/io.h>
  8. #include <linux/delay.h>
  9. #include "gpioregs.h"
  10. extern struct kobject *hwmon_kobj;
  11. /* Helper functions for IO access */
  12. static uint8_t hwm_read_reg(uint16_t hwm_base, uint8_t reg)
  13. {
  14. outb(reg, hwm_base + HWM_INDEX_OFFSET);
  15. return inb(hwm_base + HWM_DATA_OFFSET);
  16. }
  17. static void hwm_write_reg(uint16_t hwm_base, uint8_t reg, uint8_t val)
  18. {
  19. outb(reg, hwm_base + HWM_INDEX_OFFSET);
  20. outb(val, hwm_base + HWM_DATA_OFFSET);
  21. }
  22. static uint8_t hwm_read_reg_retry(uint16_t hwm_base, uint8_t reg)
  23. {
  24. uint8_t v = hwm_read_reg(hwm_base, reg);
  25. if (v == 0xFF) {
  26. v = hwm_read_reg(hwm_base, reg);
  27. }
  28. return v;
  29. }
  30. static int vin_raw_to_volt(uint8_t raw, int r_top_kohm, int r_bottom_kohm)
  31. {
  32. int vm = raw * 11;
  33. if (r_top_kohm > 0 && r_bottom_kohm > 0) {
  34. vm = (vm * (r_top_kohm + r_bottom_kohm)) / r_bottom_kohm;
  35. }
  36. return vm;
  37. }
  38. static int ec_raw_to_volt(uint8_t raw, int r_top_kohm, int r_bottom_kohm)
  39. {
  40. int vm = raw * 12; /* EC unit: 10mV */
  41. vm = (vm * (r_top_kohm + r_bottom_kohm)) / r_bottom_kohm;
  42. return vm ;
  43. }
  44. static int ec_wait_ibf(void)
  45. {
  46. int i = 0;
  47. while (inb(EC_CMD_PORT) & EC_IBF) {
  48. if (++i > TIMEOUT_LOOPS) {
  49. printk("Error: EC IBF Timeout!\n");
  50. return -1;
  51. }
  52. udelay(1);
  53. }
  54. return 0;
  55. }
  56. static int ec_wait_obf(void)
  57. {
  58. int i = 0;
  59. while (!(inb(EC_CMD_PORT) & EC_OBF)) {
  60. if (++i > TIMEOUT_LOOPS) {
  61. printk("Error: EC OBF Timeout!\n");
  62. return -1;
  63. }
  64. udelay(1);
  65. }
  66. return 0;
  67. }
  68. static int wait_ibf(void)
  69. {
  70. int i = 0;
  71. while (inb(EC_CMD_PORT) & EC_IBF)
  72. {
  73. if (++i > TIMEOUT_LOOPS)
  74. {
  75. return -1;
  76. }
  77. udelay(1);
  78. }
  79. return 0;
  80. }
  81. static int wait_obf(void)
  82. {
  83. int i = 0;
  84. while (!(inb(EC_CMD_PORT) & EC_OBF))
  85. {
  86. if (++i > TIMEOUT_LOOPS)
  87. {
  88. return -1;
  89. }
  90. udelay(1);
  91. }
  92. return 0;
  93. }
  94. static int ec_read_ram(uint8_t offset, uint8_t *data)
  95. {
  96. if (wait_ibf() < 0)
  97. return -1;
  98. outb(CMD_READ_RAM, EC_CMD_PORT);
  99. if (wait_ibf() < 0)
  100. return -1;
  101. outb(offset, EC_DATA_PORT);
  102. if (wait_obf() < 0)
  103. return -1;
  104. *data = inb(EC_DATA_PORT);
  105. return 0;
  106. }
  107. static int ec_write_ram(uint8_t offset, uint8_t data)
  108. {
  109. if (wait_ibf() < 0)
  110. return -1;
  111. outb(CMD_WRITE_RAM, EC_CMD_PORT);
  112. if (wait_ibf() < 0)
  113. return -1;
  114. outb(offset, EC_DATA_PORT);
  115. if (wait_ibf() < 0)
  116. return -1;
  117. outb(data, EC_DATA_PORT);
  118. return 0;
  119. }
  120. static int oem_ec_read_ram(uint8_t page, uint8_t offset, uint8_t *data)
  121. {
  122. unsigned char WEC, REC;
  123. switch(page)
  124. {
  125. case 0:
  126. {
  127. WEC = 0x96;
  128. REC = 0x95;
  129. break;
  130. }
  131. case 1:
  132. {
  133. WEC = 0x98;
  134. REC = 0x97;
  135. break;
  136. }
  137. default:
  138. {
  139. WEC = 0x81;
  140. REC = 0x80;
  141. break;
  142. }
  143. }
  144. if (wait_ibf() < 0)
  145. return -1;
  146. outb(REC, EC_CMD_PORT);
  147. if (wait_ibf() < 0)
  148. return -1;
  149. outb(offset, EC_DATA_PORT);
  150. if (wait_obf() < 0)
  151. return -1;
  152. *data = inb(EC_DATA_PORT);
  153. return 0;
  154. }
  155. static int oem_ec_write_ram(uint8_t page, uint8_t offset, uint8_t data)
  156. {
  157. unsigned char WEC, REC;
  158. switch(page)
  159. {
  160. case 0:
  161. {
  162. WEC = 0x96;
  163. REC = 0x95;
  164. break;
  165. }
  166. case 1:
  167. {
  168. WEC = 0x98;
  169. REC = 0x97;
  170. break;
  171. }
  172. default:
  173. {
  174. WEC = 0x81;
  175. REC = 0x80;
  176. break;
  177. }
  178. }
  179. if (wait_ibf() < 0)
  180. return -1;
  181. outb(WEC, EC_CMD_PORT);
  182. if (wait_ibf() < 0)
  183. return -1;
  184. outb(offset, EC_DATA_PORT);
  185. if (wait_ibf() < 0)
  186. return -1;
  187. outb(data, EC_DATA_PORT);
  188. return 0;
  189. }
  190. static ssize_t voltage_5v_show(struct kobject *kobj, struct kobj_attribute *attr,
  191. char *buf)
  192. {
  193. int vlotage = 0;
  194. uint8_t raw;
  195. raw = hwm_read_reg_retry(IT8786_HWM_BASE_DEFAULT, 0x22);
  196. vlotage = vin_raw_to_volt(raw, 3, 2);
  197. return sprintf(buf, "%d\n", vlotage);
  198. }
  199. static ssize_t voltage_5v_store(struct kobject *kobj, struct kobj_attribute *attr,
  200. const char *buf, size_t count)
  201. {
  202. return -EINVAL;
  203. }
  204. static ssize_t voltage_vcore_show(struct kobject *kobj, struct kobj_attribute *attr,
  205. char *buf)
  206. {
  207. int vlotage = 0;
  208. uint8_t raw;
  209. raw = hwm_read_reg_retry(IT8786_HWM_BASE_DEFAULT, 0x20);
  210. vlotage = vin_raw_to_volt(raw, 0, 1);
  211. return sprintf(buf, "%d\n", vlotage);
  212. }
  213. static ssize_t voltage_vcore_store(struct kobject *kobj, struct kobj_attribute *attr,
  214. const char *buf, size_t count)
  215. {
  216. return -EINVAL;
  217. }
  218. static ssize_t voltage_12v_show(struct kobject *kobj, struct kobj_attribute *attr,
  219. char *buf)
  220. {
  221. int vlotage = 0;
  222. uint8_t raw;
  223. if(oem_ec_read_ram(0x00, 0x6a, &raw) < 0)
  224. {
  225. return -1;
  226. }
  227. // raw = hwm_read_reg_retry(IT8786_HWM_BASE_DEFAULT, 0x6a);
  228. vlotage = ec_raw_to_volt(raw, 10, 2);
  229. return sprintf(buf, "%d\n", vlotage);
  230. }
  231. static ssize_t voltage_12v_store(struct kobject *kobj, struct kobj_attribute *attr,
  232. const char *buf, size_t count)
  233. {
  234. return -EINVAL;
  235. }
  236. static struct kobj_attribute voltage_5v_attr =
  237. __ATTR(voltage_5v, 0444, voltage_5v_show, voltage_5v_store);
  238. static struct kobj_attribute voltage_vcorev_attr =
  239. __ATTR(voltage_vcore, 0444, voltage_vcore_show, voltage_vcore_store);
  240. static struct kobj_attribute voltage_12v_attr =
  241. __ATTR(voltage_12v, 0444, voltage_12v_show, voltage_12v_store);
  242. static struct attribute *voltage_sysfs_attrs[] = {
  243. &voltage_5v_attr.attr,
  244. &voltage_vcorev_attr.attr,
  245. &voltage_12v_attr.attr,
  246. NULL,
  247. };
  248. static struct attribute_group voltage_sysfs_attr_group = {
  249. .attrs = voltage_sysfs_attrs,
  250. };
  251. int voltage_sysfs_init(void)
  252. {
  253. int ret = 0;
  254. ret = sysfs_create_group(hwmon_kobj, &voltage_sysfs_attr_group);
  255. return ret;
  256. }
  257. void voltage_sysfs_exit(void)
  258. {
  259. sysfs_remove_group(hwmon_kobj, &voltage_sysfs_attr_group);
  260. }