2
0

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 "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. .minimum_version_id_old = 1,
  37. .fields = (VMStateField[]) {
  38. VMSTATE_I2C_SLAVE(parent_obj, DS1338State),
  39. VMSTATE_INT64(offset, DS1338State),
  40. VMSTATE_UINT8_V(wday_offset, DS1338State, 2),
  41. VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE),
  42. VMSTATE_INT32(ptr, DS1338State),
  43. VMSTATE_BOOL(addr_byte, DS1338State),
  44. VMSTATE_END_OF_LIST()
  45. }
  46. };
  47. static void capture_current_time(DS1338State *s)
  48. {
  49. /* Capture the current time into the secondary registers
  50. * which will be actually read by the data transfer operation.
  51. */
  52. struct tm now;
  53. qemu_get_timedate(&now, s->offset);
  54. s->nvram[0] = to_bcd(now.tm_sec);
  55. s->nvram[1] = to_bcd(now.tm_min);
  56. if (s->nvram[2] & HOURS_12) {
  57. int tmp = now.tm_hour;
  58. if (tmp % 12 == 0) {
  59. tmp += 12;
  60. }
  61. if (tmp <= 12) {
  62. s->nvram[2] = HOURS_12 | to_bcd(tmp);
  63. } else {
  64. s->nvram[2] = HOURS_12 | HOURS_PM | to_bcd(tmp - 12);
  65. }
  66. } else {
  67. s->nvram[2] = to_bcd(now.tm_hour);
  68. }
  69. s->nvram[3] = (now.tm_wday + s->wday_offset) % 7 + 1;
  70. s->nvram[4] = to_bcd(now.tm_mday);
  71. s->nvram[5] = to_bcd(now.tm_mon + 1);
  72. s->nvram[6] = to_bcd(now.tm_year - 100);
  73. }
  74. static void inc_regptr(DS1338State *s)
  75. {
  76. /* The register pointer wraps around after 0x3F; wraparound
  77. * causes the current time/date to be retransferred into
  78. * the secondary registers.
  79. */
  80. s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1);
  81. if (!s->ptr) {
  82. capture_current_time(s);
  83. }
  84. }
  85. static void ds1338_event(I2CSlave *i2c, enum i2c_event event)
  86. {
  87. DS1338State *s = DS1338(i2c);
  88. switch (event) {
  89. case I2C_START_RECV:
  90. /* In h/w, capture happens on any START condition, not just a
  91. * START_RECV, but there is no need to actually capture on
  92. * START_SEND, because the guest can't get at that data
  93. * without going through a START_RECV which would overwrite it.
  94. */
  95. capture_current_time(s);
  96. break;
  97. case I2C_START_SEND:
  98. s->addr_byte = true;
  99. break;
  100. default:
  101. break;
  102. }
  103. }
  104. static int ds1338_recv(I2CSlave *i2c)
  105. {
  106. DS1338State *s = DS1338(i2c);
  107. uint8_t res;
  108. res = s->nvram[s->ptr];
  109. inc_regptr(s);
  110. return res;
  111. }
  112. static int ds1338_send(I2CSlave *i2c, uint8_t data)
  113. {
  114. DS1338State *s = DS1338(i2c);
  115. if (s->addr_byte) {
  116. s->ptr = data & (NVRAM_SIZE - 1);
  117. s->addr_byte = false;
  118. return 0;
  119. }
  120. if (s->ptr < 7) {
  121. /* Time register. */
  122. struct tm now;
  123. qemu_get_timedate(&now, s->offset);
  124. switch(s->ptr) {
  125. case 0:
  126. /* TODO: Implement CH (stop) bit. */
  127. now.tm_sec = from_bcd(data & 0x7f);
  128. break;
  129. case 1:
  130. now.tm_min = from_bcd(data & 0x7f);
  131. break;
  132. case 2:
  133. if (data & HOURS_12) {
  134. int tmp = from_bcd(data & (HOURS_PM - 1));
  135. if (data & HOURS_PM) {
  136. tmp += 12;
  137. }
  138. if (tmp % 12 == 0) {
  139. tmp -= 12;
  140. }
  141. now.tm_hour = tmp;
  142. } else {
  143. now.tm_hour = from_bcd(data & (HOURS_12 - 1));
  144. }
  145. break;
  146. case 3:
  147. {
  148. /* The day field is supposed to contain a value in
  149. the range 1-7. Otherwise behavior is undefined.
  150. */
  151. int user_wday = (data & 7) - 1;
  152. s->wday_offset = (user_wday - now.tm_wday + 7) % 7;
  153. }
  154. break;
  155. case 4:
  156. now.tm_mday = from_bcd(data & 0x3f);
  157. break;
  158. case 5:
  159. now.tm_mon = from_bcd(data & 0x1f) - 1;
  160. break;
  161. case 6:
  162. now.tm_year = from_bcd(data) + 100;
  163. break;
  164. }
  165. s->offset = qemu_timedate_diff(&now);
  166. } else if (s->ptr == 7) {
  167. /* Control register. */
  168. /* Ensure bits 2, 3 and 6 will read back as zero. */
  169. data &= 0xB3;
  170. /* Attempting to write the OSF flag to logic 1 leaves the
  171. value unchanged. */
  172. data = (data & ~CTRL_OSF) | (data & s->nvram[s->ptr] & CTRL_OSF);
  173. s->nvram[s->ptr] = data;
  174. } else {
  175. s->nvram[s->ptr] = data;
  176. }
  177. inc_regptr(s);
  178. return 0;
  179. }
  180. static int ds1338_init(I2CSlave *i2c)
  181. {
  182. return 0;
  183. }
  184. static void ds1338_reset(DeviceState *dev)
  185. {
  186. DS1338State *s = DS1338(dev);
  187. /* The clock is running and synchronized with the host */
  188. s->offset = 0;
  189. s->wday_offset = 0;
  190. memset(s->nvram, 0, NVRAM_SIZE);
  191. s->ptr = 0;
  192. s->addr_byte = false;
  193. }
  194. static void ds1338_class_init(ObjectClass *klass, void *data)
  195. {
  196. DeviceClass *dc = DEVICE_CLASS(klass);
  197. I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
  198. k->init = ds1338_init;
  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)