ds1338.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * MAXIM DS1338 I2C RTC+NVRAM
  3. *
  4. * Copyright (c) 2009 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licensed under the GNU GPL v2.
  8. *
  9. * Contributions after 2012-01-13 are licensed under the terms of the
  10. * GNU GPL, version 2 or (at your option) any later version.
  11. */
  12. #include "hw/i2c/i2c.h"
  13. /* Size of NVRAM including both the user-accessible area and the
  14. * secondary register area.
  15. */
  16. #define NVRAM_SIZE 64
  17. /* Flags definitions */
  18. #define SECONDS_CH 0x80
  19. #define HOURS_12 0x40
  20. #define HOURS_PM 0x20
  21. #define CTRL_OSF 0x20
  22. #define TYPE_DS1338 "ds1338"
  23. #define DS1338(obj) OBJECT_CHECK(DS1338State, (obj), TYPE_DS1338)
  24. typedef struct DS1338State {
  25. I2CSlave parent_obj;
  26. int64_t offset;
  27. uint8_t wday_offset;
  28. uint8_t nvram[NVRAM_SIZE];
  29. int32_t ptr;
  30. bool addr_byte;
  31. } DS1338State;
  32. static const VMStateDescription vmstate_ds1338 = {
  33. .name = "ds1338",
  34. .version_id = 2,
  35. .minimum_version_id = 1,
  36. .fields = (VMStateField[]) {
  37. VMSTATE_I2C_SLAVE(parent_obj, DS1338State),
  38. VMSTATE_INT64(offset, DS1338State),
  39. VMSTATE_UINT8_V(wday_offset, DS1338State, 2),
  40. VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE),
  41. VMSTATE_INT32(ptr, DS1338State),
  42. VMSTATE_BOOL(addr_byte, DS1338State),
  43. VMSTATE_END_OF_LIST()
  44. }
  45. };
  46. static void capture_current_time(DS1338State *s)
  47. {
  48. /* Capture the current time into the secondary registers
  49. * which will be actually read by the data transfer operation.
  50. */
  51. struct tm now;
  52. qemu_get_timedate(&now, s->offset);
  53. s->nvram[0] = to_bcd(now.tm_sec);
  54. s->nvram[1] = to_bcd(now.tm_min);
  55. if (s->nvram[2] & HOURS_12) {
  56. int tmp = now.tm_hour;
  57. if (tmp % 12 == 0) {
  58. tmp += 12;
  59. }
  60. if (tmp <= 12) {
  61. s->nvram[2] = HOURS_12 | to_bcd(tmp);
  62. } else {
  63. s->nvram[2] = HOURS_12 | HOURS_PM | to_bcd(tmp - 12);
  64. }
  65. } else {
  66. s->nvram[2] = to_bcd(now.tm_hour);
  67. }
  68. s->nvram[3] = (now.tm_wday + s->wday_offset) % 7 + 1;
  69. s->nvram[4] = to_bcd(now.tm_mday);
  70. s->nvram[5] = to_bcd(now.tm_mon + 1);
  71. s->nvram[6] = to_bcd(now.tm_year - 100);
  72. }
  73. static void inc_regptr(DS1338State *s)
  74. {
  75. /* The register pointer wraps around after 0x3F; wraparound
  76. * causes the current time/date to be retransferred into
  77. * the secondary registers.
  78. */
  79. s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1);
  80. if (!s->ptr) {
  81. capture_current_time(s);
  82. }
  83. }
  84. static void ds1338_event(I2CSlave *i2c, enum i2c_event event)
  85. {
  86. DS1338State *s = DS1338(i2c);
  87. switch (event) {
  88. case I2C_START_RECV:
  89. /* In h/w, capture happens on any START condition, not just a
  90. * START_RECV, but there is no need to actually capture on
  91. * START_SEND, because the guest can't get at that data
  92. * without going through a START_RECV which would overwrite it.
  93. */
  94. capture_current_time(s);
  95. break;
  96. case I2C_START_SEND:
  97. s->addr_byte = true;
  98. break;
  99. default:
  100. break;
  101. }
  102. }
  103. static int ds1338_recv(I2CSlave *i2c)
  104. {
  105. DS1338State *s = DS1338(i2c);
  106. uint8_t res;
  107. res = s->nvram[s->ptr];
  108. inc_regptr(s);
  109. return res;
  110. }
  111. static int ds1338_send(I2CSlave *i2c, uint8_t data)
  112. {
  113. DS1338State *s = DS1338(i2c);
  114. if (s->addr_byte) {
  115. s->ptr = data & (NVRAM_SIZE - 1);
  116. s->addr_byte = false;
  117. return 0;
  118. }
  119. if (s->ptr < 7) {
  120. /* Time register. */
  121. struct tm now;
  122. qemu_get_timedate(&now, s->offset);
  123. switch(s->ptr) {
  124. case 0:
  125. /* TODO: Implement CH (stop) bit. */
  126. now.tm_sec = from_bcd(data & 0x7f);
  127. break;
  128. case 1:
  129. now.tm_min = from_bcd(data & 0x7f);
  130. break;
  131. case 2:
  132. if (data & HOURS_12) {
  133. int tmp = from_bcd(data & (HOURS_PM - 1));
  134. if (data & HOURS_PM) {
  135. tmp += 12;
  136. }
  137. if (tmp % 12 == 0) {
  138. tmp -= 12;
  139. }
  140. now.tm_hour = tmp;
  141. } else {
  142. now.tm_hour = from_bcd(data & (HOURS_12 - 1));
  143. }
  144. break;
  145. case 3:
  146. {
  147. /* The day field is supposed to contain a value in
  148. the range 1-7. Otherwise behavior is undefined.
  149. */
  150. int user_wday = (data & 7) - 1;
  151. s->wday_offset = (user_wday - now.tm_wday + 7) % 7;
  152. }
  153. break;
  154. case 4:
  155. now.tm_mday = from_bcd(data & 0x3f);
  156. break;
  157. case 5:
  158. now.tm_mon = from_bcd(data & 0x1f) - 1;
  159. break;
  160. case 6:
  161. now.tm_year = from_bcd(data) + 100;
  162. break;
  163. }
  164. s->offset = qemu_timedate_diff(&now);
  165. } else if (s->ptr == 7) {
  166. /* Control register. */
  167. /* Ensure bits 2, 3 and 6 will read back as zero. */
  168. data &= 0xB3;
  169. /* Attempting to write the OSF flag to logic 1 leaves the
  170. value unchanged. */
  171. data = (data & ~CTRL_OSF) | (data & s->nvram[s->ptr] & CTRL_OSF);
  172. s->nvram[s->ptr] = data;
  173. } else {
  174. s->nvram[s->ptr] = data;
  175. }
  176. inc_regptr(s);
  177. return 0;
  178. }
  179. static int ds1338_init(I2CSlave *i2c)
  180. {
  181. return 0;
  182. }
  183. static void ds1338_reset(DeviceState *dev)
  184. {
  185. DS1338State *s = DS1338(dev);
  186. /* The clock is running and synchronized with the host */
  187. s->offset = 0;
  188. s->wday_offset = 0;
  189. memset(s->nvram, 0, NVRAM_SIZE);
  190. s->ptr = 0;
  191. s->addr_byte = false;
  192. }
  193. static void ds1338_class_init(ObjectClass *klass, void *data)
  194. {
  195. DeviceClass *dc = DEVICE_CLASS(klass);
  196. I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
  197. k->init = ds1338_init;
  198. k->event = ds1338_event;
  199. k->recv = ds1338_recv;
  200. k->send = ds1338_send;
  201. dc->reset = ds1338_reset;
  202. dc->vmsd = &vmstate_ds1338;
  203. }
  204. static const TypeInfo ds1338_info = {
  205. .name = TYPE_DS1338,
  206. .parent = TYPE_I2C_SLAVE,
  207. .instance_size = sizeof(DS1338State),
  208. .class_init = ds1338_class_init,
  209. };
  210. static void ds1338_register_types(void)
  211. {
  212. type_register_static(&ds1338_info);
  213. }
  214. type_init(ds1338_register_types)