qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

exynos4210_rtc.c (17564B)


      1 /*
      2  * Samsung exynos4210 Real Time Clock
      3  *
      4  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
      5  *  Ogurtsov Oleg <o.ogurtsov@samsung.com>
      6  *
      7  *  This program is free software; you can redistribute it and/or modify it
      8  *  under the terms of the GNU General Public License as published by the
      9  *  Free Software Foundation; either version 2 of the License, or
     10  *  (at your option) any later version.
     11  *
     12  *  This program is distributed in the hope that it will be useful, but WITHOUT
     13  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
     15  *  for more details.
     16  *
     17  *  You should have received a copy of the GNU General Public License along
     18  *  with this program; if not, see <http://www.gnu.org/licenses/>.
     19  *
     20  */
     21 
     22 /* Description:
     23  * Register RTCCON:
     24  *  CLKSEL Bit[1] not used
     25  *  CLKOUTEN Bit[9] not used
     26  */
     27 
     28 #include "qemu/osdep.h"
     29 #include "qemu/log.h"
     30 #include "qemu/module.h"
     31 #include "hw/sysbus.h"
     32 #include "migration/vmstate.h"
     33 #include "qemu/timer.h"
     34 #include "qemu/bcd.h"
     35 #include "hw/ptimer.h"
     36 
     37 #include "hw/irq.h"
     38 
     39 #include "hw/arm/exynos4210.h"
     40 #include "qom/object.h"
     41 #include "sysemu/rtc.h"
     42 
     43 #define DEBUG_RTC 0
     44 
     45 #if DEBUG_RTC
     46 #define DPRINTF(fmt, ...) \
     47         do { fprintf(stdout, "RTC: [%24s:%5d] " fmt, __func__, __LINE__, \
     48                 ## __VA_ARGS__); } while (0)
     49 #else
     50 #define DPRINTF(fmt, ...) do {} while (0)
     51 #endif
     52 
     53 #define     EXYNOS4210_RTC_REG_MEM_SIZE     0x0100
     54 
     55 #define     INTP            0x0030
     56 #define     RTCCON          0x0040
     57 #define     TICCNT          0x0044
     58 #define     RTCALM          0x0050
     59 #define     ALMSEC          0x0054
     60 #define     ALMMIN          0x0058
     61 #define     ALMHOUR         0x005C
     62 #define     ALMDAY          0x0060
     63 #define     ALMMON          0x0064
     64 #define     ALMYEAR         0x0068
     65 #define     BCDSEC          0x0070
     66 #define     BCDMIN          0x0074
     67 #define     BCDHOUR         0x0078
     68 #define     BCDDAY          0x007C
     69 #define     BCDDAYWEEK      0x0080
     70 #define     BCDMON          0x0084
     71 #define     BCDYEAR         0x0088
     72 #define     CURTICNT        0x0090
     73 
     74 #define     TICK_TIMER_ENABLE   0x0100
     75 #define     TICNT_THRESHOLD     2
     76 
     77 
     78 #define     RTC_ENABLE          0x0001
     79 
     80 #define     INTP_TICK_ENABLE    0x0001
     81 #define     INTP_ALM_ENABLE     0x0002
     82 
     83 #define     ALARM_INT_ENABLE    0x0040
     84 
     85 #define     RTC_BASE_FREQ       32768
     86 
     87 #define TYPE_EXYNOS4210_RTC "exynos4210.rtc"
     88 OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210RTCState, EXYNOS4210_RTC)
     89 
     90 struct Exynos4210RTCState {
     91     SysBusDevice parent_obj;
     92 
     93     MemoryRegion iomem;
     94 
     95     /* registers */
     96     uint32_t    reg_intp;
     97     uint32_t    reg_rtccon;
     98     uint32_t    reg_ticcnt;
     99     uint32_t    reg_rtcalm;
    100     uint32_t    reg_almsec;
    101     uint32_t    reg_almmin;
    102     uint32_t    reg_almhour;
    103     uint32_t    reg_almday;
    104     uint32_t    reg_almmon;
    105     uint32_t    reg_almyear;
    106     uint32_t    reg_curticcnt;
    107 
    108     ptimer_state    *ptimer;        /* tick timer */
    109     ptimer_state    *ptimer_1Hz;    /* clock timer */
    110     uint32_t        freq;
    111 
    112     qemu_irq        tick_irq;   /* Time Tick Generator irq */
    113     qemu_irq        alm_irq;    /* alarm irq */
    114 
    115     struct tm   current_tm;     /* current time */
    116 };
    117 
    118 #define TICCKSEL(value) ((value & (0x0F << 4)) >> 4)
    119 
    120 /*** VMState ***/
    121 static const VMStateDescription vmstate_exynos4210_rtc_state = {
    122     .name = "exynos4210.rtc",
    123     .version_id = 1,
    124     .minimum_version_id = 1,
    125     .fields = (VMStateField[]) {
    126         VMSTATE_UINT32(reg_intp, Exynos4210RTCState),
    127         VMSTATE_UINT32(reg_rtccon, Exynos4210RTCState),
    128         VMSTATE_UINT32(reg_ticcnt, Exynos4210RTCState),
    129         VMSTATE_UINT32(reg_rtcalm, Exynos4210RTCState),
    130         VMSTATE_UINT32(reg_almsec, Exynos4210RTCState),
    131         VMSTATE_UINT32(reg_almmin, Exynos4210RTCState),
    132         VMSTATE_UINT32(reg_almhour, Exynos4210RTCState),
    133         VMSTATE_UINT32(reg_almday, Exynos4210RTCState),
    134         VMSTATE_UINT32(reg_almmon, Exynos4210RTCState),
    135         VMSTATE_UINT32(reg_almyear, Exynos4210RTCState),
    136         VMSTATE_UINT32(reg_curticcnt, Exynos4210RTCState),
    137         VMSTATE_PTIMER(ptimer, Exynos4210RTCState),
    138         VMSTATE_PTIMER(ptimer_1Hz, Exynos4210RTCState),
    139         VMSTATE_UINT32(freq, Exynos4210RTCState),
    140         VMSTATE_INT32(current_tm.tm_sec, Exynos4210RTCState),
    141         VMSTATE_INT32(current_tm.tm_min, Exynos4210RTCState),
    142         VMSTATE_INT32(current_tm.tm_hour, Exynos4210RTCState),
    143         VMSTATE_INT32(current_tm.tm_wday, Exynos4210RTCState),
    144         VMSTATE_INT32(current_tm.tm_mday, Exynos4210RTCState),
    145         VMSTATE_INT32(current_tm.tm_mon, Exynos4210RTCState),
    146         VMSTATE_INT32(current_tm.tm_year, Exynos4210RTCState),
    147         VMSTATE_END_OF_LIST()
    148     }
    149 };
    150 
    151 #define BCD3DIGITS(x) \
    152     ((uint32_t)to_bcd((uint8_t)(x % 100)) + \
    153     ((uint32_t)to_bcd((uint8_t)((x % 1000) / 100)) << 8))
    154 
    155 static void check_alarm_raise(Exynos4210RTCState *s)
    156 {
    157     unsigned int alarm_raise = 0;
    158     struct tm stm = s->current_tm;
    159 
    160     if ((s->reg_rtcalm & 0x01) &&
    161         (to_bcd((uint8_t)stm.tm_sec) == (uint8_t)s->reg_almsec)) {
    162         alarm_raise = 1;
    163     }
    164     if ((s->reg_rtcalm & 0x02) &&
    165         (to_bcd((uint8_t)stm.tm_min) == (uint8_t)s->reg_almmin)) {
    166         alarm_raise = 1;
    167     }
    168     if ((s->reg_rtcalm & 0x04) &&
    169         (to_bcd((uint8_t)stm.tm_hour) == (uint8_t)s->reg_almhour)) {
    170         alarm_raise = 1;
    171     }
    172     if ((s->reg_rtcalm & 0x08) &&
    173         (to_bcd((uint8_t)stm.tm_mday) == (uint8_t)s->reg_almday)) {
    174         alarm_raise = 1;
    175     }
    176     if ((s->reg_rtcalm & 0x10) &&
    177          (to_bcd((uint8_t)stm.tm_mon) == (uint8_t)s->reg_almmon)) {
    178         alarm_raise = 1;
    179     }
    180     if ((s->reg_rtcalm & 0x20) &&
    181         (BCD3DIGITS(stm.tm_year) == s->reg_almyear)) {
    182         alarm_raise = 1;
    183     }
    184 
    185     if (alarm_raise) {
    186         DPRINTF("ALARM IRQ\n");
    187         /* set irq status */
    188         s->reg_intp |= INTP_ALM_ENABLE;
    189         qemu_irq_raise(s->alm_irq);
    190     }
    191 }
    192 
    193 /*
    194  * RTC update frequency
    195  * Parameters:
    196  *     reg_value - current RTCCON register or his new value
    197  * Must be called within a ptimer_transaction_begin/commit block for s->ptimer.
    198  */
    199 static void exynos4210_rtc_update_freq(Exynos4210RTCState *s,
    200                                        uint32_t reg_value)
    201 {
    202     uint32_t freq;
    203 
    204     freq = s->freq;
    205     /* set frequncy for time generator */
    206     s->freq = RTC_BASE_FREQ / (1 << TICCKSEL(reg_value));
    207 
    208     if (freq != s->freq) {
    209         ptimer_set_freq(s->ptimer, s->freq);
    210         DPRINTF("freq=%dHz\n", s->freq);
    211     }
    212 }
    213 
    214 /* month is between 0 and 11. */
    215 static int get_days_in_month(int month, int year)
    216 {
    217     static const int days_tab[12] = {
    218         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    219     };
    220     int d;
    221     if ((unsigned)month >= 12) {
    222         return 31;
    223     }
    224     d = days_tab[month];
    225     if (month == 1) {
    226         if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {
    227             d++;
    228         }
    229     }
    230     return d;
    231 }
    232 
    233 /* update 'tm' to the next second */
    234 static void rtc_next_second(struct tm *tm)
    235 {
    236     int days_in_month;
    237 
    238     tm->tm_sec++;
    239     if ((unsigned)tm->tm_sec >= 60) {
    240         tm->tm_sec = 0;
    241         tm->tm_min++;
    242         if ((unsigned)tm->tm_min >= 60) {
    243             tm->tm_min = 0;
    244             tm->tm_hour++;
    245             if ((unsigned)tm->tm_hour >= 24) {
    246                 tm->tm_hour = 0;
    247                 /* next day */
    248                 tm->tm_wday++;
    249                 if ((unsigned)tm->tm_wday >= 7) {
    250                     tm->tm_wday = 0;
    251                 }
    252                 days_in_month = get_days_in_month(tm->tm_mon,
    253                                                   tm->tm_year + 1900);
    254                 tm->tm_mday++;
    255                 if (tm->tm_mday < 1) {
    256                     tm->tm_mday = 1;
    257                 } else if (tm->tm_mday > days_in_month) {
    258                     tm->tm_mday = 1;
    259                     tm->tm_mon++;
    260                     if (tm->tm_mon >= 12) {
    261                         tm->tm_mon = 0;
    262                         tm->tm_year++;
    263                     }
    264                 }
    265             }
    266         }
    267     }
    268 }
    269 
    270 /*
    271  * tick handler
    272  */
    273 static void exynos4210_rtc_tick(void *opaque)
    274 {
    275     Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
    276 
    277     DPRINTF("TICK IRQ\n");
    278     /* set irq status */
    279     s->reg_intp |= INTP_TICK_ENABLE;
    280     /* raise IRQ */
    281     qemu_irq_raise(s->tick_irq);
    282 
    283     /* restart timer */
    284     ptimer_set_count(s->ptimer, s->reg_ticcnt);
    285     ptimer_run(s->ptimer, 1);
    286 }
    287 
    288 /*
    289  * 1Hz clock handler
    290  */
    291 static void exynos4210_rtc_1Hz_tick(void *opaque)
    292 {
    293     Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
    294 
    295     rtc_next_second(&s->current_tm);
    296     /* DPRINTF("1Hz tick\n"); */
    297 
    298     /* raise IRQ */
    299     if (s->reg_rtcalm & ALARM_INT_ENABLE) {
    300         check_alarm_raise(s);
    301     }
    302 
    303     ptimer_set_count(s->ptimer_1Hz, RTC_BASE_FREQ);
    304     ptimer_run(s->ptimer_1Hz, 1);
    305 }
    306 
    307 /*
    308  * RTC Read
    309  */
    310 static uint64_t exynos4210_rtc_read(void *opaque, hwaddr offset,
    311         unsigned size)
    312 {
    313     uint32_t value = 0;
    314     Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
    315 
    316     switch (offset) {
    317     case INTP:
    318         value = s->reg_intp;
    319         break;
    320     case RTCCON:
    321         value = s->reg_rtccon;
    322         break;
    323     case TICCNT:
    324         value = s->reg_ticcnt;
    325         break;
    326     case RTCALM:
    327         value = s->reg_rtcalm;
    328         break;
    329     case ALMSEC:
    330         value = s->reg_almsec;
    331         break;
    332     case ALMMIN:
    333         value = s->reg_almmin;
    334         break;
    335     case ALMHOUR:
    336         value = s->reg_almhour;
    337         break;
    338     case ALMDAY:
    339         value = s->reg_almday;
    340         break;
    341     case ALMMON:
    342         value = s->reg_almmon;
    343         break;
    344     case ALMYEAR:
    345         value = s->reg_almyear;
    346         break;
    347 
    348     case BCDSEC:
    349         value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_sec);
    350         break;
    351     case BCDMIN:
    352         value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_min);
    353         break;
    354     case BCDHOUR:
    355         value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_hour);
    356         break;
    357     case BCDDAYWEEK:
    358         value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_wday);
    359         break;
    360     case BCDDAY:
    361         value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_mday);
    362         break;
    363     case BCDMON:
    364         value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_mon + 1);
    365         break;
    366     case BCDYEAR:
    367         value = BCD3DIGITS(s->current_tm.tm_year);
    368         break;
    369 
    370     case CURTICNT:
    371         s->reg_curticcnt = ptimer_get_count(s->ptimer);
    372         value = s->reg_curticcnt;
    373         break;
    374 
    375     default:
    376         qemu_log_mask(LOG_GUEST_ERROR,
    377                       "exynos4210.rtc: bad read offset " TARGET_FMT_plx,
    378                       offset);
    379         break;
    380     }
    381     return value;
    382 }
    383 
    384 /*
    385  * RTC Write
    386  */
    387 static void exynos4210_rtc_write(void *opaque, hwaddr offset,
    388         uint64_t value, unsigned size)
    389 {
    390     Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
    391 
    392     switch (offset) {
    393     case INTP:
    394         if (value & INTP_ALM_ENABLE) {
    395             qemu_irq_lower(s->alm_irq);
    396             s->reg_intp &= (~INTP_ALM_ENABLE);
    397         }
    398         if (value & INTP_TICK_ENABLE) {
    399             qemu_irq_lower(s->tick_irq);
    400             s->reg_intp &= (~INTP_TICK_ENABLE);
    401         }
    402         break;
    403     case RTCCON:
    404         ptimer_transaction_begin(s->ptimer_1Hz);
    405         ptimer_transaction_begin(s->ptimer);
    406         if (value & RTC_ENABLE) {
    407             exynos4210_rtc_update_freq(s, value);
    408         }
    409         if ((value & RTC_ENABLE) > (s->reg_rtccon & RTC_ENABLE)) {
    410             /* clock timer */
    411             ptimer_set_count(s->ptimer_1Hz, RTC_BASE_FREQ);
    412             ptimer_run(s->ptimer_1Hz, 1);
    413             DPRINTF("run clock timer\n");
    414         }
    415         if ((value & RTC_ENABLE) < (s->reg_rtccon & RTC_ENABLE)) {
    416             /* tick timer */
    417             ptimer_stop(s->ptimer);
    418             /* clock timer */
    419             ptimer_stop(s->ptimer_1Hz);
    420             DPRINTF("stop all timers\n");
    421         }
    422         if (value & RTC_ENABLE) {
    423             if ((value & TICK_TIMER_ENABLE) >
    424                 (s->reg_rtccon & TICK_TIMER_ENABLE) &&
    425                 (s->reg_ticcnt)) {
    426                 ptimer_set_count(s->ptimer, s->reg_ticcnt);
    427                 ptimer_run(s->ptimer, 1);
    428                 DPRINTF("run tick timer\n");
    429             }
    430             if ((value & TICK_TIMER_ENABLE) <
    431                 (s->reg_rtccon & TICK_TIMER_ENABLE)) {
    432                 ptimer_stop(s->ptimer);
    433             }
    434         }
    435         ptimer_transaction_commit(s->ptimer_1Hz);
    436         ptimer_transaction_commit(s->ptimer);
    437         s->reg_rtccon = value;
    438         break;
    439     case TICCNT:
    440         if (value > TICNT_THRESHOLD) {
    441             s->reg_ticcnt = value;
    442         } else {
    443             qemu_log_mask(LOG_GUEST_ERROR,
    444                           "exynos4210.rtc: bad TICNT value %u",
    445                           (uint32_t)value);
    446         }
    447         break;
    448 
    449     case RTCALM:
    450         s->reg_rtcalm = value;
    451         break;
    452     case ALMSEC:
    453         s->reg_almsec = (value & 0x7f);
    454         break;
    455     case ALMMIN:
    456         s->reg_almmin = (value & 0x7f);
    457         break;
    458     case ALMHOUR:
    459         s->reg_almhour = (value & 0x3f);
    460         break;
    461     case ALMDAY:
    462         s->reg_almday = (value & 0x3f);
    463         break;
    464     case ALMMON:
    465         s->reg_almmon = (value & 0x1f);
    466         break;
    467     case ALMYEAR:
    468         s->reg_almyear = (value & 0x0fff);
    469         break;
    470 
    471     case BCDSEC:
    472         if (s->reg_rtccon & RTC_ENABLE) {
    473             s->current_tm.tm_sec = (int)from_bcd((uint8_t)value);
    474         }
    475         break;
    476     case BCDMIN:
    477         if (s->reg_rtccon & RTC_ENABLE) {
    478             s->current_tm.tm_min = (int)from_bcd((uint8_t)value);
    479         }
    480         break;
    481     case BCDHOUR:
    482         if (s->reg_rtccon & RTC_ENABLE) {
    483             s->current_tm.tm_hour = (int)from_bcd((uint8_t)value);
    484         }
    485         break;
    486     case BCDDAYWEEK:
    487         if (s->reg_rtccon & RTC_ENABLE) {
    488             s->current_tm.tm_wday = (int)from_bcd((uint8_t)value);
    489         }
    490         break;
    491     case BCDDAY:
    492         if (s->reg_rtccon & RTC_ENABLE) {
    493             s->current_tm.tm_mday = (int)from_bcd((uint8_t)value);
    494         }
    495         break;
    496     case BCDMON:
    497         if (s->reg_rtccon & RTC_ENABLE) {
    498             s->current_tm.tm_mon = (int)from_bcd((uint8_t)value) - 1;
    499         }
    500         break;
    501     case BCDYEAR:
    502         if (s->reg_rtccon & RTC_ENABLE) {
    503             /* 3 digits */
    504             s->current_tm.tm_year = (int)from_bcd((uint8_t)value) +
    505                     (int)from_bcd((uint8_t)((value >> 8) & 0x0f)) * 100;
    506         }
    507         break;
    508 
    509     default:
    510         qemu_log_mask(LOG_GUEST_ERROR,
    511                       "exynos4210.rtc: bad write offset " TARGET_FMT_plx,
    512                       offset);
    513         break;
    514 
    515     }
    516 }
    517 
    518 /*
    519  * Set default values to timer fields and registers
    520  */
    521 static void exynos4210_rtc_reset(DeviceState *d)
    522 {
    523     Exynos4210RTCState *s = EXYNOS4210_RTC(d);
    524 
    525     qemu_get_timedate(&s->current_tm, 0);
    526 
    527     DPRINTF("Get time from host: %d-%d-%d %2d:%02d:%02d\n",
    528             s->current_tm.tm_year, s->current_tm.tm_mon, s->current_tm.tm_mday,
    529             s->current_tm.tm_hour, s->current_tm.tm_min, s->current_tm.tm_sec);
    530 
    531     s->reg_intp = 0;
    532     s->reg_rtccon = 0;
    533     s->reg_ticcnt = 0;
    534     s->reg_rtcalm = 0;
    535     s->reg_almsec = 0;
    536     s->reg_almmin = 0;
    537     s->reg_almhour = 0;
    538     s->reg_almday = 0;
    539     s->reg_almmon = 0;
    540     s->reg_almyear = 0;
    541 
    542     s->reg_curticcnt = 0;
    543 
    544     ptimer_transaction_begin(s->ptimer);
    545     exynos4210_rtc_update_freq(s, s->reg_rtccon);
    546     ptimer_stop(s->ptimer);
    547     ptimer_transaction_commit(s->ptimer);
    548     ptimer_transaction_begin(s->ptimer_1Hz);
    549     ptimer_stop(s->ptimer_1Hz);
    550     ptimer_transaction_commit(s->ptimer_1Hz);
    551 }
    552 
    553 static const MemoryRegionOps exynos4210_rtc_ops = {
    554     .read = exynos4210_rtc_read,
    555     .write = exynos4210_rtc_write,
    556     .endianness = DEVICE_NATIVE_ENDIAN,
    557 };
    558 
    559 /*
    560  * RTC timer initialization
    561  */
    562 static void exynos4210_rtc_init(Object *obj)
    563 {
    564     Exynos4210RTCState *s = EXYNOS4210_RTC(obj);
    565     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
    566 
    567     s->ptimer = ptimer_init(exynos4210_rtc_tick, s, PTIMER_POLICY_LEGACY);
    568     ptimer_transaction_begin(s->ptimer);
    569     ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
    570     exynos4210_rtc_update_freq(s, 0);
    571     ptimer_transaction_commit(s->ptimer);
    572 
    573     s->ptimer_1Hz = ptimer_init(exynos4210_rtc_1Hz_tick,
    574                                 s, PTIMER_POLICY_LEGACY);
    575     ptimer_transaction_begin(s->ptimer_1Hz);
    576     ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
    577     ptimer_transaction_commit(s->ptimer_1Hz);
    578 
    579     sysbus_init_irq(dev, &s->alm_irq);
    580     sysbus_init_irq(dev, &s->tick_irq);
    581 
    582     memory_region_init_io(&s->iomem, obj, &exynos4210_rtc_ops, s,
    583                           "exynos4210-rtc", EXYNOS4210_RTC_REG_MEM_SIZE);
    584     sysbus_init_mmio(dev, &s->iomem);
    585 }
    586 
    587 static void exynos4210_rtc_finalize(Object *obj)
    588 {
    589     Exynos4210RTCState *s = EXYNOS4210_RTC(obj);
    590 
    591     ptimer_free(s->ptimer);
    592     ptimer_free(s->ptimer_1Hz);
    593 }
    594 
    595 static void exynos4210_rtc_class_init(ObjectClass *klass, void *data)
    596 {
    597     DeviceClass *dc = DEVICE_CLASS(klass);
    598 
    599     dc->reset = exynos4210_rtc_reset;
    600     dc->vmsd = &vmstate_exynos4210_rtc_state;
    601 }
    602 
    603 static const TypeInfo exynos4210_rtc_info = {
    604     .name          = TYPE_EXYNOS4210_RTC,
    605     .parent        = TYPE_SYS_BUS_DEVICE,
    606     .instance_size = sizeof(Exynos4210RTCState),
    607     .instance_init = exynos4210_rtc_init,
    608     .instance_finalize = exynos4210_rtc_finalize,
    609     .class_init    = exynos4210_rtc_class_init,
    610 };
    611 
    612 static void exynos4210_rtc_register_types(void)
    613 {
    614     type_register_static(&exynos4210_rtc_info);
    615 }
    616 
    617 type_init(exynos4210_rtc_register_types)