ds1338.c 6.2 KB

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