sch311x.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. /* $OpenBSD: sch311x.c,v 1.15 2015/03/14 03:38:47 jsg Exp $ */
  2. /*
  3. * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org>
  4. * Copyright (c) 2009 Michael Knudsen <mk@openbsd.org>
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /*
  19. * SMSC SCH3112, SCH3114, and SCH3116 LPC Super I/O driver.
  20. */
  21. #include <sys/param.h>
  22. #include <sys/device.h>
  23. #include <sys/kernel.h>
  24. #include <sys/systm.h>
  25. #include <sys/types.h>
  26. #include <sys/sensors.h>
  27. #include <machine/bus.h>
  28. #include <dev/isa/isavar.h>
  29. /* Device identifiers */
  30. #define SCHSIO_ID_SCH3112 0x7c
  31. #define SCHSIO_ID_SCH3114 0x7d
  32. #define SCHSIO_ID_SCH3116 0x7f
  33. #define SCHSIO_IOSIZE 0x02
  34. #define SCHSIO_PORT_CONFIG 0x00
  35. /* These are used in configuration mode */
  36. #define SCHSIO_PORT_INDEX 0x00
  37. #define SCHSIO_PORT_DATA 0x01
  38. #define SCHSIO_CONFIG_ENTER 0x55
  39. #define SCHSIO_CONFIG_LEAVE 0xaa
  40. /* Register definitions */
  41. #define SCHSIO_IDX_LDEVSEL 0x07 /* Logical device select */
  42. #define SCHSIO_IDX_DEVICE 0x20 /* Device ID */
  43. #define SCHSIO_IDX_REV 0x21 /* Device revision */
  44. #define SCHSIO_IDX_BASE_HI 0x60 /* Configuration base address */
  45. #define SCHSIO_IDX_BASE_LO 0x61
  46. /* Logical devices */
  47. #define SCHSIO_LDEV_RUNTIME 0x0a /* holds wdog and sensors */
  48. #define SCHSIO_LDEV_RUNTIME_SZ 0x100
  49. /* Hardware monitor */
  50. #define SCHSIO_HWM_INTERVAL 5 /* seconds */
  51. /* Register access */
  52. #define SCHSIO_HWM_INDEX 0x70
  53. #define SCHSIO_HWM_DATA 0x71
  54. /* Sensor definitions */
  55. /* Voltage */
  56. #define SCHSIO_HWM_VOLT1 0x20
  57. #define SCHSIO_HWM_VOLT2 0x21
  58. #define SCHSIO_HWM_VOLT3 0x22
  59. #define SCHSIO_HWM_VOLT4 0x23
  60. #define SCHSIO_HWM_VOLT5 0x24
  61. #define SCHSIO_HWM_VOLT6 0x99
  62. #define SCHSIO_HWM_VOLT7 0x9a
  63. /* Temperature */
  64. #define SCHSIO_HWM_TEMP1 0x26
  65. #define SCHSIO_HWM_TEMP2 0x25
  66. #define SCHSIO_HWM_TEMP3 0x27
  67. /* Fan speed */
  68. #define SCHSIO_HWM_TACH1_L 0x28
  69. #define SCHSIO_HWM_TACH1_U 0x29
  70. #define SCHSIO_HWM_TACH2_L 0x2a
  71. #define SCHSIO_HWM_TACH2_U 0x2b
  72. #define SCHSIO_HWM_TACH3_L 0x2c
  73. #define SCHSIO_HWM_TACH3_U 0x2d
  74. /* 11111 = 90kHz * 10^9 */
  75. #define SCHSIO_FAN_RPM(x) (1000000000 / ((x) * 11111) * 60)
  76. #define SCHSIO_CONV_VOLT1 66400
  77. #define SCHSIO_CONV_VOLT2 20000
  78. #define SCHSIO_CONV_VOLT3 43800
  79. #define SCHSIO_CONV_VOLT4 66400
  80. #define SCHSIO_CONV_VOLT5 160000
  81. #define SCHSIO_CONV_VOLT6 43800
  82. #define SCHSIO_CONV_VOLT7 43800
  83. #define SCHSIO_VOLT_MUV(x, k) (1000000 * (x) / 2560000 * (k))
  84. #define SCHSIO_TEMP_MUK(x) (((x) + 273) * 1000000)
  85. #define SCHSIO_SENSORS 13
  86. #define SCHSIO_SENSOR_FAN1 0
  87. #define SCHSIO_SENSOR_FAN2 1
  88. #define SCHSIO_SENSOR_FAN3 2
  89. #define SCHSIO_SENSOR_VOLT1 3
  90. #define SCHSIO_SENSOR_VOLT2 4
  91. #define SCHSIO_SENSOR_VOLT3 5
  92. #define SCHSIO_SENSOR_VOLT4 6
  93. #define SCHSIO_SENSOR_VOLT5 7
  94. #define SCHSIO_SENSOR_VOLT6 8
  95. #define SCHSIO_SENSOR_VOLT7 9
  96. #define SCHSIO_SENSOR_TEMP1 10
  97. #define SCHSIO_SENSOR_TEMP2 11
  98. #define SCHSIO_SENSOR_TEMP3 12
  99. /* Watchdog */
  100. /* Register access */
  101. #define SCHSIO_WDT_GPIO 0x47
  102. #define SCHSIO_WDT_TIMEOUT 0x65
  103. #define SCHSIO_WDT_VAL 0x66
  104. #define SCHSIO_WDT_CFG 0x67
  105. #define SCHSIO_WDT_CTRL 0x68
  106. /* Bits */
  107. #define SCHSIO_WDT_GPIO_MASK 0x0f
  108. #define SCHSIO_WDT_GPIO_OUT 0x0e
  109. #define SCHSIO_WDT_TO_SECONDS (1 << 7)
  110. #define SCHSIO_WDT_CTRL_TRIGGERED (1 << 0)
  111. #define SCHSIO_WDT_CFG_KBDEN (1 << 1)
  112. #define SCHSIO_WDT_CFG_MSEN (1 << 2)
  113. /* autoconf(9) flags etc. */
  114. #define SCHSIO_CFFLAGS_WDTEN (1 << 0)
  115. #define DEVNAME(x) ((x)->sc_dev.dv_xname)
  116. struct schsio_softc {
  117. struct device sc_dev;
  118. bus_space_tag_t sc_iot;
  119. bus_space_handle_t sc_ioh;
  120. bus_space_handle_t sc_ioh_rr;
  121. struct ksensordev sc_sensordev;
  122. struct ksensor sc_sensor[SCHSIO_SENSORS];
  123. };
  124. int schsio_probe(struct device *, void *, void *);
  125. void schsio_attach(struct device *, struct device *, void *);
  126. int schsio_activate(struct device *, int);
  127. static __inline void schsio_config_enable(bus_space_tag_t iot,
  128. bus_space_handle_t ioh);
  129. static __inline void schsio_config_disable(bus_space_tag_t iot,
  130. bus_space_handle_t ioh);
  131. u_int8_t schsio_config_read(bus_space_tag_t iot, bus_space_handle_t ioh,
  132. u_int8_t reg);
  133. void schsio_config_write(bus_space_tag_t iot, bus_space_handle_t ioh,
  134. u_int8_t reg, u_int8_t val);
  135. /* HWM prototypes */
  136. void schsio_hwm_init(struct schsio_softc *sc);
  137. void schsio_hwm_update(void *arg);
  138. u_int8_t schsio_hwm_read(struct schsio_softc *sc, u_int8_t reg);
  139. /* Watchdog prototypes */
  140. void schsio_wdt_init(struct schsio_softc *sc);
  141. int schsio_wdt_cb(void *arg, int period);
  142. struct cfattach schsio_ca = {
  143. sizeof(struct schsio_softc),
  144. schsio_probe,
  145. schsio_attach,
  146. NULL,
  147. schsio_activate
  148. };
  149. struct cfdriver schsio_cd = {
  150. NULL, "schsio", DV_DULL
  151. };
  152. static __inline void
  153. schsio_config_enable(bus_space_tag_t iot, bus_space_handle_t ioh)
  154. {
  155. bus_space_write_1(iot, ioh, SCHSIO_PORT_CONFIG, SCHSIO_CONFIG_ENTER);
  156. }
  157. static __inline void
  158. schsio_config_disable(bus_space_tag_t iot, bus_space_handle_t ioh)
  159. {
  160. bus_space_write_1(iot, ioh, SCHSIO_PORT_CONFIG, SCHSIO_CONFIG_LEAVE);
  161. }
  162. u_int8_t
  163. schsio_config_read(bus_space_tag_t iot, bus_space_handle_t ioh,
  164. u_int8_t reg)
  165. {
  166. bus_space_write_1(iot, ioh, SCHSIO_PORT_INDEX, reg);
  167. return (bus_space_read_1(iot, ioh, SCHSIO_PORT_DATA));
  168. }
  169. void
  170. schsio_config_write(bus_space_tag_t iot, bus_space_handle_t ioh,
  171. u_int8_t reg, u_int8_t val)
  172. {
  173. bus_space_write_1(iot, ioh, SCHSIO_PORT_INDEX, reg);
  174. bus_space_write_1(iot, ioh, SCHSIO_PORT_DATA, val);
  175. }
  176. int
  177. schsio_probe(struct device *parent, void *match, void *aux)
  178. {
  179. struct isa_attach_args *ia = aux;
  180. bus_space_tag_t iot;
  181. bus_space_handle_t ioh;
  182. u_int8_t reg;
  183. /* Match by device ID */
  184. iot = ia->ia_iot;
  185. if (bus_space_map(iot, ia->ipa_io[0].base, SCHSIO_IOSIZE, 0, &ioh))
  186. return (0);
  187. schsio_config_enable(iot, ioh);
  188. reg = schsio_config_read(iot, ioh, SCHSIO_IDX_DEVICE);
  189. schsio_config_disable(iot, ioh);
  190. bus_space_unmap(iot, ia->ipa_io[0].base, SCHSIO_IOSIZE);
  191. switch (reg) {
  192. case SCHSIO_ID_SCH3112:
  193. case SCHSIO_ID_SCH3114:
  194. case SCHSIO_ID_SCH3116:
  195. ia->ipa_nio = 1;
  196. ia->ipa_io[0].length = SCHSIO_IOSIZE;
  197. ia->ipa_nmem = 0;
  198. ia->ipa_nirq = 0;
  199. ia->ipa_ndrq = 0;
  200. ia->ia_aux = (void *)(u_long) reg;
  201. return (1);
  202. break;
  203. }
  204. return (0);
  205. }
  206. void
  207. schsio_attach(struct device *parent, struct device *self, void *aux)
  208. {
  209. struct schsio_softc *sc = (void *)self;
  210. struct isa_attach_args *ia = aux;
  211. u_int16_t iobase;
  212. u_int8_t reg0, reg1;
  213. /* Map ISA I/O space */
  214. sc->sc_iot = ia->ia_iot;
  215. if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base,
  216. SCHSIO_IOSIZE, 0, &sc->sc_ioh)) {
  217. printf(": can't map i/o space\n");
  218. return;
  219. }
  220. /* Enter configuration mode */
  221. schsio_config_enable(sc->sc_iot, sc->sc_ioh);
  222. /* Check device ID */
  223. reg0 = (u_int8_t)(u_long) ia->ia_aux;
  224. switch (reg0) {
  225. case SCHSIO_ID_SCH3112:
  226. printf(": SCH3112");
  227. break;
  228. case SCHSIO_ID_SCH3114:
  229. printf(": SCH3114");
  230. break;
  231. case SCHSIO_ID_SCH3116:
  232. printf(": SCH3116");
  233. break;
  234. }
  235. /* Read device revision */
  236. reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_REV);
  237. printf(" rev 0x%02x", reg0);
  238. /* Select runtime registers logical device */
  239. schsio_config_write(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_LDEVSEL,
  240. SCHSIO_LDEV_RUNTIME);
  241. reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh,
  242. SCHSIO_IDX_BASE_HI);
  243. reg1 = schsio_config_read(sc->sc_iot, sc->sc_ioh,
  244. SCHSIO_IDX_BASE_LO);
  245. iobase = (reg0 << 8) | reg1;
  246. if (bus_space_map(sc->sc_iot, iobase, SCHSIO_LDEV_RUNTIME_SZ,
  247. 0, &sc->sc_ioh_rr)) {
  248. printf(": can't map i/o space\n");
  249. return;
  250. }
  251. schsio_wdt_init(sc);
  252. schsio_hwm_init(sc);
  253. printf("\n");
  254. /* Escape from configuration mode */
  255. schsio_config_disable(sc->sc_iot, sc->sc_ioh);
  256. }
  257. int
  258. schsio_activate(struct device *self, int act)
  259. {
  260. switch (act) {
  261. case DVACT_POWERDOWN:
  262. wdog_shutdown(self);
  263. break;
  264. }
  265. return (0);
  266. }
  267. void
  268. schsio_hwm_init(struct schsio_softc *sc)
  269. {
  270. int i;
  271. /* Set up sensors */
  272. for (i = SCHSIO_SENSOR_FAN1; i < SCHSIO_SENSOR_FAN3 + 1; i++)
  273. sc->sc_sensor[i].type = SENSOR_FANRPM;
  274. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT1].desc, "+2.5V",
  275. sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT1].desc));
  276. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT2].desc, "+1.5V (Vccp)",
  277. sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT2].desc));
  278. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT3].desc, "+3.3V (VCC)",
  279. sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT3].desc));
  280. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT4].desc, "+5V",
  281. sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT4].desc));
  282. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT5].desc, "+12V",
  283. sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT5].desc));
  284. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT6].desc, "+3.3V (VTR)",
  285. sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT6].desc));
  286. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT7].desc, "+3V (Vbat)",
  287. sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT7].desc));
  288. for (i = SCHSIO_SENSOR_VOLT1; i < SCHSIO_SENSOR_VOLT7 + 1; i++)
  289. sc->sc_sensor[i].type = SENSOR_VOLTS_DC;
  290. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP1].desc, "Internal",
  291. sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP1].desc));
  292. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP2].desc, "Remote",
  293. sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP2].desc));
  294. strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP3].desc, "Remote",
  295. sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP3].desc));
  296. for (i = SCHSIO_SENSOR_TEMP1; i < SCHSIO_SENSOR_TEMP3 + 1; i++)
  297. sc->sc_sensor[i].type = SENSOR_TEMP;
  298. strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
  299. sizeof(sc->sc_sensordev.xname));
  300. for (i = 0; i < SCHSIO_SENSORS; i++)
  301. sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  302. if (sensor_task_register(sc, schsio_hwm_update,
  303. SCHSIO_HWM_INTERVAL) == NULL) {
  304. printf(": unable to register update task");
  305. return;
  306. }
  307. sensordev_install(&sc->sc_sensordev);
  308. }
  309. void
  310. schsio_hwm_update(void *arg)
  311. {
  312. struct schsio_softc *sc;
  313. u_int16_t tach;
  314. int8_t temp;
  315. u_int8_t volt;
  316. u_int8_t reg0, reg1;
  317. sc = (struct schsio_softc *)arg;
  318. reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_L);
  319. reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_U);
  320. tach = (reg1 << 8) | reg0;
  321. sc->sc_sensor[SCHSIO_SENSOR_FAN1].value = SCHSIO_FAN_RPM(tach);
  322. sc->sc_sensor[SCHSIO_SENSOR_FAN1].flags =
  323. (tach == 0xffff) ? SENSOR_FINVALID : 0;
  324. reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH2_L);
  325. reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH2_U);
  326. tach = (reg1 << 8) | reg0;
  327. sc->sc_sensor[SCHSIO_SENSOR_FAN2].value = SCHSIO_FAN_RPM(tach);
  328. sc->sc_sensor[SCHSIO_SENSOR_FAN2].flags =
  329. (tach == 0xffff) ? SENSOR_FINVALID : 0;
  330. reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH3_L);
  331. reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH3_U);
  332. tach = (reg1 << 8) | reg0;
  333. sc->sc_sensor[SCHSIO_SENSOR_FAN3].value = SCHSIO_FAN_RPM(tach);
  334. sc->sc_sensor[SCHSIO_SENSOR_FAN3].flags =
  335. (tach == 0xffff) ? SENSOR_FINVALID : 0;
  336. volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT1);
  337. sc->sc_sensor[SCHSIO_SENSOR_VOLT1].value =
  338. SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT1);
  339. volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT2);
  340. sc->sc_sensor[SCHSIO_SENSOR_VOLT2].value =
  341. SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT2);
  342. volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT3);
  343. sc->sc_sensor[SCHSIO_SENSOR_VOLT3].value =
  344. SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT3);
  345. volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT4);
  346. sc->sc_sensor[SCHSIO_SENSOR_VOLT4].value =
  347. SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT4);
  348. volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT5);
  349. sc->sc_sensor[SCHSIO_SENSOR_VOLT5].value =
  350. SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT5);
  351. volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT6);
  352. sc->sc_sensor[SCHSIO_SENSOR_VOLT6].value =
  353. SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT6);
  354. volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT7);
  355. sc->sc_sensor[SCHSIO_SENSOR_VOLT7].value =
  356. SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT7);
  357. temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP1);
  358. sc->sc_sensor[SCHSIO_SENSOR_TEMP1].value = SCHSIO_TEMP_MUK(temp);
  359. sc->sc_sensor[SCHSIO_SENSOR_TEMP1].flags =
  360. ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
  361. temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP2);
  362. sc->sc_sensor[SCHSIO_SENSOR_TEMP2].value = SCHSIO_TEMP_MUK(temp);
  363. sc->sc_sensor[SCHSIO_SENSOR_TEMP2].flags =
  364. ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
  365. temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP3);
  366. sc->sc_sensor[SCHSIO_SENSOR_TEMP3].value = SCHSIO_TEMP_MUK(temp);
  367. sc->sc_sensor[SCHSIO_SENSOR_TEMP3].flags =
  368. ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
  369. }
  370. u_int8_t
  371. schsio_hwm_read(struct schsio_softc *sc, u_int8_t reg)
  372. {
  373. bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_INDEX, reg);
  374. return (bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_DATA));
  375. }
  376. void
  377. schsio_wdt_init(struct schsio_softc *sc)
  378. {
  379. u_int8_t reg;
  380. reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_GPIO);
  381. if ((reg & SCHSIO_WDT_GPIO_MASK) != SCHSIO_WDT_GPIO_OUT) {
  382. if (sc->sc_dev.dv_cfdata->cf_flags & SCHSIO_CFFLAGS_WDTEN) {
  383. reg &= ~0x0f;
  384. reg |= SCHSIO_WDT_GPIO_OUT;
  385. bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
  386. SCHSIO_WDT_GPIO, reg);
  387. }
  388. else {
  389. printf(", watchdog disabled");
  390. return;
  391. }
  392. }
  393. /* First of all, make sure the wdt is disabled */
  394. bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, 0);
  395. /* Clear triggered status */
  396. reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CTRL);
  397. if (reg & SCHSIO_WDT_CTRL_TRIGGERED) {
  398. printf(", warning: watchdog triggered");
  399. reg &= ~SCHSIO_WDT_CTRL_TRIGGERED;
  400. bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
  401. SCHSIO_WDT_CTRL, reg);
  402. }
  403. /* Disable wdt reset by mouse and kbd */
  404. reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG);
  405. reg &= ~(SCHSIO_WDT_CFG_MSEN | SCHSIO_WDT_CFG_MSEN);
  406. bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG, reg);
  407. wdog_register(schsio_wdt_cb, sc);
  408. }
  409. int
  410. schsio_wdt_cb(void *arg, int period)
  411. {
  412. struct schsio_softc *sc;
  413. uint8_t val, minute, reg;
  414. sc = (struct schsio_softc *)arg;
  415. if (period > 255) {
  416. val = period / 60;
  417. minute = 1;
  418. } else {
  419. val = period;
  420. minute = 0;
  421. }
  422. /* Set unit */
  423. reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr,
  424. SCHSIO_WDT_TIMEOUT);
  425. if (!minute)
  426. reg |= SCHSIO_WDT_TO_SECONDS;
  427. else
  428. reg &= ~SCHSIO_WDT_TO_SECONDS;
  429. bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_TIMEOUT,
  430. reg);
  431. /* Set value */
  432. bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, val);
  433. if (!minute)
  434. return val;
  435. else
  436. return val * 60;
  437. }