time.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. * linux/arch/m68k/atari/time.c
  3. *
  4. * Atari time and real time clock stuff
  5. *
  6. * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file COPYING in the main directory of this archive
  10. * for more details.
  11. */
  12. #include <linux/types.h>
  13. #include <linux/mc146818rtc.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/init.h>
  16. #include <linux/rtc.h>
  17. #include <linux/bcd.h>
  18. #include <linux/delay.h>
  19. #include <linux/export.h>
  20. #include <asm/atariints.h>
  21. DEFINE_SPINLOCK(rtc_lock);
  22. EXPORT_SYMBOL_GPL(rtc_lock);
  23. static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
  24. {
  25. irq_handler_t timer_routine = dev_id;
  26. unsigned long flags;
  27. local_irq_save(flags);
  28. timer_routine(0, NULL);
  29. local_irq_restore(flags);
  30. return IRQ_HANDLED;
  31. }
  32. void __init
  33. atari_sched_init(irq_handler_t timer_routine)
  34. {
  35. /* set Timer C data Register */
  36. st_mfp.tim_dt_c = INT_TICKS;
  37. /* start timer C, div = 1:100 */
  38. st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
  39. /* install interrupt service routine for MFP Timer C */
  40. if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, 0, "timer",
  41. timer_routine))
  42. pr_err("Couldn't register timer interrupt\n");
  43. }
  44. /* ++andreas: gettimeoffset fixed to check for pending interrupt */
  45. #define TICK_SIZE 10000
  46. /* This is always executed with interrupts disabled. */
  47. u32 atari_gettimeoffset(void)
  48. {
  49. u32 ticks, offset = 0;
  50. /* read MFP timer C current value */
  51. ticks = st_mfp.tim_dt_c;
  52. /* The probability of underflow is less than 2% */
  53. if (ticks > INT_TICKS - INT_TICKS / 50)
  54. /* Check for pending timer interrupt */
  55. if (st_mfp.int_pn_b & (1 << 5))
  56. offset = TICK_SIZE;
  57. ticks = INT_TICKS - ticks;
  58. ticks = ticks * 10000L / INT_TICKS;
  59. return (ticks + offset) * 1000;
  60. }
  61. static void mste_read(struct MSTE_RTC *val)
  62. {
  63. #define COPY(v) val->v=(mste_rtc.v & 0xf)
  64. do {
  65. COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
  66. COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
  67. COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
  68. COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
  69. COPY(year_tens) ;
  70. /* prevent from reading the clock while it changed */
  71. } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
  72. #undef COPY
  73. }
  74. static void mste_write(struct MSTE_RTC *val)
  75. {
  76. #define COPY(v) mste_rtc.v=val->v
  77. do {
  78. COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
  79. COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
  80. COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
  81. COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
  82. COPY(year_tens) ;
  83. /* prevent from writing the clock while it changed */
  84. } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
  85. #undef COPY
  86. }
  87. #define RTC_READ(reg) \
  88. ({ unsigned char __val; \
  89. (void) atari_writeb(reg,&tt_rtc.regsel); \
  90. __val = tt_rtc.data; \
  91. __val; \
  92. })
  93. #define RTC_WRITE(reg,val) \
  94. do { \
  95. atari_writeb(reg,&tt_rtc.regsel); \
  96. tt_rtc.data = (val); \
  97. } while(0)
  98. #define HWCLK_POLL_INTERVAL 5
  99. int atari_mste_hwclk( int op, struct rtc_time *t )
  100. {
  101. int hour, year;
  102. int hr24=0;
  103. struct MSTE_RTC val;
  104. mste_rtc.mode=(mste_rtc.mode | 1);
  105. hr24=mste_rtc.mon_tens & 1;
  106. mste_rtc.mode=(mste_rtc.mode & ~1);
  107. if (op) {
  108. /* write: prepare values */
  109. val.sec_ones = t->tm_sec % 10;
  110. val.sec_tens = t->tm_sec / 10;
  111. val.min_ones = t->tm_min % 10;
  112. val.min_tens = t->tm_min / 10;
  113. hour = t->tm_hour;
  114. if (!hr24) {
  115. if (hour > 11)
  116. hour += 20 - 12;
  117. if (hour == 0 || hour == 20)
  118. hour += 12;
  119. }
  120. val.hr_ones = hour % 10;
  121. val.hr_tens = hour / 10;
  122. val.day_ones = t->tm_mday % 10;
  123. val.day_tens = t->tm_mday / 10;
  124. val.mon_ones = (t->tm_mon+1) % 10;
  125. val.mon_tens = (t->tm_mon+1) / 10;
  126. year = t->tm_year - 80;
  127. val.year_ones = year % 10;
  128. val.year_tens = year / 10;
  129. val.weekday = t->tm_wday;
  130. mste_write(&val);
  131. mste_rtc.mode=(mste_rtc.mode | 1);
  132. val.year_ones = (year % 4); /* leap year register */
  133. mste_rtc.mode=(mste_rtc.mode & ~1);
  134. }
  135. else {
  136. mste_read(&val);
  137. t->tm_sec = val.sec_ones + val.sec_tens * 10;
  138. t->tm_min = val.min_ones + val.min_tens * 10;
  139. hour = val.hr_ones + val.hr_tens * 10;
  140. if (!hr24) {
  141. if (hour == 12 || hour == 12 + 20)
  142. hour -= 12;
  143. if (hour >= 20)
  144. hour += 12 - 20;
  145. }
  146. t->tm_hour = hour;
  147. t->tm_mday = val.day_ones + val.day_tens * 10;
  148. t->tm_mon = val.mon_ones + val.mon_tens * 10 - 1;
  149. t->tm_year = val.year_ones + val.year_tens * 10 + 80;
  150. t->tm_wday = val.weekday;
  151. }
  152. return 0;
  153. }
  154. int atari_tt_hwclk( int op, struct rtc_time *t )
  155. {
  156. int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0;
  157. unsigned long flags;
  158. unsigned char ctrl;
  159. int pm = 0;
  160. ctrl = RTC_READ(RTC_CONTROL); /* control registers are
  161. * independent from the UIP */
  162. if (op) {
  163. /* write: prepare values */
  164. sec = t->tm_sec;
  165. min = t->tm_min;
  166. hour = t->tm_hour;
  167. day = t->tm_mday;
  168. mon = t->tm_mon + 1;
  169. year = t->tm_year - atari_rtc_year_offset;
  170. wday = t->tm_wday + (t->tm_wday >= 0);
  171. if (!(ctrl & RTC_24H)) {
  172. if (hour > 11) {
  173. pm = 0x80;
  174. if (hour != 12)
  175. hour -= 12;
  176. }
  177. else if (hour == 0)
  178. hour = 12;
  179. }
  180. if (!(ctrl & RTC_DM_BINARY)) {
  181. sec = bin2bcd(sec);
  182. min = bin2bcd(min);
  183. hour = bin2bcd(hour);
  184. day = bin2bcd(day);
  185. mon = bin2bcd(mon);
  186. year = bin2bcd(year);
  187. if (wday >= 0)
  188. wday = bin2bcd(wday);
  189. }
  190. }
  191. /* Reading/writing the clock registers is a bit critical due to
  192. * the regular update cycle of the RTC. While an update is in
  193. * progress, registers 0..9 shouldn't be touched.
  194. * The problem is solved like that: If an update is currently in
  195. * progress (the UIP bit is set), the process sleeps for a while
  196. * (50ms). This really should be enough, since the update cycle
  197. * normally needs 2 ms.
  198. * If the UIP bit reads as 0, we have at least 244 usecs until the
  199. * update starts. This should be enough... But to be sure,
  200. * additionally the RTC_SET bit is set to prevent an update cycle.
  201. */
  202. while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
  203. if (in_atomic() || irqs_disabled())
  204. mdelay(1);
  205. else
  206. schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
  207. }
  208. local_irq_save(flags);
  209. RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
  210. if (!op) {
  211. sec = RTC_READ( RTC_SECONDS );
  212. min = RTC_READ( RTC_MINUTES );
  213. hour = RTC_READ( RTC_HOURS );
  214. day = RTC_READ( RTC_DAY_OF_MONTH );
  215. mon = RTC_READ( RTC_MONTH );
  216. year = RTC_READ( RTC_YEAR );
  217. wday = RTC_READ( RTC_DAY_OF_WEEK );
  218. }
  219. else {
  220. RTC_WRITE( RTC_SECONDS, sec );
  221. RTC_WRITE( RTC_MINUTES, min );
  222. RTC_WRITE( RTC_HOURS, hour + pm);
  223. RTC_WRITE( RTC_DAY_OF_MONTH, day );
  224. RTC_WRITE( RTC_MONTH, mon );
  225. RTC_WRITE( RTC_YEAR, year );
  226. if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
  227. }
  228. RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
  229. local_irq_restore(flags);
  230. if (!op) {
  231. /* read: adjust values */
  232. if (hour & 0x80) {
  233. hour &= ~0x80;
  234. pm = 1;
  235. }
  236. if (!(ctrl & RTC_DM_BINARY)) {
  237. sec = bcd2bin(sec);
  238. min = bcd2bin(min);
  239. hour = bcd2bin(hour);
  240. day = bcd2bin(day);
  241. mon = bcd2bin(mon);
  242. year = bcd2bin(year);
  243. wday = bcd2bin(wday);
  244. }
  245. if (!(ctrl & RTC_24H)) {
  246. if (!pm && hour == 12)
  247. hour = 0;
  248. else if (pm && hour != 12)
  249. hour += 12;
  250. }
  251. t->tm_sec = sec;
  252. t->tm_min = min;
  253. t->tm_hour = hour;
  254. t->tm_mday = day;
  255. t->tm_mon = mon - 1;
  256. t->tm_year = year + atari_rtc_year_offset;
  257. t->tm_wday = wday - 1;
  258. }
  259. return( 0 );
  260. }
  261. /*
  262. * Local variables:
  263. * c-indent-level: 4
  264. * tab-width: 8
  265. * End:
  266. */