dsrtc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /* $OpenBSD: dsrtc.c,v 1.12 2012/03/28 20:44:23 miod Exp $ */
  2. /*
  3. * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  15. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  18. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. * SUCH DAMAGE.
  25. *
  26. */
  27. #include <sys/param.h>
  28. #include <sys/kernel.h>
  29. #include <sys/systm.h>
  30. #include <sys/device.h>
  31. #include <machine/autoconf.h>
  32. #include <machine/bus.h>
  33. #include <dev/ic/ds1687reg.h>
  34. #define todr_chip_handle_t void * /* XXX that's just to eat prototypes */
  35. #include <dev/ic/mk48txxreg.h>
  36. #include <mips64/archtype.h>
  37. #include <mips64/dev/clockvar.h>
  38. #include <sgi/dev/dsrtcvar.h>
  39. #include <sgi/localbus/macebusvar.h>
  40. #include <sgi/pci/iocreg.h>
  41. #include <sgi/pci/iocvar.h>
  42. #include <sgi/pci/iofvar.h>
  43. struct dsrtc_softc {
  44. struct device sc_dev;
  45. bus_space_tag_t sc_clkt;
  46. bus_space_handle_t sc_clkh, sc_clkh2;
  47. int sc_yrbase;
  48. int (*read)(struct dsrtc_softc *, int);
  49. void (*write)(struct dsrtc_softc *, int, int);
  50. };
  51. int dsrtc_match(struct device *, void *, void *);
  52. void dsrtc_attach_ioc(struct device *, struct device *, void *);
  53. void dsrtc_attach_iof(struct device *, struct device *, void *);
  54. void dsrtc_attach_macebus(struct device *, struct device *, void *);
  55. struct cfdriver dsrtc_cd = {
  56. NULL, "dsrtc", DV_DULL
  57. };
  58. struct cfattach dsrtc_macebus_ca = {
  59. sizeof(struct dsrtc_softc), dsrtc_match, dsrtc_attach_macebus
  60. };
  61. struct cfattach dsrtc_ioc_ca = {
  62. sizeof(struct dsrtc_softc), dsrtc_match, dsrtc_attach_ioc
  63. };
  64. struct cfattach dsrtc_iof_ca = {
  65. sizeof(struct dsrtc_softc), dsrtc_match, dsrtc_attach_ioc
  66. };
  67. int ip32_dsrtc_read(struct dsrtc_softc *, int);
  68. void ip32_dsrtc_write(struct dsrtc_softc *, int, int);
  69. int ioc_ds1687_dsrtc_read(struct dsrtc_softc *, int);
  70. void ioc_ds1687_dsrtc_write(struct dsrtc_softc *, int, int);
  71. void ds1687_get(void *, time_t, struct tod_time *);
  72. void ds1687_set(void *, struct tod_time *);
  73. void ds1742_get(void *, time_t, struct tod_time *);
  74. void ds1742_set(void *, struct tod_time *);
  75. static inline int frombcd(int, int);
  76. static inline int tobcd(int, int);
  77. static inline int
  78. frombcd(int x, int binary)
  79. {
  80. return binary ? x : (x >> 4) * 10 + (x & 0xf);
  81. }
  82. static inline int
  83. tobcd(int x, int binary)
  84. {
  85. return binary ? x : (x / 10 * 16) + (x % 10);
  86. }
  87. int
  88. dsrtc_match(struct device *parent, void *match, void *aux)
  89. {
  90. /*
  91. * Depending on what dsrtc attaches to, the actual attach_args
  92. * may be a different struct, but all of them start with the
  93. * same name field.
  94. */
  95. struct mainbus_attach_args *maa = aux;
  96. return strcmp(maa->maa_name, dsrtc_cd.cd_name) == 0;
  97. }
  98. void
  99. dsrtc_attach_ioc(struct device *parent, struct device *self, void *aux)
  100. {
  101. struct dsrtc_softc *sc = (void *)self;
  102. struct ioc_attach_args *iaa = aux;
  103. bus_space_handle_t ih, ih2;
  104. /*
  105. * The IOC3 RTC is either a Dallas (now Maxim) DS1397 or compatible
  106. * (likely a more recent DS1687), or a DS1747 or compatible
  107. * (itself being a Mostek MK48T35 clone).
  108. *
  109. * Surprisingly, the chip found on Fuel has a DS1742W label,
  110. * which has much less memory than the DS1747. I guess whatever
  111. * the chip is, it is mapped to the end of the DS1747 address
  112. * space, so that the clock registers always appear at the same
  113. * addresses in memory.
  114. */
  115. sc->sc_clkt = iaa->iaa_memt;
  116. if (iaa->iaa_base != IOC3_BYTEBUS_0) {
  117. /* DS1687 */
  118. if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh,
  119. IOC3_BYTEBUS_1, 1, &ih) != 0 ||
  120. bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh,
  121. IOC3_BYTEBUS_2, 1, &ih2) != 0)
  122. goto fail;
  123. printf(": DS1687\n");
  124. sc->sc_clkh = ih;
  125. sc->sc_clkh2 = ih2;
  126. sc->read = ioc_ds1687_dsrtc_read;
  127. sc->write = ioc_ds1687_dsrtc_write;
  128. sys_tod.tod_get = ds1687_get;
  129. sys_tod.tod_set = ds1687_set;
  130. } else {
  131. /* DS1742W */
  132. bus_space_unmap(iaa->iaa_memt, ih, 1);
  133. bus_space_unmap(iaa->iaa_memt, ih2, 1);
  134. if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh,
  135. iaa->iaa_base + MK48T35_CLKOFF,
  136. MK48T35_CLKSZ - MK48T35_CLKOFF, &ih) != 0)
  137. goto fail;
  138. printf(": DS1742W\n");
  139. sc->sc_clkh = ih;
  140. /*
  141. * For some reason, the base year differs between IP27
  142. * and IP35.
  143. */
  144. sc->sc_yrbase = sys_config.system_type == SGI_IP35 ?
  145. POSIX_BASE_YEAR - 2 : POSIX_BASE_YEAR;
  146. /* mips64 clock code expects year relative to 1900 */
  147. sc->sc_yrbase -= 1900;
  148. sys_tod.tod_get = ds1742_get;
  149. sys_tod.tod_set = ds1742_set;
  150. }
  151. sys_tod.tod_cookie = self;
  152. return;
  153. fail:
  154. printf(": can't map registers\n");
  155. }
  156. void
  157. dsrtc_attach_iof(struct device *parent, struct device *self, void *aux)
  158. {
  159. struct dsrtc_softc *sc = (void *)self;
  160. struct iof_attach_args *iaa = aux;
  161. bus_space_handle_t ih;
  162. /*
  163. * The IOC4 RTC is a DS1747 or compatible (itself being a Mostek
  164. * MK48T35 clone).
  165. */
  166. if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh,
  167. iaa->iaa_base + MK48T35_CLKOFF,
  168. MK48T35_CLKSZ - MK48T35_CLKOFF, &ih) != 0)
  169. goto fail;
  170. printf(": DS1742W\n");
  171. sc->sc_clkh = ih;
  172. /*
  173. * For some reason, the base year differs between IP27
  174. * and IP35.
  175. */
  176. sc->sc_yrbase = sys_config.system_type == SGI_IP35 ?
  177. POSIX_BASE_YEAR - 2 : POSIX_BASE_YEAR;
  178. /* mips64 clock code expects year relative to 1900 */
  179. sc->sc_yrbase -= 1900;
  180. sys_tod.tod_cookie = self;
  181. sys_tod.tod_get = ds1742_get;
  182. sys_tod.tod_set = ds1742_set;
  183. return;
  184. fail:
  185. printf(": can't map registers\n");
  186. }
  187. void
  188. dsrtc_attach_macebus(struct device *parent, struct device *self, void *aux)
  189. {
  190. struct dsrtc_softc *sc = (void *)self;
  191. struct macebus_attach_args *maa = aux;
  192. sc->sc_clkt = maa->maa_iot;
  193. if (bus_space_map(sc->sc_clkt, maa->maa_baseaddr, 128 * 256, 0,
  194. &sc->sc_clkh)) {
  195. printf(": can't map registers\n");
  196. return;
  197. }
  198. printf(": DS1687\n");
  199. sc->read = ip32_dsrtc_read;
  200. sc->write = ip32_dsrtc_write;
  201. sys_tod.tod_cookie = self;
  202. sys_tod.tod_get = ds1687_get;
  203. sys_tod.tod_set = ds1687_set;
  204. }
  205. int
  206. ip32_dsrtc_read(struct dsrtc_softc *sc, int reg)
  207. {
  208. return bus_space_read_1(sc->sc_clkt, sc->sc_clkh, reg);
  209. }
  210. void
  211. ip32_dsrtc_write(struct dsrtc_softc *sc, int reg, int val)
  212. {
  213. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, reg, val);
  214. }
  215. int
  216. ioc_ds1687_dsrtc_read(struct dsrtc_softc *sc, int reg)
  217. {
  218. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, 0, reg);
  219. return bus_space_read_1(sc->sc_clkt, sc->sc_clkh2, 0);
  220. }
  221. void
  222. ioc_ds1687_dsrtc_write(struct dsrtc_softc *sc, int reg, int val)
  223. {
  224. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, 0, reg);
  225. bus_space_write_1(sc->sc_clkt, sc->sc_clkh2, 0, val);
  226. }
  227. /*
  228. * Dallas DS1687 clock driver.
  229. */
  230. void
  231. ds1687_get(void *v, time_t base, struct tod_time *ct)
  232. {
  233. struct dsrtc_softc *sc = v;
  234. int ctrl, century, dm;
  235. /* Select bank 1. */
  236. ctrl = (*sc->read)(sc, DS1687_CTRL_A);
  237. (*sc->write)(sc, DS1687_CTRL_A, ctrl | DS1687_BANK_1);
  238. /* Figure out which data mode to use. */
  239. dm = (*sc->read)(sc, DS1687_CTRL_B) & DS1687_DM_1;
  240. /* Wait for no update in progress. */
  241. while ((*sc->read)(sc, DS1687_CTRL_A) & DS1687_UIP)
  242. /* Do nothing. */;
  243. /* Read the RTC. */
  244. ct->sec = frombcd((*sc->read)(sc, DS1687_SEC), dm);
  245. ct->min = frombcd((*sc->read)(sc, DS1687_MIN), dm);
  246. ct->hour = frombcd((*sc->read)(sc, DS1687_HOUR), dm);
  247. ct->day = frombcd((*sc->read)(sc, DS1687_DAY), dm);
  248. ct->mon = frombcd((*sc->read)(sc, DS1687_MONTH), dm);
  249. ct->year = frombcd((*sc->read)(sc, DS1687_YEAR), dm);
  250. century = frombcd((*sc->read)(sc, DS1687_CENTURY), dm);
  251. ct->year += 100 * (century - 19);
  252. }
  253. void
  254. ds1687_set(void *v, struct tod_time *ct)
  255. {
  256. struct dsrtc_softc *sc = v;
  257. int year, century, ctrl, dm;
  258. century = ct->year / 100 + 19;
  259. year = ct->year % 100;
  260. /* Select bank 1. */
  261. ctrl = (*sc->read)(sc, DS1687_CTRL_A);
  262. (*sc->write)(sc, DS1687_CTRL_A, ctrl | DS1687_BANK_1);
  263. /* Figure out which data mode to use, and select 24 hour time. */
  264. ctrl = (*sc->read)(sc, DS1687_CTRL_B);
  265. dm = ctrl & DS1687_DM_1;
  266. (*sc->write)(sc, DS1687_CTRL_B, ctrl | DS1687_24_HR);
  267. /* Prevent updates. */
  268. ctrl = (*sc->read)(sc, DS1687_CTRL_B);
  269. (*sc->write)(sc, DS1687_CTRL_B, ctrl | DS1687_SET_CLOCK);
  270. /* Update the RTC. */
  271. (*sc->write)(sc, DS1687_SEC, tobcd(ct->sec, dm));
  272. (*sc->write)(sc, DS1687_MIN, tobcd(ct->min, dm));
  273. (*sc->write)(sc, DS1687_HOUR, tobcd(ct->hour, dm));
  274. (*sc->write)(sc, DS1687_DOW, tobcd(ct->dow, dm));
  275. (*sc->write)(sc, DS1687_DAY, tobcd(ct->day, dm));
  276. (*sc->write)(sc, DS1687_MONTH, tobcd(ct->mon, dm));
  277. (*sc->write)(sc, DS1687_YEAR, tobcd(year, dm));
  278. (*sc->write)(sc, DS1687_CENTURY, tobcd(century, dm));
  279. /* Enable updates. */
  280. (*sc->write)(sc, DS1687_CTRL_B, ctrl);
  281. }
  282. /*
  283. * Dallas DS1742 clock driver.
  284. */
  285. void
  286. ds1742_get(void *v, time_t base, struct tod_time *ct)
  287. {
  288. struct dsrtc_softc *sc = v;
  289. int csr;
  290. /* Freeze update. */
  291. csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR);
  292. csr |= MK48TXX_CSR_READ;
  293. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr);
  294. /* Read the RTC. */
  295. ct->sec = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh,
  296. MK48TXX_ISEC), 0);
  297. ct->min = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh,
  298. MK48TXX_IMIN), 0);
  299. ct->hour = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh,
  300. MK48TXX_IHOUR), 0);
  301. ct->day = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh,
  302. MK48TXX_IDAY), 0);
  303. ct->mon = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh,
  304. MK48TXX_IMON), 0);
  305. ct->year = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh,
  306. MK48TXX_IYEAR), 0) + sc->sc_yrbase;
  307. /* Enable updates again. */
  308. csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR);
  309. csr &= ~MK48TXX_CSR_READ;
  310. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr);
  311. }
  312. void
  313. ds1742_set(void *v, struct tod_time *ct)
  314. {
  315. struct dsrtc_softc *sc = v;
  316. int csr;
  317. /* Enable write. */
  318. csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR);
  319. csr |= MK48TXX_CSR_WRITE;
  320. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr);
  321. /* Update the RTC. */
  322. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ISEC,
  323. tobcd(ct->sec, 0));
  324. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IMIN,
  325. tobcd(ct->min, 0));
  326. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IHOUR,
  327. tobcd(ct->hour, 0));
  328. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IWDAY,
  329. tobcd(ct->dow, 0));
  330. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IDAY,
  331. tobcd(ct->day, 0));
  332. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IMON,
  333. tobcd(ct->mon, 0));
  334. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IYEAR,
  335. tobcd(ct->year - sc->sc_yrbase, 0));
  336. /* Load new values. */
  337. csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR);
  338. csr &= ~MK48TXX_CSR_WRITE;
  339. bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr);
  340. }
  341. /*
  342. * Routines allowing external access to the RTC registers, used by
  343. * power(4).
  344. */
  345. int
  346. dsrtc_register_read(int reg)
  347. {
  348. struct dsrtc_softc *sc;
  349. if (dsrtc_cd.cd_ndevs == 0 ||
  350. (sc = (struct dsrtc_softc *)dsrtc_cd.cd_devs[0]) == NULL ||
  351. sc->read == NULL)
  352. return -1;
  353. return (*sc->read)(sc, reg);
  354. }
  355. void
  356. dsrtc_register_write(int reg, int val)
  357. {
  358. struct dsrtc_softc *sc;
  359. if (dsrtc_cd.cd_ndevs == 0 ||
  360. (sc = (struct dsrtc_softc *)dsrtc_cd.cd_devs[0]) == NULL ||
  361. sc->write == NULL)
  362. return;
  363. (*sc->write)(sc, reg, val);
  364. }