cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

bcm2835_cprman.c (22912B)


      1/*
      2 * BCM2835 CPRMAN clock manager
      3 *
      4 * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
      5 *
      6 * SPDX-License-Identifier: GPL-2.0-or-later
      7 */
      8
      9/*
     10 * This peripheral is roughly divided into 3 main parts:
     11 *   - the PLLs
     12 *   - the PLL channels
     13 *   - the clock muxes
     14 *
     15 * A main oscillator (xosc) feeds all the PLLs. Each PLLs has one or more
     16 * channels. Those channel are then connected to the clock muxes. Each mux has
     17 * multiples sources (usually the xosc, some of the PLL channels and some "test
     18 * debug" clocks). A mux is configured to select a given source through its
     19 * control register. Each mux has one output clock that also goes out of the
     20 * CPRMAN. This output clock usually connects to another peripheral in the SoC
     21 * (so a given mux is dedicated to a peripheral).
     22 *
     23 * At each level (PLL, channel and mux), the clock can be altered through
     24 * dividers (and multipliers in case of the PLLs), and can be disabled (in this
     25 * case, the next levels see no clock).
     26 *
     27 * This can be sum-up as follows (this is an example and not the actual BCM2835
     28 * clock tree):
     29 *
     30 *          /-->[PLL]-|->[PLL channel]--...            [mux]--> to peripherals
     31 *          |         |->[PLL channel]  muxes takes    [mux]
     32 *          |         \->[PLL channel]  inputs from    [mux]
     33 *          |                           some channels  [mux]
     34 * [xosc]---|-->[PLL]-|->[PLL channel]  and other srcs [mux]
     35 *          |         \->[PLL channel]           ...-->[mux]
     36 *          |                                          [mux]
     37 *          \-->[PLL]--->[PLL channel]                 [mux]
     38 *
     39 * The page at https://elinux.org/The_Undocumented_Pi gives the actual clock
     40 * tree configuration.
     41 *
     42 * The CPRMAN exposes clock outputs with the name of the clock mux suffixed
     43 * with "-out" (e.g. "uart-out", "h264-out", ...).
     44 */
     45
     46#include "qemu/osdep.h"
     47#include "qemu/log.h"
     48#include "migration/vmstate.h"
     49#include "hw/qdev-properties.h"
     50#include "hw/misc/bcm2835_cprman.h"
     51#include "hw/misc/bcm2835_cprman_internals.h"
     52#include "trace.h"
     53
     54/* PLL */
     55
     56static void pll_reset(DeviceState *dev)
     57{
     58    CprmanPllState *s = CPRMAN_PLL(dev);
     59    const PLLResetInfo *info = &PLL_RESET_INFO[s->id];
     60
     61    *s->reg_cm = info->cm;
     62    *s->reg_a2w_ctrl = info->a2w_ctrl;
     63    memcpy(s->reg_a2w_ana, info->a2w_ana, sizeof(info->a2w_ana));
     64    *s->reg_a2w_frac = info->a2w_frac;
     65}
     66
     67static bool pll_is_locked(const CprmanPllState *pll)
     68{
     69    return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN)
     70        && !FIELD_EX32(*pll->reg_cm, CM_PLLx, ANARST);
     71}
     72
     73static void pll_update(CprmanPllState *pll)
     74{
     75    uint64_t freq, ndiv, fdiv, pdiv;
     76
     77    if (!pll_is_locked(pll)) {
     78        clock_update(pll->out, 0);
     79        return;
     80    }
     81
     82    pdiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PDIV);
     83
     84    if (!pdiv) {
     85        clock_update(pll->out, 0);
     86        return;
     87    }
     88
     89    ndiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, NDIV);
     90    fdiv = FIELD_EX32(*pll->reg_a2w_frac, A2W_PLLx_FRAC, FRAC);
     91
     92    if (pll->reg_a2w_ana[1] & pll->prediv_mask) {
     93        /* The prescaler doubles the parent frequency */
     94        ndiv *= 2;
     95        fdiv *= 2;
     96    }
     97
     98    /*
     99     * We have a multiplier with an integer part (ndiv) and a fractional part
    100     * (fdiv), and a divider (pdiv).
    101     */
    102    freq = clock_get_hz(pll->xosc_in) *
    103        ((ndiv << R_A2W_PLLx_FRAC_FRAC_LENGTH) + fdiv);
    104    freq /= pdiv;
    105    freq >>= R_A2W_PLLx_FRAC_FRAC_LENGTH;
    106
    107    clock_update_hz(pll->out, freq);
    108}
    109
    110static void pll_xosc_update(void *opaque, ClockEvent event)
    111{
    112    pll_update(CPRMAN_PLL(opaque));
    113}
    114
    115static void pll_init(Object *obj)
    116{
    117    CprmanPllState *s = CPRMAN_PLL(obj);
    118
    119    s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update,
    120                                    s, ClockUpdate);
    121    s->out = qdev_init_clock_out(DEVICE(s), "out");
    122}
    123
    124static const VMStateDescription pll_vmstate = {
    125    .name = TYPE_CPRMAN_PLL,
    126    .version_id = 1,
    127    .minimum_version_id = 1,
    128    .fields = (VMStateField[]) {
    129        VMSTATE_CLOCK(xosc_in, CprmanPllState),
    130        VMSTATE_END_OF_LIST()
    131    }
    132};
    133
    134static void pll_class_init(ObjectClass *klass, void *data)
    135{
    136    DeviceClass *dc = DEVICE_CLASS(klass);
    137
    138    dc->reset = pll_reset;
    139    dc->vmsd = &pll_vmstate;
    140}
    141
    142static const TypeInfo cprman_pll_info = {
    143    .name = TYPE_CPRMAN_PLL,
    144    .parent = TYPE_DEVICE,
    145    .instance_size = sizeof(CprmanPllState),
    146    .class_init = pll_class_init,
    147    .instance_init = pll_init,
    148};
    149
    150
    151/* PLL channel */
    152
    153static void pll_channel_reset(DeviceState *dev)
    154{
    155    CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(dev);
    156    const PLLChannelResetInfo *info = &PLL_CHANNEL_RESET_INFO[s->id];
    157
    158    *s->reg_a2w_ctrl = info->a2w_ctrl;
    159}
    160
    161static bool pll_channel_is_enabled(CprmanPllChannelState *channel)
    162{
    163    /*
    164     * XXX I'm not sure of the purpose of the LOAD field. The Linux driver does
    165     * not set it when enabling the channel, but does clear it when disabling
    166     * it.
    167     */
    168    return !FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DISABLE)
    169        && !(*channel->reg_cm & channel->hold_mask);
    170}
    171
    172static void pll_channel_update(CprmanPllChannelState *channel)
    173{
    174    uint64_t freq, div;
    175
    176    if (!pll_channel_is_enabled(channel)) {
    177        clock_update(channel->out, 0);
    178        return;
    179    }
    180
    181    div = FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DIV);
    182
    183    if (!div) {
    184        /*
    185         * It seems that when the divider value is 0, it is considered as
    186         * being maximum by the hardware (see the Linux driver).
    187         */
    188        div = R_A2W_PLLx_CHANNELy_DIV_MASK;
    189    }
    190
    191    /* Some channels have an additional fixed divider */
    192    freq = clock_get_hz(channel->pll_in) / (div * channel->fixed_divider);
    193
    194    clock_update_hz(channel->out, freq);
    195}
    196
    197/* Update a PLL and all its channels */
    198static void pll_update_all_channels(BCM2835CprmanState *s,
    199                                    CprmanPllState *pll)
    200{
    201    size_t i;
    202
    203    pll_update(pll);
    204
    205    for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
    206        CprmanPllChannelState *channel = &s->channels[i];
    207        if (channel->parent == pll->id) {
    208            pll_channel_update(channel);
    209        }
    210    }
    211}
    212
    213static void pll_channel_pll_in_update(void *opaque, ClockEvent event)
    214{
    215    pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
    216}
    217
    218static void pll_channel_init(Object *obj)
    219{
    220    CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
    221
    222    s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
    223                                   pll_channel_pll_in_update, s,
    224                                   ClockUpdate);
    225    s->out = qdev_init_clock_out(DEVICE(s), "out");
    226}
    227
    228static const VMStateDescription pll_channel_vmstate = {
    229    .name = TYPE_CPRMAN_PLL_CHANNEL,
    230    .version_id = 1,
    231    .minimum_version_id = 1,
    232    .fields = (VMStateField[]) {
    233        VMSTATE_CLOCK(pll_in, CprmanPllChannelState),
    234        VMSTATE_END_OF_LIST()
    235    }
    236};
    237
    238static void pll_channel_class_init(ObjectClass *klass, void *data)
    239{
    240    DeviceClass *dc = DEVICE_CLASS(klass);
    241
    242    dc->reset = pll_channel_reset;
    243    dc->vmsd = &pll_channel_vmstate;
    244}
    245
    246static const TypeInfo cprman_pll_channel_info = {
    247    .name = TYPE_CPRMAN_PLL_CHANNEL,
    248    .parent = TYPE_DEVICE,
    249    .instance_size = sizeof(CprmanPllChannelState),
    250    .class_init = pll_channel_class_init,
    251    .instance_init = pll_channel_init,
    252};
    253
    254
    255/* clock mux */
    256
    257static bool clock_mux_is_enabled(CprmanClockMuxState *mux)
    258{
    259    return FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, ENABLE);
    260}
    261
    262static void clock_mux_update(CprmanClockMuxState *mux)
    263{
    264    uint64_t freq;
    265    uint32_t div, src = FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, SRC);
    266    bool enabled = clock_mux_is_enabled(mux);
    267
    268    *mux->reg_ctl = FIELD_DP32(*mux->reg_ctl, CM_CLOCKx_CTL, BUSY, enabled);
    269
    270    if (!enabled) {
    271        clock_update(mux->out, 0);
    272        return;
    273    }
    274
    275    freq = clock_get_hz(mux->srcs[src]);
    276
    277    if (mux->int_bits == 0 && mux->frac_bits == 0) {
    278        clock_update_hz(mux->out, freq);
    279        return;
    280    }
    281
    282    /*
    283     * The divider has an integer and a fractional part. The size of each part
    284     * varies with the muxes (int_bits and frac_bits). Both parts are
    285     * concatenated, with the integer part always starting at bit 12.
    286     *
    287     *         31          12 11          0
    288     *        ------------------------------
    289     * CM_DIV |      |  int  |  frac  |    |
    290     *        ------------------------------
    291     *                <-----> <------>
    292     *                int_bits frac_bits
    293     */
    294    div = extract32(*mux->reg_div,
    295                    R_CM_CLOCKx_DIV_FRAC_LENGTH - mux->frac_bits,
    296                    mux->int_bits + mux->frac_bits);
    297
    298    if (!div) {
    299        clock_update(mux->out, 0);
    300        return;
    301    }
    302
    303    freq = muldiv64(freq, 1 << mux->frac_bits, div);
    304
    305    clock_update_hz(mux->out, freq);
    306}
    307
    308static void clock_mux_src_update(void *opaque, ClockEvent event)
    309{
    310    CprmanClockMuxState **backref = opaque;
    311    CprmanClockMuxState *s = *backref;
    312    CprmanClockMuxSource src = backref - s->backref;
    313
    314    if (FIELD_EX32(*s->reg_ctl, CM_CLOCKx_CTL, SRC) != src) {
    315        return;
    316    }
    317
    318    clock_mux_update(s);
    319}
    320
    321static void clock_mux_reset(DeviceState *dev)
    322{
    323    CprmanClockMuxState *clock = CPRMAN_CLOCK_MUX(dev);
    324    const ClockMuxResetInfo *info = &CLOCK_MUX_RESET_INFO[clock->id];
    325
    326    *clock->reg_ctl = info->cm_ctl;
    327    *clock->reg_div = info->cm_div;
    328}
    329
    330static void clock_mux_init(Object *obj)
    331{
    332    CprmanClockMuxState *s = CPRMAN_CLOCK_MUX(obj);
    333    size_t i;
    334
    335    for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) {
    336        char *name = g_strdup_printf("srcs[%zu]", i);
    337        s->backref[i] = s;
    338        s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
    339                                        clock_mux_src_update,
    340                                        &s->backref[i],
    341                                        ClockUpdate);
    342        g_free(name);
    343    }
    344
    345    s->out = qdev_init_clock_out(DEVICE(s), "out");
    346}
    347
    348static const VMStateDescription clock_mux_vmstate = {
    349    .name = TYPE_CPRMAN_CLOCK_MUX,
    350    .version_id = 1,
    351    .minimum_version_id = 1,
    352    .fields = (VMStateField[]) {
    353        VMSTATE_ARRAY_CLOCK(srcs, CprmanClockMuxState,
    354                            CPRMAN_NUM_CLOCK_MUX_SRC),
    355        VMSTATE_END_OF_LIST()
    356    }
    357};
    358
    359static void clock_mux_class_init(ObjectClass *klass, void *data)
    360{
    361    DeviceClass *dc = DEVICE_CLASS(klass);
    362
    363    dc->reset = clock_mux_reset;
    364    dc->vmsd = &clock_mux_vmstate;
    365}
    366
    367static const TypeInfo cprman_clock_mux_info = {
    368    .name = TYPE_CPRMAN_CLOCK_MUX,
    369    .parent = TYPE_DEVICE,
    370    .instance_size = sizeof(CprmanClockMuxState),
    371    .class_init = clock_mux_class_init,
    372    .instance_init = clock_mux_init,
    373};
    374
    375
    376/* DSI0HSCK mux */
    377
    378static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s)
    379{
    380    bool src_is_plld = FIELD_EX32(*s->reg_cm, CM_DSI0HSCK, SELPLLD);
    381    Clock *src = src_is_plld ? s->plld_in : s->plla_in;
    382
    383    clock_update(s->out, clock_get(src));
    384}
    385
    386static void dsi0hsck_mux_in_update(void *opaque, ClockEvent event)
    387{
    388    dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque));
    389}
    390
    391static void dsi0hsck_mux_init(Object *obj)
    392{
    393    CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj);
    394    DeviceState *dev = DEVICE(obj);
    395
    396    s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update,
    397                                    s, ClockUpdate);
    398    s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update,
    399                                    s, ClockUpdate);
    400    s->out = qdev_init_clock_out(DEVICE(s), "out");
    401}
    402
    403static const VMStateDescription dsi0hsck_mux_vmstate = {
    404    .name = TYPE_CPRMAN_DSI0HSCK_MUX,
    405    .version_id = 1,
    406    .minimum_version_id = 1,
    407    .fields = (VMStateField[]) {
    408        VMSTATE_CLOCK(plla_in, CprmanDsi0HsckMuxState),
    409        VMSTATE_CLOCK(plld_in, CprmanDsi0HsckMuxState),
    410        VMSTATE_END_OF_LIST()
    411    }
    412};
    413
    414static void dsi0hsck_mux_class_init(ObjectClass *klass, void *data)
    415{
    416    DeviceClass *dc = DEVICE_CLASS(klass);
    417
    418    dc->vmsd = &dsi0hsck_mux_vmstate;
    419}
    420
    421static const TypeInfo cprman_dsi0hsck_mux_info = {
    422    .name = TYPE_CPRMAN_DSI0HSCK_MUX,
    423    .parent = TYPE_DEVICE,
    424    .instance_size = sizeof(CprmanDsi0HsckMuxState),
    425    .class_init = dsi0hsck_mux_class_init,
    426    .instance_init = dsi0hsck_mux_init,
    427};
    428
    429
    430/* CPRMAN "top level" model */
    431
    432static uint32_t get_cm_lock(const BCM2835CprmanState *s)
    433{
    434    static const int CM_LOCK_MAPPING[CPRMAN_NUM_PLL] = {
    435        [CPRMAN_PLLA] = R_CM_LOCK_FLOCKA_SHIFT,
    436        [CPRMAN_PLLC] = R_CM_LOCK_FLOCKC_SHIFT,
    437        [CPRMAN_PLLD] = R_CM_LOCK_FLOCKD_SHIFT,
    438        [CPRMAN_PLLH] = R_CM_LOCK_FLOCKH_SHIFT,
    439        [CPRMAN_PLLB] = R_CM_LOCK_FLOCKB_SHIFT,
    440    };
    441
    442    uint32_t r = 0;
    443    size_t i;
    444
    445    for (i = 0; i < CPRMAN_NUM_PLL; i++) {
    446        r |= pll_is_locked(&s->plls[i]) << CM_LOCK_MAPPING[i];
    447    }
    448
    449    return r;
    450}
    451
    452static uint64_t cprman_read(void *opaque, hwaddr offset,
    453                            unsigned size)
    454{
    455    BCM2835CprmanState *s = CPRMAN(opaque);
    456    uint64_t r = 0;
    457    size_t idx = offset / sizeof(uint32_t);
    458
    459    switch (idx) {
    460    case R_CM_LOCK:
    461        r = get_cm_lock(s);
    462        break;
    463
    464    default:
    465        r = s->regs[idx];
    466    }
    467
    468    trace_bcm2835_cprman_read(offset, r);
    469    return r;
    470}
    471
    472static inline void update_pll_and_channels_from_cm(BCM2835CprmanState *s,
    473                                                   size_t idx)
    474{
    475    size_t i;
    476
    477    for (i = 0; i < CPRMAN_NUM_PLL; i++) {
    478        if (PLL_INIT_INFO[i].cm_offset == idx) {
    479            pll_update_all_channels(s, &s->plls[i]);
    480            return;
    481        }
    482    }
    483}
    484
    485static inline void update_channel_from_a2w(BCM2835CprmanState *s, size_t idx)
    486{
    487    size_t i;
    488
    489    for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
    490        if (PLL_CHANNEL_INIT_INFO[i].a2w_ctrl_offset == idx) {
    491            pll_channel_update(&s->channels[i]);
    492            return;
    493        }
    494    }
    495}
    496
    497static inline void update_mux_from_cm(BCM2835CprmanState *s, size_t idx)
    498{
    499    size_t i;
    500
    501    for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
    502        if ((CLOCK_MUX_INIT_INFO[i].cm_offset == idx) ||
    503            (CLOCK_MUX_INIT_INFO[i].cm_offset + 4 == idx)) {
    504            /* matches CM_CTL or CM_DIV mux register */
    505            clock_mux_update(&s->clock_muxes[i]);
    506            return;
    507        }
    508    }
    509}
    510
    511#define CASE_PLL_A2W_REGS(pll_) \
    512    case R_A2W_ ## pll_ ## _CTRL: \
    513    case R_A2W_ ## pll_ ## _ANA0: \
    514    case R_A2W_ ## pll_ ## _ANA1: \
    515    case R_A2W_ ## pll_ ## _ANA2: \
    516    case R_A2W_ ## pll_ ## _ANA3: \
    517    case R_A2W_ ## pll_ ## _FRAC
    518
    519static void cprman_write(void *opaque, hwaddr offset,
    520                         uint64_t value, unsigned size)
    521{
    522    BCM2835CprmanState *s = CPRMAN(opaque);
    523    size_t idx = offset / sizeof(uint32_t);
    524
    525    if (FIELD_EX32(value, CPRMAN, PASSWORD) != CPRMAN_PASSWORD) {
    526        trace_bcm2835_cprman_write_invalid_magic(offset, value);
    527        return;
    528    }
    529
    530    value &= ~R_CPRMAN_PASSWORD_MASK;
    531
    532    trace_bcm2835_cprman_write(offset, value);
    533    s->regs[idx] = value;
    534
    535    switch (idx) {
    536    case R_CM_PLLA ... R_CM_PLLH:
    537    case R_CM_PLLB:
    538        /*
    539         * A given CM_PLLx register is shared by both the PLL and the channels
    540         * of this PLL.
    541         */
    542        update_pll_and_channels_from_cm(s, idx);
    543        break;
    544
    545    CASE_PLL_A2W_REGS(PLLA) :
    546        pll_update(&s->plls[CPRMAN_PLLA]);
    547        break;
    548
    549    CASE_PLL_A2W_REGS(PLLC) :
    550        pll_update(&s->plls[CPRMAN_PLLC]);
    551        break;
    552
    553    CASE_PLL_A2W_REGS(PLLD) :
    554        pll_update(&s->plls[CPRMAN_PLLD]);
    555        break;
    556
    557    CASE_PLL_A2W_REGS(PLLH) :
    558        pll_update(&s->plls[CPRMAN_PLLH]);
    559        break;
    560
    561    CASE_PLL_A2W_REGS(PLLB) :
    562        pll_update(&s->plls[CPRMAN_PLLB]);
    563        break;
    564
    565    case R_A2W_PLLA_DSI0:
    566    case R_A2W_PLLA_CORE:
    567    case R_A2W_PLLA_PER:
    568    case R_A2W_PLLA_CCP2:
    569    case R_A2W_PLLC_CORE2:
    570    case R_A2W_PLLC_CORE1:
    571    case R_A2W_PLLC_PER:
    572    case R_A2W_PLLC_CORE0:
    573    case R_A2W_PLLD_DSI0:
    574    case R_A2W_PLLD_CORE:
    575    case R_A2W_PLLD_PER:
    576    case R_A2W_PLLD_DSI1:
    577    case R_A2W_PLLH_AUX:
    578    case R_A2W_PLLH_RCAL:
    579    case R_A2W_PLLH_PIX:
    580    case R_A2W_PLLB_ARM:
    581        update_channel_from_a2w(s, idx);
    582        break;
    583
    584    case R_CM_GNRICCTL ... R_CM_SMIDIV:
    585    case R_CM_TCNTCNT ... R_CM_VECDIV:
    586    case R_CM_PULSECTL ... R_CM_PULSEDIV:
    587    case R_CM_SDCCTL ... R_CM_ARMCTL:
    588    case R_CM_AVEOCTL ... R_CM_EMMCDIV:
    589    case R_CM_EMMC2CTL ... R_CM_EMMC2DIV:
    590        update_mux_from_cm(s, idx);
    591        break;
    592
    593    case R_CM_DSI0HSCK:
    594        dsi0hsck_mux_update(&s->dsi0hsck_mux);
    595        break;
    596    }
    597}
    598
    599#undef CASE_PLL_A2W_REGS
    600
    601static const MemoryRegionOps cprman_ops = {
    602    .read = cprman_read,
    603    .write = cprman_write,
    604    .endianness = DEVICE_LITTLE_ENDIAN,
    605    .valid = {
    606        /*
    607         * Although this hasn't been checked against real hardware, nor the
    608         * information can be found in a datasheet, it seems reasonable because
    609         * of the "PASSWORD" magic value found in every registers.
    610         */
    611        .min_access_size        = 4,
    612        .max_access_size        = 4,
    613        .unaligned              = false,
    614    },
    615    .impl = {
    616        .max_access_size = 4,
    617    },
    618};
    619
    620static void cprman_reset(DeviceState *dev)
    621{
    622    BCM2835CprmanState *s = CPRMAN(dev);
    623    size_t i;
    624
    625    memset(s->regs, 0, sizeof(s->regs));
    626
    627    for (i = 0; i < CPRMAN_NUM_PLL; i++) {
    628        device_cold_reset(DEVICE(&s->plls[i]));
    629    }
    630
    631    for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
    632        device_cold_reset(DEVICE(&s->channels[i]));
    633    }
    634
    635    device_cold_reset(DEVICE(&s->dsi0hsck_mux));
    636
    637    for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
    638        device_cold_reset(DEVICE(&s->clock_muxes[i]));
    639    }
    640
    641    clock_update_hz(s->xosc, s->xosc_freq);
    642}
    643
    644static void cprman_init(Object *obj)
    645{
    646    BCM2835CprmanState *s = CPRMAN(obj);
    647    size_t i;
    648
    649    for (i = 0; i < CPRMAN_NUM_PLL; i++) {
    650        object_initialize_child(obj, PLL_INIT_INFO[i].name,
    651                                &s->plls[i], TYPE_CPRMAN_PLL);
    652        set_pll_init_info(s, &s->plls[i], i);
    653    }
    654
    655    for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
    656        object_initialize_child(obj, PLL_CHANNEL_INIT_INFO[i].name,
    657                                &s->channels[i],
    658                                TYPE_CPRMAN_PLL_CHANNEL);
    659        set_pll_channel_init_info(s, &s->channels[i], i);
    660    }
    661
    662    object_initialize_child(obj, "dsi0hsck-mux",
    663                            &s->dsi0hsck_mux, TYPE_CPRMAN_DSI0HSCK_MUX);
    664    s->dsi0hsck_mux.reg_cm = &s->regs[R_CM_DSI0HSCK];
    665
    666    for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
    667        char *alias;
    668
    669        object_initialize_child(obj, CLOCK_MUX_INIT_INFO[i].name,
    670                                &s->clock_muxes[i],
    671                                TYPE_CPRMAN_CLOCK_MUX);
    672        set_clock_mux_init_info(s, &s->clock_muxes[i], i);
    673
    674        /* Expose muxes output as CPRMAN outputs */
    675        alias = g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO[i].name);
    676        qdev_alias_clock(DEVICE(&s->clock_muxes[i]), "out", DEVICE(obj), alias);
    677        g_free(alias);
    678    }
    679
    680    s->xosc = clock_new(obj, "xosc");
    681    s->gnd = clock_new(obj, "gnd");
    682
    683    clock_set(s->gnd, 0);
    684
    685    memory_region_init_io(&s->iomem, obj, &cprman_ops,
    686                          s, "bcm2835-cprman", 0x2000);
    687    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
    688}
    689
    690static void connect_mux_sources(BCM2835CprmanState *s,
    691                                CprmanClockMuxState *mux,
    692                                const CprmanPllChannel *clk_mapping)
    693{
    694    size_t i;
    695    Clock *td0 = s->clock_muxes[CPRMAN_CLOCK_TD0].out;
    696    Clock *td1 = s->clock_muxes[CPRMAN_CLOCK_TD1].out;
    697
    698    /* For sources from 0 to 3. Source 4 to 9 are mux specific */
    699    Clock * const CLK_SRC_MAPPING[] = {
    700        [CPRMAN_CLOCK_SRC_GND] = s->gnd,
    701        [CPRMAN_CLOCK_SRC_XOSC] = s->xosc,
    702        [CPRMAN_CLOCK_SRC_TD0] = td0,
    703        [CPRMAN_CLOCK_SRC_TD1] = td1,
    704    };
    705
    706    for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) {
    707        CprmanPllChannel mapping = clk_mapping[i];
    708        Clock *src;
    709
    710        if (mapping == CPRMAN_CLOCK_SRC_FORCE_GROUND) {
    711            src = s->gnd;
    712        } else if (mapping == CPRMAN_CLOCK_SRC_DSI0HSCK) {
    713            src = s->dsi0hsck_mux.out;
    714        } else if (i < CPRMAN_CLOCK_SRC_PLLA) {
    715            src = CLK_SRC_MAPPING[i];
    716        } else {
    717            src = s->channels[mapping].out;
    718        }
    719
    720        clock_set_source(mux->srcs[i], src);
    721    }
    722}
    723
    724static void cprman_realize(DeviceState *dev, Error **errp)
    725{
    726    BCM2835CprmanState *s = CPRMAN(dev);
    727    size_t i;
    728
    729    for (i = 0; i < CPRMAN_NUM_PLL; i++) {
    730        CprmanPllState *pll = &s->plls[i];
    731
    732        clock_set_source(pll->xosc_in, s->xosc);
    733
    734        if (!qdev_realize(DEVICE(pll), NULL, errp)) {
    735            return;
    736        }
    737    }
    738
    739    for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
    740        CprmanPllChannelState *channel = &s->channels[i];
    741        CprmanPll parent = PLL_CHANNEL_INIT_INFO[i].parent;
    742        Clock *parent_clk = s->plls[parent].out;
    743
    744        clock_set_source(channel->pll_in, parent_clk);
    745
    746        if (!qdev_realize(DEVICE(channel), NULL, errp)) {
    747            return;
    748        }
    749    }
    750
    751    clock_set_source(s->dsi0hsck_mux.plla_in,
    752                     s->channels[CPRMAN_PLLA_CHANNEL_DSI0].out);
    753    clock_set_source(s->dsi0hsck_mux.plld_in,
    754                     s->channels[CPRMAN_PLLD_CHANNEL_DSI0].out);
    755
    756    if (!qdev_realize(DEVICE(&s->dsi0hsck_mux), NULL, errp)) {
    757        return;
    758    }
    759
    760    for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
    761        CprmanClockMuxState *clock_mux = &s->clock_muxes[i];
    762
    763        connect_mux_sources(s, clock_mux, CLOCK_MUX_INIT_INFO[i].src_mapping);
    764
    765        if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) {
    766            return;
    767        }
    768    }
    769}
    770
    771static const VMStateDescription cprman_vmstate = {
    772    .name = TYPE_BCM2835_CPRMAN,
    773    .version_id = 1,
    774    .minimum_version_id = 1,
    775    .fields = (VMStateField[]) {
    776        VMSTATE_UINT32_ARRAY(regs, BCM2835CprmanState, CPRMAN_NUM_REGS),
    777        VMSTATE_END_OF_LIST()
    778    }
    779};
    780
    781static Property cprman_properties[] = {
    782    DEFINE_PROP_UINT32("xosc-freq-hz", BCM2835CprmanState, xosc_freq, 19200000),
    783    DEFINE_PROP_END_OF_LIST()
    784};
    785
    786static void cprman_class_init(ObjectClass *klass, void *data)
    787{
    788    DeviceClass *dc = DEVICE_CLASS(klass);
    789
    790    dc->realize = cprman_realize;
    791    dc->reset = cprman_reset;
    792    dc->vmsd = &cprman_vmstate;
    793    device_class_set_props(dc, cprman_properties);
    794}
    795
    796static const TypeInfo cprman_info = {
    797    .name = TYPE_BCM2835_CPRMAN,
    798    .parent = TYPE_SYS_BUS_DEVICE,
    799    .instance_size = sizeof(BCM2835CprmanState),
    800    .class_init = cprman_class_init,
    801    .instance_init = cprman_init,
    802};
    803
    804static void cprman_register_types(void)
    805{
    806    type_register_static(&cprman_info);
    807    type_register_static(&cprman_pll_info);
    808    type_register_static(&cprman_pll_channel_info);
    809    type_register_static(&cprman_clock_mux_info);
    810    type_register_static(&cprman_dsi0hsck_mux_info);
    811}
    812
    813type_init(cprman_register_types);