qemu

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

npcm7xx_clk.c (33246B)


      1 /*
      2  * Nuvoton NPCM7xx Clock Control Registers.
      3  *
      4  * Copyright 2020 Google LLC
      5  *
      6  * This program is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License as published by the
      8  * Free Software Foundation; either version 2 of the License, or
      9  * (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
     14  * for more details.
     15  */
     16 
     17 #include "qemu/osdep.h"
     18 
     19 #include "hw/misc/npcm7xx_clk.h"
     20 #include "hw/timer/npcm7xx_timer.h"
     21 #include "hw/qdev-clock.h"
     22 #include "migration/vmstate.h"
     23 #include "qemu/error-report.h"
     24 #include "qemu/log.h"
     25 #include "qemu/module.h"
     26 #include "qemu/timer.h"
     27 #include "qemu/units.h"
     28 #include "trace.h"
     29 #include "sysemu/watchdog.h"
     30 
     31 /*
     32  * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
     33  * is always 25 MHz.
     34  */
     35 #define NPCM7XX_CLOCK_REF_HZ            (25000000)
     36 
     37 /* Register Field Definitions */
     38 #define NPCM7XX_CLK_WDRCR_CA9C  BIT(0) /* Cortex-A9 Cores */
     39 
     40 #define PLLCON_LOKI     BIT(31)
     41 #define PLLCON_LOKS     BIT(30)
     42 #define PLLCON_PWDEN    BIT(12)
     43 #define PLLCON_FBDV(con) extract32((con), 16, 12)
     44 #define PLLCON_OTDV2(con) extract32((con), 13, 3)
     45 #define PLLCON_OTDV1(con) extract32((con), 8, 3)
     46 #define PLLCON_INDV(con) extract32((con), 0, 6)
     47 
     48 enum NPCM7xxCLKRegisters {
     49     NPCM7XX_CLK_CLKEN1,
     50     NPCM7XX_CLK_CLKSEL,
     51     NPCM7XX_CLK_CLKDIV1,
     52     NPCM7XX_CLK_PLLCON0,
     53     NPCM7XX_CLK_PLLCON1,
     54     NPCM7XX_CLK_SWRSTR,
     55     NPCM7XX_CLK_IPSRST1         = 0x20 / sizeof(uint32_t),
     56     NPCM7XX_CLK_IPSRST2,
     57     NPCM7XX_CLK_CLKEN2,
     58     NPCM7XX_CLK_CLKDIV2,
     59     NPCM7XX_CLK_CLKEN3,
     60     NPCM7XX_CLK_IPSRST3,
     61     NPCM7XX_CLK_WD0RCR,
     62     NPCM7XX_CLK_WD1RCR,
     63     NPCM7XX_CLK_WD2RCR,
     64     NPCM7XX_CLK_SWRSTC1,
     65     NPCM7XX_CLK_SWRSTC2,
     66     NPCM7XX_CLK_SWRSTC3,
     67     NPCM7XX_CLK_SWRSTC4,
     68     NPCM7XX_CLK_PLLCON2,
     69     NPCM7XX_CLK_CLKDIV3,
     70     NPCM7XX_CLK_CORSTC,
     71     NPCM7XX_CLK_PLLCONG,
     72     NPCM7XX_CLK_AHBCKFI,
     73     NPCM7XX_CLK_SECCNT,
     74     NPCM7XX_CLK_CNTR25M,
     75     NPCM7XX_CLK_REGS_END,
     76 };
     77 
     78 /*
     79  * These reset values were taken from version 0.91 of the NPCM750R data sheet.
     80  *
     81  * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
     82  * core domain reset, but this reset type is not yet supported by QEMU.
     83  */
     84 static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
     85     [NPCM7XX_CLK_CLKEN1]        = 0xffffffff,
     86     [NPCM7XX_CLK_CLKSEL]        = 0x004aaaaa,
     87     [NPCM7XX_CLK_CLKDIV1]       = 0x5413f855,
     88     [NPCM7XX_CLK_PLLCON0]       = 0x00222101 | PLLCON_LOKI,
     89     [NPCM7XX_CLK_PLLCON1]       = 0x00202101 | PLLCON_LOKI,
     90     [NPCM7XX_CLK_IPSRST1]       = 0x00001000,
     91     [NPCM7XX_CLK_IPSRST2]       = 0x80000000,
     92     [NPCM7XX_CLK_CLKEN2]        = 0xffffffff,
     93     [NPCM7XX_CLK_CLKDIV2]       = 0xaa4f8f9f,
     94     [NPCM7XX_CLK_CLKEN3]        = 0xffffffff,
     95     [NPCM7XX_CLK_IPSRST3]       = 0x03000000,
     96     [NPCM7XX_CLK_WD0RCR]        = 0xffffffff,
     97     [NPCM7XX_CLK_WD1RCR]        = 0xffffffff,
     98     [NPCM7XX_CLK_WD2RCR]        = 0xffffffff,
     99     [NPCM7XX_CLK_SWRSTC1]       = 0x00000003,
    100     [NPCM7XX_CLK_PLLCON2]       = 0x00c02105 | PLLCON_LOKI,
    101     [NPCM7XX_CLK_CORSTC]        = 0x04000003,
    102     [NPCM7XX_CLK_PLLCONG]       = 0x01228606 | PLLCON_LOKI,
    103     [NPCM7XX_CLK_AHBCKFI]       = 0x000000c8,
    104 };
    105 
    106 /* The number of watchdogs that can trigger a reset. */
    107 #define NPCM7XX_NR_WATCHDOGS    (3)
    108 
    109 /* Clock converter functions */
    110 
    111 #define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
    112 #define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
    113         (obj), TYPE_NPCM7XX_CLOCK_PLL)
    114 #define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
    115 #define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
    116         (obj), TYPE_NPCM7XX_CLOCK_SEL)
    117 #define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
    118 #define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
    119         (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
    120 
    121 static void npcm7xx_clk_update_pll(void *opaque)
    122 {
    123     NPCM7xxClockPLLState *s = opaque;
    124     uint32_t con = s->clk->regs[s->reg];
    125     uint64_t freq;
    126 
    127     /* The PLL is grounded if it is not locked yet. */
    128     if (con & PLLCON_LOKI) {
    129         freq = clock_get_hz(s->clock_in);
    130         freq *= PLLCON_FBDV(con);
    131         freq /= PLLCON_INDV(con) * PLLCON_OTDV1(con) * PLLCON_OTDV2(con);
    132     } else {
    133         freq = 0;
    134     }
    135 
    136     clock_update_hz(s->clock_out, freq);
    137 }
    138 
    139 static void npcm7xx_clk_update_sel(void *opaque)
    140 {
    141     NPCM7xxClockSELState *s = opaque;
    142     uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
    143             s->len);
    144 
    145     if (index >= s->input_size) {
    146         qemu_log_mask(LOG_GUEST_ERROR,
    147                       "%s: SEL index: %u out of range\n",
    148                       __func__, index);
    149         index = 0;
    150     }
    151     clock_update_hz(s->clock_out, clock_get_hz(s->clock_in[index]));
    152 }
    153 
    154 static void npcm7xx_clk_update_divider(void *opaque)
    155 {
    156     NPCM7xxClockDividerState *s = opaque;
    157     uint32_t freq;
    158 
    159     freq = s->divide(s);
    160     clock_update_hz(s->clock_out, freq);
    161 }
    162 
    163 static uint32_t divide_by_constant(NPCM7xxClockDividerState *s)
    164 {
    165     return clock_get_hz(s->clock_in) / s->divisor;
    166 }
    167 
    168 static uint32_t divide_by_reg_divisor(NPCM7xxClockDividerState *s)
    169 {
    170     return clock_get_hz(s->clock_in) /
    171             (extract32(s->clk->regs[s->reg], s->offset, s->len) + 1);
    172 }
    173 
    174 static uint32_t divide_by_reg_divisor_times_2(NPCM7xxClockDividerState *s)
    175 {
    176     return divide_by_reg_divisor(s) / 2;
    177 }
    178 
    179 static uint32_t shift_by_reg_divisor(NPCM7xxClockDividerState *s)
    180 {
    181     return clock_get_hz(s->clock_in) >>
    182         extract32(s->clk->regs[s->reg], s->offset, s->len);
    183 }
    184 
    185 static NPCM7xxClockPLL find_pll_by_reg(enum NPCM7xxCLKRegisters reg)
    186 {
    187     switch (reg) {
    188     case NPCM7XX_CLK_PLLCON0:
    189         return NPCM7XX_CLOCK_PLL0;
    190     case NPCM7XX_CLK_PLLCON1:
    191         return NPCM7XX_CLOCK_PLL1;
    192     case NPCM7XX_CLK_PLLCON2:
    193         return NPCM7XX_CLOCK_PLL2;
    194     case NPCM7XX_CLK_PLLCONG:
    195         return NPCM7XX_CLOCK_PLLG;
    196     default:
    197         g_assert_not_reached();
    198     }
    199 }
    200 
    201 static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
    202 {
    203     int i;
    204 
    205     for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
    206         npcm7xx_clk_update_pll(&clk->plls[i]);
    207     }
    208 }
    209 
    210 static void npcm7xx_clk_update_all_sels(NPCM7xxCLKState *clk)
    211 {
    212     int i;
    213 
    214     for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
    215         npcm7xx_clk_update_sel(&clk->sels[i]);
    216     }
    217 }
    218 
    219 static void npcm7xx_clk_update_all_dividers(NPCM7xxCLKState *clk)
    220 {
    221     int i;
    222 
    223     for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
    224         npcm7xx_clk_update_divider(&clk->dividers[i]);
    225     }
    226 }
    227 
    228 static void npcm7xx_clk_update_all_clocks(NPCM7xxCLKState *clk)
    229 {
    230     clock_update_hz(clk->clkref, NPCM7XX_CLOCK_REF_HZ);
    231     npcm7xx_clk_update_all_plls(clk);
    232     npcm7xx_clk_update_all_sels(clk);
    233     npcm7xx_clk_update_all_dividers(clk);
    234 }
    235 
    236 /* Types of clock sources. */
    237 typedef enum ClockSrcType {
    238     CLKSRC_REF,
    239     CLKSRC_PLL,
    240     CLKSRC_SEL,
    241     CLKSRC_DIV,
    242 } ClockSrcType;
    243 
    244 typedef struct PLLInitInfo {
    245     const char *name;
    246     ClockSrcType src_type;
    247     int src_index;
    248     int reg;
    249     const char *public_name;
    250 } PLLInitInfo;
    251 
    252 typedef struct SELInitInfo {
    253     const char *name;
    254     uint8_t input_size;
    255     ClockSrcType src_type[NPCM7XX_CLK_SEL_MAX_INPUT];
    256     int src_index[NPCM7XX_CLK_SEL_MAX_INPUT];
    257     int offset;
    258     int len;
    259     const char *public_name;
    260 } SELInitInfo;
    261 
    262 typedef struct DividerInitInfo {
    263     const char *name;
    264     ClockSrcType src_type;
    265     int src_index;
    266     uint32_t (*divide)(NPCM7xxClockDividerState *s);
    267     int reg; /* not used when type == CONSTANT */
    268     int offset; /* not used when type == CONSTANT */
    269     int len; /* not used when type == CONSTANT */
    270     int divisor; /* used only when type == CONSTANT */
    271     const char *public_name;
    272 } DividerInitInfo;
    273 
    274 static const PLLInitInfo pll_init_info_list[] = {
    275     [NPCM7XX_CLOCK_PLL0] = {
    276         .name = "pll0",
    277         .src_type = CLKSRC_REF,
    278         .reg = NPCM7XX_CLK_PLLCON0,
    279     },
    280     [NPCM7XX_CLOCK_PLL1] = {
    281         .name = "pll1",
    282         .src_type = CLKSRC_REF,
    283         .reg = NPCM7XX_CLK_PLLCON1,
    284     },
    285     [NPCM7XX_CLOCK_PLL2] = {
    286         .name = "pll2",
    287         .src_type = CLKSRC_REF,
    288         .reg = NPCM7XX_CLK_PLLCON2,
    289     },
    290     [NPCM7XX_CLOCK_PLLG] = {
    291         .name = "pllg",
    292         .src_type = CLKSRC_REF,
    293         .reg = NPCM7XX_CLK_PLLCONG,
    294     },
    295 };
    296 
    297 static const SELInitInfo sel_init_info_list[] = {
    298     [NPCM7XX_CLOCK_PIXCKSEL] = {
    299         .name = "pixcksel",
    300         .input_size = 2,
    301         .src_type = {CLKSRC_PLL, CLKSRC_REF},
    302         .src_index = {NPCM7XX_CLOCK_PLLG, 0},
    303         .offset = 5,
    304         .len = 1,
    305         .public_name = "pixel-clock",
    306     },
    307     [NPCM7XX_CLOCK_MCCKSEL] = {
    308         .name = "mccksel",
    309         .input_size = 4,
    310         .src_type = {CLKSRC_DIV, CLKSRC_REF, CLKSRC_REF,
    311             /*MCBPCK, shouldn't be used in normal operation*/
    312             CLKSRC_REF},
    313         .src_index = {NPCM7XX_CLOCK_PLL1D2, 0, 0, 0},
    314         .offset = 12,
    315         .len = 2,
    316         .public_name = "mc-phy-clock",
    317     },
    318     [NPCM7XX_CLOCK_CPUCKSEL] = {
    319         .name = "cpucksel",
    320         .input_size = 4,
    321         .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
    322             /*SYSBPCK, shouldn't be used in normal operation*/
    323             CLKSRC_REF},
    324         .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0, 0},
    325         .offset = 0,
    326         .len = 2,
    327         .public_name = "system-clock",
    328     },
    329     [NPCM7XX_CLOCK_CLKOUTSEL] = {
    330         .name = "clkoutsel",
    331         .input_size = 5,
    332         .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
    333             CLKSRC_PLL, CLKSRC_DIV},
    334         .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
    335             NPCM7XX_CLOCK_PLLG, NPCM7XX_CLOCK_PLL2D2},
    336         .offset = 18,
    337         .len = 3,
    338         .public_name = "tock",
    339     },
    340     [NPCM7XX_CLOCK_UARTCKSEL] = {
    341         .name = "uartcksel",
    342         .input_size = 4,
    343         .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
    344         .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
    345             NPCM7XX_CLOCK_PLL2D2},
    346         .offset = 8,
    347         .len = 2,
    348     },
    349     [NPCM7XX_CLOCK_TIMCKSEL] = {
    350         .name = "timcksel",
    351         .input_size = 4,
    352         .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
    353         .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
    354             NPCM7XX_CLOCK_PLL2D2},
    355         .offset = 14,
    356         .len = 2,
    357     },
    358     [NPCM7XX_CLOCK_SDCKSEL] = {
    359         .name = "sdcksel",
    360         .input_size = 4,
    361         .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
    362         .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
    363             NPCM7XX_CLOCK_PLL2D2},
    364         .offset = 6,
    365         .len = 2,
    366     },
    367     [NPCM7XX_CLOCK_GFXMSEL] = {
    368         .name = "gfxmksel",
    369         .input_size = 2,
    370         .src_type = {CLKSRC_REF, CLKSRC_PLL},
    371         .src_index = {0, NPCM7XX_CLOCK_PLL2},
    372         .offset = 21,
    373         .len = 1,
    374     },
    375     [NPCM7XX_CLOCK_SUCKSEL] = {
    376         .name = "sucksel",
    377         .input_size = 4,
    378         .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
    379         .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
    380             NPCM7XX_CLOCK_PLL2D2},
    381         .offset = 10,
    382         .len = 2,
    383     },
    384 };
    385 
    386 static const DividerInitInfo divider_init_info_list[] = {
    387     [NPCM7XX_CLOCK_PLL1D2] = {
    388         .name = "pll1d2",
    389         .src_type = CLKSRC_PLL,
    390         .src_index = NPCM7XX_CLOCK_PLL1,
    391         .divide = divide_by_constant,
    392         .divisor = 2,
    393     },
    394     [NPCM7XX_CLOCK_PLL2D2] = {
    395         .name = "pll2d2",
    396         .src_type = CLKSRC_PLL,
    397         .src_index = NPCM7XX_CLOCK_PLL2,
    398         .divide = divide_by_constant,
    399         .divisor = 2,
    400     },
    401     [NPCM7XX_CLOCK_MC_DIVIDER] = {
    402         .name = "mc-divider",
    403         .src_type = CLKSRC_SEL,
    404         .src_index = NPCM7XX_CLOCK_MCCKSEL,
    405         .divide = divide_by_constant,
    406         .divisor = 2,
    407         .public_name = "mc-clock"
    408     },
    409     [NPCM7XX_CLOCK_AXI_DIVIDER] = {
    410         .name = "axi-divider",
    411         .src_type = CLKSRC_SEL,
    412         .src_index = NPCM7XX_CLOCK_CPUCKSEL,
    413         .divide = shift_by_reg_divisor,
    414         .reg = NPCM7XX_CLK_CLKDIV1,
    415         .offset = 0,
    416         .len = 1,
    417         .public_name = "clk2"
    418     },
    419     [NPCM7XX_CLOCK_AHB_DIVIDER] = {
    420         .name = "ahb-divider",
    421         .src_type = CLKSRC_DIV,
    422         .src_index = NPCM7XX_CLOCK_AXI_DIVIDER,
    423         .divide = divide_by_reg_divisor,
    424         .reg = NPCM7XX_CLK_CLKDIV1,
    425         .offset = 26,
    426         .len = 2,
    427         .public_name = "clk4"
    428     },
    429     [NPCM7XX_CLOCK_AHB3_DIVIDER] = {
    430         .name = "ahb3-divider",
    431         .src_type = CLKSRC_DIV,
    432         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    433         .divide = divide_by_reg_divisor,
    434         .reg = NPCM7XX_CLK_CLKDIV1,
    435         .offset = 6,
    436         .len = 5,
    437         .public_name = "ahb3-spi3-clock"
    438     },
    439     [NPCM7XX_CLOCK_SPI0_DIVIDER] = {
    440         .name = "spi0-divider",
    441         .src_type = CLKSRC_DIV,
    442         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    443         .divide = divide_by_reg_divisor,
    444         .reg = NPCM7XX_CLK_CLKDIV3,
    445         .offset = 6,
    446         .len = 5,
    447         .public_name = "spi0-clock",
    448     },
    449     [NPCM7XX_CLOCK_SPIX_DIVIDER] = {
    450         .name = "spix-divider",
    451         .src_type = CLKSRC_DIV,
    452         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    453         .divide = divide_by_reg_divisor,
    454         .reg = NPCM7XX_CLK_CLKDIV3,
    455         .offset = 1,
    456         .len = 5,
    457         .public_name = "spix-clock",
    458     },
    459     [NPCM7XX_CLOCK_APB1_DIVIDER] = {
    460         .name = "apb1-divider",
    461         .src_type = CLKSRC_DIV,
    462         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    463         .divide = shift_by_reg_divisor,
    464         .reg = NPCM7XX_CLK_CLKDIV2,
    465         .offset = 24,
    466         .len = 2,
    467         .public_name = "apb1-clock",
    468     },
    469     [NPCM7XX_CLOCK_APB2_DIVIDER] = {
    470         .name = "apb2-divider",
    471         .src_type = CLKSRC_DIV,
    472         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    473         .divide = shift_by_reg_divisor,
    474         .reg = NPCM7XX_CLK_CLKDIV2,
    475         .offset = 26,
    476         .len = 2,
    477         .public_name = "apb2-clock",
    478     },
    479     [NPCM7XX_CLOCK_APB3_DIVIDER] = {
    480         .name = "apb3-divider",
    481         .src_type = CLKSRC_DIV,
    482         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    483         .divide = shift_by_reg_divisor,
    484         .reg = NPCM7XX_CLK_CLKDIV2,
    485         .offset = 28,
    486         .len = 2,
    487         .public_name = "apb3-clock",
    488     },
    489     [NPCM7XX_CLOCK_APB4_DIVIDER] = {
    490         .name = "apb4-divider",
    491         .src_type = CLKSRC_DIV,
    492         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    493         .divide = shift_by_reg_divisor,
    494         .reg = NPCM7XX_CLK_CLKDIV2,
    495         .offset = 30,
    496         .len = 2,
    497         .public_name = "apb4-clock",
    498     },
    499     [NPCM7XX_CLOCK_APB5_DIVIDER] = {
    500         .name = "apb5-divider",
    501         .src_type = CLKSRC_DIV,
    502         .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
    503         .divide = shift_by_reg_divisor,
    504         .reg = NPCM7XX_CLK_CLKDIV2,
    505         .offset = 22,
    506         .len = 2,
    507         .public_name = "apb5-clock",
    508     },
    509     [NPCM7XX_CLOCK_CLKOUT_DIVIDER] = {
    510         .name = "clkout-divider",
    511         .src_type = CLKSRC_SEL,
    512         .src_index = NPCM7XX_CLOCK_CLKOUTSEL,
    513         .divide = divide_by_reg_divisor,
    514         .reg = NPCM7XX_CLK_CLKDIV2,
    515         .offset = 16,
    516         .len = 5,
    517         .public_name = "clkout",
    518     },
    519     [NPCM7XX_CLOCK_UART_DIVIDER] = {
    520         .name = "uart-divider",
    521         .src_type = CLKSRC_SEL,
    522         .src_index = NPCM7XX_CLOCK_UARTCKSEL,
    523         .divide = divide_by_reg_divisor,
    524         .reg = NPCM7XX_CLK_CLKDIV1,
    525         .offset = 16,
    526         .len = 5,
    527         .public_name = "uart-clock",
    528     },
    529     [NPCM7XX_CLOCK_TIMER_DIVIDER] = {
    530         .name = "timer-divider",
    531         .src_type = CLKSRC_SEL,
    532         .src_index = NPCM7XX_CLOCK_TIMCKSEL,
    533         .divide = divide_by_reg_divisor,
    534         .reg = NPCM7XX_CLK_CLKDIV1,
    535         .offset = 21,
    536         .len = 5,
    537         .public_name = "timer-clock",
    538     },
    539     [NPCM7XX_CLOCK_ADC_DIVIDER] = {
    540         .name = "adc-divider",
    541         .src_type = CLKSRC_DIV,
    542         .src_index = NPCM7XX_CLOCK_TIMER_DIVIDER,
    543         .divide = shift_by_reg_divisor,
    544         .reg = NPCM7XX_CLK_CLKDIV1,
    545         .offset = 28,
    546         .len = 3,
    547         .public_name = "adc-clock",
    548     },
    549     [NPCM7XX_CLOCK_MMC_DIVIDER] = {
    550         .name = "mmc-divider",
    551         .src_type = CLKSRC_SEL,
    552         .src_index = NPCM7XX_CLOCK_SDCKSEL,
    553         .divide = divide_by_reg_divisor,
    554         .reg = NPCM7XX_CLK_CLKDIV1,
    555         .offset = 11,
    556         .len = 5,
    557         .public_name = "mmc-clock",
    558     },
    559     [NPCM7XX_CLOCK_SDHC_DIVIDER] = {
    560         .name = "sdhc-divider",
    561         .src_type = CLKSRC_SEL,
    562         .src_index = NPCM7XX_CLOCK_SDCKSEL,
    563         .divide = divide_by_reg_divisor_times_2,
    564         .reg = NPCM7XX_CLK_CLKDIV2,
    565         .offset = 0,
    566         .len = 4,
    567         .public_name = "sdhc-clock",
    568     },
    569     [NPCM7XX_CLOCK_GFXM_DIVIDER] = {
    570         .name = "gfxm-divider",
    571         .src_type = CLKSRC_SEL,
    572         .src_index = NPCM7XX_CLOCK_GFXMSEL,
    573         .divide = divide_by_constant,
    574         .divisor = 3,
    575         .public_name = "gfxm-clock",
    576     },
    577     [NPCM7XX_CLOCK_UTMI_DIVIDER] = {
    578         .name = "utmi-divider",
    579         .src_type = CLKSRC_SEL,
    580         .src_index = NPCM7XX_CLOCK_SUCKSEL,
    581         .divide = divide_by_reg_divisor,
    582         .reg = NPCM7XX_CLK_CLKDIV2,
    583         .offset = 8,
    584         .len = 5,
    585         .public_name = "utmi-clock",
    586     },
    587 };
    588 
    589 static void npcm7xx_clk_update_pll_cb(void *opaque, ClockEvent event)
    590 {
    591     npcm7xx_clk_update_pll(opaque);
    592 }
    593 
    594 static void npcm7xx_clk_pll_init(Object *obj)
    595 {
    596     NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
    597 
    598     pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
    599                                        npcm7xx_clk_update_pll_cb, pll,
    600                                        ClockUpdate);
    601     pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
    602 }
    603 
    604 static void npcm7xx_clk_update_sel_cb(void *opaque, ClockEvent event)
    605 {
    606     npcm7xx_clk_update_sel(opaque);
    607 }
    608 
    609 static void npcm7xx_clk_sel_init(Object *obj)
    610 {
    611     int i;
    612     NPCM7xxClockSELState *sel = NPCM7XX_CLOCK_SEL(obj);
    613 
    614     for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
    615         g_autofree char *s = g_strdup_printf("clock-in[%d]", i);
    616         sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel), s,
    617                 npcm7xx_clk_update_sel_cb, sel, ClockUpdate);
    618     }
    619     sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
    620 }
    621 
    622 static void npcm7xx_clk_update_divider_cb(void *opaque, ClockEvent event)
    623 {
    624     npcm7xx_clk_update_divider(opaque);
    625 }
    626 
    627 static void npcm7xx_clk_divider_init(Object *obj)
    628 {
    629     NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
    630 
    631     div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
    632                                        npcm7xx_clk_update_divider_cb,
    633                                        div, ClockUpdate);
    634     div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
    635 }
    636 
    637 static void npcm7xx_init_clock_pll(NPCM7xxClockPLLState *pll,
    638         NPCM7xxCLKState *clk, const PLLInitInfo *init_info)
    639 {
    640     pll->name = init_info->name;
    641     pll->clk = clk;
    642     pll->reg = init_info->reg;
    643     if (init_info->public_name != NULL) {
    644         qdev_alias_clock(DEVICE(pll), "clock-out", DEVICE(clk),
    645                 init_info->public_name);
    646     }
    647 }
    648 
    649 static void npcm7xx_init_clock_sel(NPCM7xxClockSELState *sel,
    650         NPCM7xxCLKState *clk, const SELInitInfo *init_info)
    651 {
    652     int input_size = init_info->input_size;
    653 
    654     sel->name = init_info->name;
    655     sel->clk = clk;
    656     sel->input_size = init_info->input_size;
    657     g_assert(input_size <= NPCM7XX_CLK_SEL_MAX_INPUT);
    658     sel->offset = init_info->offset;
    659     sel->len = init_info->len;
    660     if (init_info->public_name != NULL) {
    661         qdev_alias_clock(DEVICE(sel), "clock-out", DEVICE(clk),
    662                 init_info->public_name);
    663     }
    664 }
    665 
    666 static void npcm7xx_init_clock_divider(NPCM7xxClockDividerState *div,
    667         NPCM7xxCLKState *clk, const DividerInitInfo *init_info)
    668 {
    669     div->name = init_info->name;
    670     div->clk = clk;
    671 
    672     div->divide = init_info->divide;
    673     if (div->divide == divide_by_constant) {
    674         div->divisor = init_info->divisor;
    675     } else {
    676         div->reg = init_info->reg;
    677         div->offset = init_info->offset;
    678         div->len = init_info->len;
    679     }
    680     if (init_info->public_name != NULL) {
    681         qdev_alias_clock(DEVICE(div), "clock-out", DEVICE(clk),
    682                 init_info->public_name);
    683     }
    684 }
    685 
    686 static Clock *npcm7xx_get_clock(NPCM7xxCLKState *clk, ClockSrcType type,
    687         int index)
    688 {
    689     switch (type) {
    690     case CLKSRC_REF:
    691         return clk->clkref;
    692     case CLKSRC_PLL:
    693         return clk->plls[index].clock_out;
    694     case CLKSRC_SEL:
    695         return clk->sels[index].clock_out;
    696     case CLKSRC_DIV:
    697         return clk->dividers[index].clock_out;
    698     default:
    699         g_assert_not_reached();
    700     }
    701 }
    702 
    703 static void npcm7xx_connect_clocks(NPCM7xxCLKState *clk)
    704 {
    705     int i, j;
    706     Clock *src;
    707 
    708     for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
    709         src = npcm7xx_get_clock(clk, pll_init_info_list[i].src_type,
    710                 pll_init_info_list[i].src_index);
    711         clock_set_source(clk->plls[i].clock_in, src);
    712     }
    713     for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
    714         for (j = 0; j < sel_init_info_list[i].input_size; ++j) {
    715             src = npcm7xx_get_clock(clk, sel_init_info_list[i].src_type[j],
    716                     sel_init_info_list[i].src_index[j]);
    717             clock_set_source(clk->sels[i].clock_in[j], src);
    718         }
    719     }
    720     for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
    721         src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
    722                 divider_init_info_list[i].src_index);
    723         clock_set_source(clk->dividers[i].clock_in, src);
    724     }
    725 }
    726 
    727 static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
    728 {
    729     uint32_t reg = offset / sizeof(uint32_t);
    730     NPCM7xxCLKState *s = opaque;
    731     int64_t now_ns;
    732     uint32_t value = 0;
    733 
    734     if (reg >= NPCM7XX_CLK_NR_REGS) {
    735         qemu_log_mask(LOG_GUEST_ERROR,
    736                       "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
    737                       __func__, offset);
    738         return 0;
    739     }
    740 
    741     switch (reg) {
    742     case NPCM7XX_CLK_SWRSTR:
    743         qemu_log_mask(LOG_GUEST_ERROR,
    744                       "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
    745                       __func__, offset);
    746         break;
    747 
    748     case NPCM7XX_CLK_SECCNT:
    749         now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    750         value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND;
    751         break;
    752 
    753     case NPCM7XX_CLK_CNTR25M:
    754         now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    755         /*
    756          * This register counts 25 MHz cycles, updating every 640 ns. It rolls
    757          * over to zero every second.
    758          *
    759          * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
    760          */
    761         value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
    762         break;
    763 
    764     default:
    765         value = s->regs[reg];
    766         break;
    767     };
    768 
    769     trace_npcm7xx_clk_read(offset, value);
    770 
    771     return value;
    772 }
    773 
    774 static void npcm7xx_clk_write(void *opaque, hwaddr offset,
    775                               uint64_t v, unsigned size)
    776 {
    777     uint32_t reg = offset / sizeof(uint32_t);
    778     NPCM7xxCLKState *s = opaque;
    779     uint32_t value = v;
    780 
    781     trace_npcm7xx_clk_write(offset, value);
    782 
    783     if (reg >= NPCM7XX_CLK_NR_REGS) {
    784         qemu_log_mask(LOG_GUEST_ERROR,
    785                       "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
    786                       __func__, offset);
    787         return;
    788     }
    789 
    790     switch (reg) {
    791     case NPCM7XX_CLK_SWRSTR:
    792         qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n",
    793                       __func__, value);
    794         value = 0;
    795         break;
    796 
    797     case NPCM7XX_CLK_PLLCON0:
    798     case NPCM7XX_CLK_PLLCON1:
    799     case NPCM7XX_CLK_PLLCON2:
    800     case NPCM7XX_CLK_PLLCONG:
    801         if (value & PLLCON_PWDEN) {
    802             /* Power down -- clear lock and indicate loss of lock */
    803             value &= ~PLLCON_LOKI;
    804             value |= PLLCON_LOKS;
    805         } else {
    806             /* Normal mode -- assume always locked */
    807             value |= PLLCON_LOKI;
    808             /* Keep LOKS unchanged unless cleared by writing 1 */
    809             if (value & PLLCON_LOKS) {
    810                 value &= ~PLLCON_LOKS;
    811             } else {
    812                 value |= (value & PLLCON_LOKS);
    813             }
    814         }
    815         /* Only update PLL when it is locked. */
    816         if (value & PLLCON_LOKI) {
    817             npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
    818         }
    819         break;
    820 
    821     case NPCM7XX_CLK_CLKSEL:
    822         npcm7xx_clk_update_all_sels(s);
    823         break;
    824 
    825     case NPCM7XX_CLK_CLKDIV1:
    826     case NPCM7XX_CLK_CLKDIV2:
    827     case NPCM7XX_CLK_CLKDIV3:
    828         npcm7xx_clk_update_all_dividers(s);
    829         break;
    830 
    831     case NPCM7XX_CLK_CNTR25M:
    832         qemu_log_mask(LOG_GUEST_ERROR,
    833                       "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
    834                       __func__, offset);
    835         return;
    836     }
    837 
    838     s->regs[reg] = value;
    839 }
    840 
    841 /* Perform reset action triggered by a watchdog */
    842 static void npcm7xx_clk_perform_watchdog_reset(void *opaque, int n,
    843         int level)
    844 {
    845     NPCM7xxCLKState *clk = NPCM7XX_CLK(opaque);
    846     uint32_t rcr;
    847 
    848     g_assert(n >= 0 && n <= NPCM7XX_NR_WATCHDOGS);
    849     rcr = clk->regs[NPCM7XX_CLK_WD0RCR + n];
    850     if (rcr & NPCM7XX_CLK_WDRCR_CA9C) {
    851         watchdog_perform_action();
    852     } else {
    853         qemu_log_mask(LOG_UNIMP,
    854                 "%s: only CPU reset is implemented. (requested 0x%" PRIx32")\n",
    855                 __func__, rcr);
    856     }
    857 }
    858 
    859 static const struct MemoryRegionOps npcm7xx_clk_ops = {
    860     .read       = npcm7xx_clk_read,
    861     .write      = npcm7xx_clk_write,
    862     .endianness = DEVICE_LITTLE_ENDIAN,
    863     .valid      = {
    864         .min_access_size        = 4,
    865         .max_access_size        = 4,
    866         .unaligned              = false,
    867     },
    868 };
    869 
    870 static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
    871 {
    872     NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
    873 
    874     QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
    875 
    876     switch (type) {
    877     case RESET_TYPE_COLD:
    878         memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
    879         s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    880         npcm7xx_clk_update_all_clocks(s);
    881         return;
    882     }
    883 
    884     /*
    885      * A small number of registers need to be reset on a core domain reset,
    886      * but no such reset type exists yet.
    887      */
    888     qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
    889                   __func__, type);
    890 }
    891 
    892 static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
    893 {
    894     int i;
    895 
    896     s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL, 0);
    897 
    898     /* First pass: init all converter modules */
    899     QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
    900     QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
    901     QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
    902             != NPCM7XX_CLOCK_NR_DIVIDERS);
    903     for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
    904         object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
    905                 &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
    906         npcm7xx_init_clock_pll(&s->plls[i], s,
    907                 &pll_init_info_list[i]);
    908     }
    909     for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
    910         object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
    911                 &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
    912         npcm7xx_init_clock_sel(&s->sels[i], s,
    913                 &sel_init_info_list[i]);
    914     }
    915     for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
    916         object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
    917                 &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
    918         npcm7xx_init_clock_divider(&s->dividers[i], s,
    919                 &divider_init_info_list[i]);
    920     }
    921 
    922     /* Second pass: connect converter modules */
    923     npcm7xx_connect_clocks(s);
    924 
    925     clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
    926 }
    927 
    928 static void npcm7xx_clk_init(Object *obj)
    929 {
    930     NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
    931 
    932     memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
    933                           TYPE_NPCM7XX_CLK, 4 * KiB);
    934     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
    935 }
    936 
    937 static int npcm7xx_clk_post_load(void *opaque, int version_id)
    938 {
    939     if (version_id >= 1) {
    940         NPCM7xxCLKState *clk = opaque;
    941 
    942         npcm7xx_clk_update_all_clocks(clk);
    943     }
    944 
    945     return 0;
    946 }
    947 
    948 static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
    949 {
    950     int i;
    951     NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
    952 
    953     qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
    954             NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
    955     npcm7xx_clk_init_clock_hierarchy(s);
    956 
    957     /* Realize child devices */
    958     for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
    959         if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
    960             return;
    961         }
    962     }
    963     for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
    964         if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
    965             return;
    966         }
    967     }
    968     for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
    969         if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
    970             return;
    971         }
    972     }
    973 }
    974 
    975 static const VMStateDescription vmstate_npcm7xx_clk_pll = {
    976     .name = "npcm7xx-clock-pll",
    977     .version_id = 0,
    978     .minimum_version_id = 0,
    979     .fields =  (VMStateField[]) {
    980         VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
    981         VMSTATE_END_OF_LIST(),
    982     },
    983 };
    984 
    985 static const VMStateDescription vmstate_npcm7xx_clk_sel = {
    986     .name = "npcm7xx-clock-sel",
    987     .version_id = 0,
    988     .minimum_version_id = 0,
    989     .fields =  (VMStateField[]) {
    990         VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
    991                 NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
    992         VMSTATE_END_OF_LIST(),
    993     },
    994 };
    995 
    996 static const VMStateDescription vmstate_npcm7xx_clk_divider = {
    997     .name = "npcm7xx-clock-divider",
    998     .version_id = 0,
    999     .minimum_version_id = 0,
   1000     .fields =  (VMStateField[]) {
   1001         VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
   1002         VMSTATE_END_OF_LIST(),
   1003     },
   1004 };
   1005 
   1006 static const VMStateDescription vmstate_npcm7xx_clk = {
   1007     .name = "npcm7xx-clk",
   1008     .version_id = 1,
   1009     .minimum_version_id = 1,
   1010     .post_load = npcm7xx_clk_post_load,
   1011     .fields = (VMStateField[]) {
   1012         VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
   1013         VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
   1014         VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
   1015         VMSTATE_END_OF_LIST(),
   1016     },
   1017 };
   1018 
   1019 static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
   1020 {
   1021     DeviceClass *dc = DEVICE_CLASS(klass);
   1022 
   1023     dc->desc = "NPCM7xx Clock PLL Module";
   1024     dc->vmsd = &vmstate_npcm7xx_clk_pll;
   1025 }
   1026 
   1027 static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
   1028 {
   1029     DeviceClass *dc = DEVICE_CLASS(klass);
   1030 
   1031     dc->desc = "NPCM7xx Clock SEL Module";
   1032     dc->vmsd = &vmstate_npcm7xx_clk_sel;
   1033 }
   1034 
   1035 static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
   1036 {
   1037     DeviceClass *dc = DEVICE_CLASS(klass);
   1038 
   1039     dc->desc = "NPCM7xx Clock Divider Module";
   1040     dc->vmsd = &vmstate_npcm7xx_clk_divider;
   1041 }
   1042 
   1043 static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
   1044 {
   1045     ResettableClass *rc = RESETTABLE_CLASS(klass);
   1046     DeviceClass *dc = DEVICE_CLASS(klass);
   1047 
   1048     QEMU_BUILD_BUG_ON(NPCM7XX_CLK_REGS_END > NPCM7XX_CLK_NR_REGS);
   1049 
   1050     dc->desc = "NPCM7xx Clock Control Registers";
   1051     dc->vmsd = &vmstate_npcm7xx_clk;
   1052     dc->realize = npcm7xx_clk_realize;
   1053     rc->phases.enter = npcm7xx_clk_enter_reset;
   1054 }
   1055 
   1056 static const TypeInfo npcm7xx_clk_pll_info = {
   1057     .name               = TYPE_NPCM7XX_CLOCK_PLL,
   1058     .parent             = TYPE_DEVICE,
   1059     .instance_size      = sizeof(NPCM7xxClockPLLState),
   1060     .instance_init      = npcm7xx_clk_pll_init,
   1061     .class_init         = npcm7xx_clk_pll_class_init,
   1062 };
   1063 
   1064 static const TypeInfo npcm7xx_clk_sel_info = {
   1065     .name               = TYPE_NPCM7XX_CLOCK_SEL,
   1066     .parent             = TYPE_DEVICE,
   1067     .instance_size      = sizeof(NPCM7xxClockSELState),
   1068     .instance_init      = npcm7xx_clk_sel_init,
   1069     .class_init         = npcm7xx_clk_sel_class_init,
   1070 };
   1071 
   1072 static const TypeInfo npcm7xx_clk_divider_info = {
   1073     .name               = TYPE_NPCM7XX_CLOCK_DIVIDER,
   1074     .parent             = TYPE_DEVICE,
   1075     .instance_size      = sizeof(NPCM7xxClockDividerState),
   1076     .instance_init      = npcm7xx_clk_divider_init,
   1077     .class_init         = npcm7xx_clk_divider_class_init,
   1078 };
   1079 
   1080 static const TypeInfo npcm7xx_clk_info = {
   1081     .name               = TYPE_NPCM7XX_CLK,
   1082     .parent             = TYPE_SYS_BUS_DEVICE,
   1083     .instance_size      = sizeof(NPCM7xxCLKState),
   1084     .instance_init      = npcm7xx_clk_init,
   1085     .class_init         = npcm7xx_clk_class_init,
   1086 };
   1087 
   1088 static void npcm7xx_clk_register_type(void)
   1089 {
   1090     type_register_static(&npcm7xx_clk_pll_info);
   1091     type_register_static(&npcm7xx_clk_sel_info);
   1092     type_register_static(&npcm7xx_clk_divider_info);
   1093     type_register_static(&npcm7xx_clk_info);
   1094 }
   1095 type_init(npcm7xx_clk_register_type);