watchdog.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  2. #include <linux/init.h>
  3. #include <linux/io.h>
  4. #include <linux/kernel.h>
  5. #include <linux/module.h>
  6. #include <linux/moduleparam.h>
  7. #include <linux/types.h>
  8. #include <linux/fs.h>
  9. #include <linux/cdev.h>
  10. #include <linux/device.h>
  11. #include <linux/uaccess.h>
  12. #include <linux/timer.h>
  13. #define WATCHDOG_NAME "IT87 WDT"
  14. #define DEVICE_NAME "watchdog"
  15. #define CLASS_NAME "watchdog_class"
  16. /* Defaults for Module Parameter */
  17. #define DEFAULT_TIMEOUT 60
  18. #define DEFAULT_TESTMODE 0
  19. /* IO Ports */
  20. #define REG 0x4e
  21. #define VAL 0x4f
  22. /* Logical device Numbers LDN */
  23. #define GPIO 0x07
  24. /* Configuration Registers and Functions */
  25. #define LDNREG 0x07
  26. #define CHIPID 0x20
  27. #define CHIPREV 0x22
  28. /* Chip Id numbers */
  29. #define NO_DEV_ID 0xffff
  30. #define IT8607_ID 0x8607
  31. #define IT8620_ID 0x8620
  32. #define IT8622_ID 0x8622
  33. #define IT8625_ID 0x8625
  34. #define IT8628_ID 0x8628
  35. #define IT8655_ID 0x8655
  36. #define IT8665_ID 0x8665
  37. #define IT8686_ID 0x8686
  38. #define IT8702_ID 0x8702
  39. #define IT8705_ID 0x8705
  40. #define IT8712_ID 0x8712
  41. #define IT8716_ID 0x8716
  42. #define IT8718_ID 0x8718
  43. #define IT8720_ID 0x8720
  44. #define IT8721_ID 0x8721
  45. #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
  46. #define IT8728_ID 0x8728
  47. #define IT8772_ID 0x8772
  48. #define IT8783_ID 0x8783
  49. #define IT8784_ID 0x8784
  50. #define IT8786_ID 0x8786
  51. /* GPIO Configuration Registers LDN=0x07 */
  52. #define WDTCTRL 0x71
  53. #define WDTCFG 0x72
  54. #define WDTVALLSB 0x73
  55. #define WDTVALMSB 0x74
  56. /* GPIO Bits WDTCFG */
  57. #define WDT_TOV1 0x80
  58. #define WDT_KRST 0x40
  59. #define WDT_TOVE 0x20
  60. #define WDT_PWROK 0x10 /* not in it8721 */
  61. #define WDT_INT_MASK 0x0f
  62. static unsigned int max_units, chip_type;
  63. static unsigned int timeout = DEFAULT_TIMEOUT;
  64. static int testmode = DEFAULT_TESTMODE;
  65. module_param(timeout, int, 0);
  66. MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
  67. __MODULE_STRING(DEFAULT_TIMEOUT));
  68. module_param(testmode, int, 0);
  69. MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
  70. __MODULE_STRING(DEFAULT_TESTMODE));
  71. /* Character device variables */
  72. static int major_number;
  73. static struct class *watchdog_class = NULL;
  74. static struct device *watchdog_device = NULL;
  75. /* Watchdog state: 0 = OFF, 1 = ON */
  76. static int watchdog_state = 0;
  77. static int watchdog_running = 0;
  78. static DEFINE_MUTEX(watchdog_mutex);
  79. /* Software timer for servicing watchdog */
  80. static struct timer_list watchdog_timer;
  81. extern struct kobject *vfiec_kobj;
  82. /* Superio Chip */
  83. static inline int superio_enter(void)
  84. {
  85. /*
  86. * Try to reserve REG and REG + 1 for exclusive access.
  87. */
  88. if (!request_muxed_region(REG, 2, WATCHDOG_NAME))
  89. return -EBUSY;
  90. outb(0x87, REG);
  91. outb(0x01, REG);
  92. outb(0x55, REG);
  93. outb(0xaa, REG);
  94. return 0;
  95. }
  96. static inline void superio_exit(void)
  97. {
  98. outb(0x02, REG);
  99. outb(0x02, VAL);
  100. release_region(REG, 2);
  101. }
  102. static inline void superio_select(int ldn)
  103. {
  104. outb(LDNREG, REG);
  105. outb(ldn, VAL);
  106. }
  107. static inline int superio_inb(int reg)
  108. {
  109. outb(reg, REG);
  110. return inb(VAL);
  111. }
  112. static inline void superio_outb(int val, int reg)
  113. {
  114. outb(reg, REG);
  115. outb(val, VAL);
  116. }
  117. static inline int superio_inw(int reg)
  118. {
  119. int val;
  120. outb(reg++, REG);
  121. val = inb(VAL) << 8;
  122. outb(reg, REG);
  123. val |= inb(VAL);
  124. return val;
  125. }
  126. /* Internal function, should be called after superio_select(GPIO) */
  127. static void _wdt_update_timeout(unsigned int t)
  128. {
  129. unsigned char cfg = WDT_KRST;
  130. if (testmode)
  131. cfg = 0;
  132. if (t <= max_units)
  133. cfg |= WDT_TOV1;
  134. else
  135. t /= 60;
  136. if (chip_type != IT8721_ID)
  137. cfg |= WDT_PWROK;
  138. superio_outb(cfg, WDTCFG);
  139. superio_outb(t, WDTVALLSB);
  140. if (max_units > 255)
  141. superio_outb(t >> 8, WDTVALMSB);
  142. else
  143. superio_outb(0, WDTVALMSB);
  144. }
  145. static int wdt_update_timeout(unsigned int t)
  146. {
  147. int ret;
  148. ret = superio_enter();
  149. if (ret)
  150. return ret;
  151. superio_select(GPIO);
  152. _wdt_update_timeout(t);
  153. superio_exit();
  154. return 0;
  155. }
  156. static int wdt_round_time(int t)
  157. {
  158. t += 59;
  159. t -= t % 60;
  160. return t;
  161. }
  162. /* Software timer callback - service the watchdog */
  163. static void watchdog_timer_callback(struct timer_list *t)
  164. {
  165. watchdog_running++;
  166. if(watchdog_running >= (timeout/2))
  167. {
  168. /* Re-trigger the hardware watchdog by writing timeout again */
  169. wdt_update_timeout(timeout);
  170. watchdog_running = 0;
  171. }
  172. /* Restart timer (periodic servicing, e.g., every half timeout) */
  173. mod_timer(&watchdog_timer, jiffies + HZ);
  174. }
  175. /* Enable watchdog - start hardware and software timer */
  176. static int watchdog_enable(void)
  177. {
  178. int ret;
  179. pr_info("Enabling watchdog timer\n");
  180. ret = wdt_update_timeout(timeout);
  181. if (ret) {
  182. pr_err("Failed to set watchdog timeout\n");
  183. return ret;
  184. }
  185. /* Start periodic software timer to service watchdog */
  186. timer_setup(&watchdog_timer, watchdog_timer_callback, 0);
  187. mod_timer(&watchdog_timer, jiffies + HZ);
  188. return 0;
  189. }
  190. /* Disable watchdog - stop hardware and software timer */
  191. static int watchdog_disable(void)
  192. {
  193. pr_info("Disabling watchdog timer\n");
  194. /* Stop and delete software timer */
  195. del_timer_sync(&watchdog_timer);
  196. watchdog_running = 0;
  197. /* Disable hardware watchdog by setting timeout to 0 */
  198. return wdt_update_timeout(0);
  199. }
  200. /* Parse user command: supports "ON", "OFF", "1", "0" */
  201. static int parse_watchdog_command(const char *buf, size_t count)
  202. {
  203. /* Skip whitespace */
  204. while (count > 0 && (*buf == ' ' || *buf == '\t' || *buf == '\n' || *buf == '\r')) {
  205. buf++;
  206. count--;
  207. }
  208. if (count == 0)
  209. return -1;
  210. /* Check for numeric value */
  211. if (count == 1 && (buf[0] == '0' || buf[0] == '1')) {
  212. return buf[0] - '0';
  213. }
  214. if (count == 1 && (buf[0] == 0 || buf[0] == 1)) {
  215. return buf[0];
  216. }
  217. /* Check for "ON" or "OFF" (case insensitive) */
  218. if (count >= 2) {
  219. if ((buf[0] == 'O' || buf[0] == 'o') &&
  220. (buf[1] == 'N' || buf[1] == 'n')) {
  221. return 1;
  222. }
  223. if (count >= 3 &&
  224. (buf[0] == 'O' || buf[0] == 'o') &&
  225. (buf[1] == 'F' || buf[1] == 'f') &&
  226. (buf[2] == 'F' || buf[2] == 'f')) {
  227. return 0;
  228. }
  229. }
  230. return -1;
  231. }
  232. /* Character device file operations */
  233. static ssize_t watchdog_read(struct file *file, char __user *user_buf,
  234. size_t count, loff_t *ppos)
  235. {
  236. char status_buf[64];
  237. int len;
  238. // if (*ppos > 0)
  239. // return 0;
  240. mutex_lock(&watchdog_mutex);
  241. if (watchdog_state)
  242. len = snprintf(status_buf, sizeof(status_buf),
  243. "The watchdog is on\nThe args value is 1\n");
  244. else
  245. len = snprintf(status_buf, sizeof(status_buf),
  246. "The watchdog is off\nThe args value is 0\n");
  247. memset(status_buf, 0, sizeof(status_buf));
  248. if( watchdog_state == 1)
  249. {
  250. status_buf[0] = 1;
  251. }
  252. else
  253. {
  254. status_buf[0] = 0;
  255. }
  256. len = 1;
  257. mutex_unlock(&watchdog_mutex);
  258. if (copy_to_user(user_buf, status_buf, len))
  259. return -EFAULT;
  260. // *ppos += len;
  261. return len;
  262. }
  263. static ssize_t watchdog_write(struct file *file, const char __user *user_buf,
  264. size_t count, loff_t *ppos)
  265. {
  266. char buf[16];
  267. int cmd;
  268. int ret = count;
  269. if (count == 0 || count >= sizeof(buf))
  270. return -EINVAL;
  271. if (copy_from_user(buf, user_buf, count))
  272. return -EFAULT;
  273. buf[count] = '\0';
  274. cmd = parse_watchdog_command(buf, count);
  275. if (cmd < 0)
  276. return -EINVAL;
  277. mutex_lock(&watchdog_mutex);
  278. if (cmd == watchdog_state) {
  279. /* No state change */
  280. if (cmd)
  281. pr_info("Watchdog is already on\n");
  282. else
  283. pr_info("Watchdog is already off\n");
  284. } else {
  285. if (cmd) {
  286. /* Turn ON */
  287. if (watchdog_enable() == 0) {
  288. watchdog_state = 1;
  289. pr_info("Watchdog turned on successfully\n");
  290. } else {
  291. ret = -EIO;
  292. }
  293. } else {
  294. /* Turn OFF */
  295. if (watchdog_disable() == 0) {
  296. watchdog_state = 0;
  297. pr_info("Watchdog turned off successfully\n");
  298. } else {
  299. ret = -EIO;
  300. }
  301. }
  302. }
  303. mutex_unlock(&watchdog_mutex);
  304. return ret;
  305. }
  306. static int watchdog_open(struct inode *inode, struct file *file)
  307. {
  308. return 0;
  309. }
  310. static int watchdog_release(struct inode *inode, struct file *file)
  311. {
  312. return 0;
  313. }
  314. static const struct file_operations watchdog_fops = {
  315. .owner = THIS_MODULE,
  316. .read = watchdog_read,
  317. .write = watchdog_write,
  318. .open = watchdog_open,
  319. .release = watchdog_release,
  320. };
  321. static char *my_devnode(struct device *dev, umode_t *mode) {
  322. if (mode) {
  323. *mode = 0666;
  324. }
  325. return NULL;
  326. }
  327. static ssize_t watchdog_show(struct kobject *kobj, struct kobj_attribute *attr,
  328. char *buf)
  329. {
  330. return sprintf(buf, "%d\n", watchdog_state);
  331. }
  332. static ssize_t watchdog_store(struct kobject *kobj, struct kobj_attribute *attr,
  333. const char *buf, size_t count)
  334. {
  335. int cmd;
  336. int ret = count;
  337. // if (count == 0 || count >= sizeof(buf))
  338. // return -EINVAL;
  339. // if (strscpy(buf, user_buf, count) < 0)
  340. // return -EFAULT;
  341. // buf[count] = '\0';
  342. cmd = parse_watchdog_command(buf, count);
  343. if (cmd < 0)
  344. return -EINVAL;
  345. mutex_lock(&watchdog_mutex);
  346. if (cmd == watchdog_state) {
  347. /* No state change */
  348. if (cmd)
  349. pr_info("Watchdog is already on\n");
  350. else
  351. pr_info("Watchdog is already off\n");
  352. } else {
  353. if (cmd) {
  354. /* Turn ON */
  355. if (watchdog_enable() == 0) {
  356. watchdog_state = 1;
  357. pr_info("Watchdog turned on successfully\n");
  358. } else {
  359. ret = -EIO;
  360. }
  361. } else {
  362. /* Turn OFF */
  363. if (watchdog_disable() == 0) {
  364. watchdog_state = 0;
  365. pr_info("Watchdog turned off successfully\n");
  366. } else {
  367. ret = -EIO;
  368. }
  369. }
  370. }
  371. mutex_unlock(&watchdog_mutex);
  372. return ret;
  373. }
  374. static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
  375. char *buf)
  376. {
  377. return sprintf(buf, "%d\n", watchdog_state);
  378. }
  379. static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
  380. const char *buf, size_t count)
  381. {
  382. return -EINVAL;
  383. }
  384. static ssize_t timeleft_show(struct kobject *kobj, struct kobj_attribute *attr,
  385. char *buf)
  386. {
  387. if(watchdog_state == 1)
  388. {
  389. return sprintf(buf, "%d\n", timeout - watchdog_running);
  390. }
  391. else
  392. {
  393. return sprintf(buf, "%d\n", 0);
  394. }
  395. }
  396. static ssize_t timeleft_store(struct kobject *kobj, struct kobj_attribute *attr,
  397. const char *buf, size_t count)
  398. {
  399. return -EINVAL;
  400. }
  401. static struct kobj_attribute state_attr =
  402. __ATTR(state, 0444, state_show, state_store);
  403. static struct kobj_attribute timeleft_attr =
  404. __ATTR(timeleft, 0444, timeleft_show, timeleft_store);
  405. static struct kobj_attribute watchdog_attr =
  406. __ATTR(watchdog, 0644, watchdog_show, watchdog_store);
  407. static struct attribute *watchdog_attrs[] = {
  408. &state_attr.attr,
  409. &timeleft_attr.attr,
  410. &watchdog_attr.attr,
  411. NULL,
  412. };
  413. static struct attribute_group watchdog_attr_group = {
  414. .attrs = watchdog_attrs,
  415. };
  416. static struct kobject *watchdog_kobj;
  417. int watchdog_init(void)
  418. {
  419. u8 chip_rev;
  420. int rc;
  421. watchdog_kobj = kobject_create_and_add("watchdog", vfiec_kobj);
  422. if (!watchdog_kobj)
  423. {
  424. rc = -ENOMEM;
  425. return -1;
  426. }
  427. rc = sysfs_create_group(watchdog_kobj, &watchdog_attr_group);
  428. if (rc)
  429. {
  430. kobject_put(watchdog_kobj);
  431. pr_err("Faiec_version to create sysfs group: %d\n", rc);
  432. return -1;
  433. }
  434. rc = superio_enter();
  435. if (rc)
  436. return rc;
  437. chip_type = superio_inw(CHIPID);
  438. chip_rev = superio_inb(CHIPREV) & 0x0f;
  439. superio_exit();
  440. switch (chip_type) {
  441. case IT8702_ID:
  442. max_units = 255;
  443. break;
  444. case IT8712_ID:
  445. max_units = (chip_rev < 8) ? 255 : 65535;
  446. break;
  447. case IT8716_ID:
  448. case IT8726_ID:
  449. max_units = 65535;
  450. break;
  451. case IT8607_ID:
  452. case IT8620_ID:
  453. case IT8622_ID:
  454. case IT8625_ID:
  455. case IT8628_ID:
  456. case IT8655_ID:
  457. case IT8665_ID:
  458. case IT8686_ID:
  459. case IT8718_ID:
  460. case IT8720_ID:
  461. case IT8721_ID:
  462. case IT8728_ID:
  463. case IT8772_ID:
  464. case IT8783_ID:
  465. case IT8784_ID:
  466. case IT8786_ID:
  467. max_units = 65535;
  468. break;
  469. case IT8705_ID:
  470. pr_err("Unsupported Chip found, Chip %04x Revision %02x\n",
  471. chip_type, chip_rev);
  472. return -ENODEV;
  473. case NO_DEV_ID:
  474. pr_err("no device\n");
  475. return -ENODEV;
  476. default:
  477. pr_err("Unknown Chip found, Chip %04x Revision %04x\n",
  478. chip_type, chip_rev);
  479. return -ENODEV;
  480. }
  481. rc = superio_enter();
  482. if (rc)
  483. return rc;
  484. superio_select(GPIO);
  485. superio_outb(WDT_TOV1, WDTCFG);
  486. superio_outb(0x00, WDTCTRL);
  487. superio_exit();
  488. if (timeout < 1 || timeout > max_units * 60) {
  489. timeout = DEFAULT_TIMEOUT;
  490. pr_warn("Timeout value out of range, use default %d sec\n",
  491. DEFAULT_TIMEOUT);
  492. }
  493. if (timeout > max_units)
  494. timeout = wdt_round_time(timeout);
  495. /* Register character device */
  496. major_number = register_chrdev(0, DEVICE_NAME, &watchdog_fops);
  497. if (major_number < 0) {
  498. pr_err("Failed to register character device\n");
  499. return major_number;
  500. }
  501. /* Create device class */
  502. watchdog_class = class_create(THIS_MODULE, CLASS_NAME);
  503. if (IS_ERR(watchdog_class)) {
  504. unregister_chrdev(major_number, DEVICE_NAME);
  505. pr_err("Failed to create device class\n");
  506. return PTR_ERR(watchdog_class);
  507. }
  508. watchdog_class->devnode = my_devnode;
  509. /* Create device node /dev/watchdog */
  510. watchdog_device = device_create(watchdog_class, NULL,
  511. MKDEV(major_number, 0),
  512. NULL, DEVICE_NAME);
  513. if (IS_ERR(watchdog_device)) {
  514. class_destroy(watchdog_class);
  515. unregister_chrdev(major_number, DEVICE_NAME);
  516. pr_err("Failed to create device node\n");
  517. return PTR_ERR(watchdog_device);
  518. }
  519. /* Initialize state */
  520. watchdog_state = 0;
  521. /* Initialize timer */
  522. timer_setup(&watchdog_timer, watchdog_timer_callback, 0);
  523. pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (testmode=%d)\n",
  524. chip_type, chip_rev, timeout, testmode);
  525. pr_info("Device /dev/watchdog created. Default state: OFF\n");
  526. return 0;
  527. }
  528. void watchdog_exit(void)
  529. {
  530. /* Ensure watchdog is disabled before exit */
  531. if (watchdog_state) {
  532. watchdog_disable();
  533. watchdog_state = 0;
  534. }
  535. /* Delete timer */
  536. del_timer_sync(&watchdog_timer);
  537. sysfs_remove_group(watchdog_kobj, &watchdog_attr_group);
  538. kobject_put(watchdog_kobj);
  539. /* Remove device */
  540. device_destroy(watchdog_class, MKDEV(major_number, 0));
  541. class_destroy(watchdog_class);
  542. unregister_chrdev(major_number, DEVICE_NAME);
  543. pr_info("Watchdog driver exited\n");
  544. }