Lines Matching +full:data +full:- +full:channel

6  * SPDX-License-Identifier: GPL-2.0-or-later
11 * - the PLLs
12 * - the PLL channels
13 * - the clock muxes
16 * channels. Those channel are then connected to the clock muxes. Each mux has
23 * At each level (PLL, channel and mux), the clock can be altered through
27 * This can be sum-up as follows (this is an example and not the actual BCM2835
30 * /-->[PLL]-|->[PLL channel]--... [mux]--> to peripherals
31 * | |->[PLL channel] muxes takes [mux]
32 * | \->[PLL channel] inputs from [mux]
34 * [xosc]---|-->[PLL]-|->[PLL channel] and other srcs [mux]
35 * | \->[PLL channel] ...-->[mux]
37 * \-->[PLL]--->[PLL channel] [mux]
43 * with "-out" (e.g. "uart-out", "h264-out", ...).
49 #include "hw/qdev-properties.h"
59 const PLLResetInfo *info = &PLL_RESET_INFO[s->id]; in pll_reset()
61 *s->reg_cm = info->cm; in pll_reset()
62 *s->reg_a2w_ctrl = info->a2w_ctrl; in pll_reset()
63 memcpy(s->reg_a2w_ana, info->a2w_ana, sizeof(info->a2w_ana)); in pll_reset()
64 *s->reg_a2w_frac = info->a2w_frac; in pll_reset()
69 return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN) in pll_is_locked()
70 && !FIELD_EX32(*pll->reg_cm, CM_PLLx, ANARST); in pll_is_locked()
78 clock_update(pll->out, 0); in pll_update()
82 pdiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PDIV); in pll_update()
85 clock_update(pll->out, 0); in pll_update()
89 ndiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, NDIV); in pll_update()
90 fdiv = FIELD_EX32(*pll->reg_a2w_frac, A2W_PLLx_FRAC, FRAC); in pll_update()
92 if (pll->reg_a2w_ana[1] & pll->prediv_mask) { in pll_update()
102 freq = clock_get_hz(pll->xosc_in) * in pll_update()
107 clock_update_hz(pll->out, freq); in pll_update()
119 s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, in pll_init()
121 s->out = qdev_init_clock_out(DEVICE(s), "out"); in pll_init()
134 static void pll_class_init(ObjectClass *klass, const void *data) in pll_class_init() argument
139 dc->vmsd = &pll_vmstate; in pll_class_init()
141 dc->user_creatable = false; in pll_class_init()
153 /* PLL channel */
158 const PLLChannelResetInfo *info = &PLL_CHANNEL_RESET_INFO[s->id]; in pll_channel_reset()
160 *s->reg_a2w_ctrl = info->a2w_ctrl; in pll_channel_reset()
163 static bool pll_channel_is_enabled(CprmanPllChannelState *channel) in pll_channel_is_enabled() argument
167 * not set it when enabling the channel, but does clear it when disabling in pll_channel_is_enabled()
170 return !FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DISABLE) in pll_channel_is_enabled()
171 && !(*channel->reg_cm & channel->hold_mask); in pll_channel_is_enabled()
174 static void pll_channel_update(CprmanPllChannelState *channel) in pll_channel_update() argument
178 if (!pll_channel_is_enabled(channel)) { in pll_channel_update()
179 clock_update(channel->out, 0); in pll_channel_update()
183 div = FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DIV); in pll_channel_update()
194 freq = clock_get_hz(channel->pll_in) / (div * channel->fixed_divider); in pll_channel_update()
196 clock_update_hz(channel->out, freq); in pll_channel_update()
208 CprmanPllChannelState *channel = &s->channels[i]; in pll_update_all_channels() local
209 if (channel->parent == pll->id) { in pll_update_all_channels()
210 pll_channel_update(channel); in pll_update_all_channels()
224 s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in", in pll_channel_init()
227 s->out = qdev_init_clock_out(DEVICE(s), "out"); in pll_channel_init()
240 static void pll_channel_class_init(ObjectClass *klass, const void *data) in pll_channel_class_init() argument
245 dc->vmsd = &pll_channel_vmstate; in pll_channel_class_init()
247 dc->user_creatable = false; in pll_channel_class_init()
263 return FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, ENABLE); in clock_mux_is_enabled()
269 uint32_t div, src = FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, SRC); in clock_mux_update()
272 *mux->reg_ctl = FIELD_DP32(*mux->reg_ctl, CM_CLOCKx_CTL, BUSY, enabled); in clock_mux_update()
275 clock_update(mux->out, 0); in clock_mux_update()
279 freq = clock_get_hz(mux->srcs[src]); in clock_mux_update()
281 if (mux->int_bits == 0 && mux->frac_bits == 0) { in clock_mux_update()
282 clock_update_hz(mux->out, freq); in clock_mux_update()
292 * ------------------------------ in clock_mux_update()
294 * ------------------------------ in clock_mux_update()
295 * <-----> <------> in clock_mux_update()
298 div = extract32(*mux->reg_div, in clock_mux_update()
299 R_CM_CLOCKx_DIV_FRAC_LENGTH - mux->frac_bits, in clock_mux_update()
300 mux->int_bits + mux->frac_bits); in clock_mux_update()
303 clock_update(mux->out, 0); in clock_mux_update()
307 freq = muldiv64(freq, 1 << mux->frac_bits, div); in clock_mux_update()
309 clock_update_hz(mux->out, freq); in clock_mux_update()
316 CprmanClockMuxSource src = backref - s->backref; in clock_mux_src_update()
318 if (FIELD_EX32(*s->reg_ctl, CM_CLOCKx_CTL, SRC) != src) { in clock_mux_src_update()
328 const ClockMuxResetInfo *info = &CLOCK_MUX_RESET_INFO[clock->id]; in clock_mux_reset()
330 *clock->reg_ctl = info->cm_ctl; in clock_mux_reset()
331 *clock->reg_div = info->cm_div; in clock_mux_reset()
341 s->backref[i] = s; in clock_mux_init()
342 s->srcs[i] = qdev_init_clock_in(DEVICE(s), name, in clock_mux_init()
344 &s->backref[i], in clock_mux_init()
349 s->out = qdev_init_clock_out(DEVICE(s), "out"); in clock_mux_init()
363 static void clock_mux_class_init(ObjectClass *klass, const void *data) in clock_mux_class_init() argument
368 dc->vmsd = &clock_mux_vmstate; in clock_mux_class_init()
370 dc->user_creatable = false; in clock_mux_class_init()
386 bool src_is_plld = FIELD_EX32(*s->reg_cm, CM_DSI0HSCK, SELPLLD); in dsi0hsck_mux_update()
387 Clock *src = src_is_plld ? s->plld_in : s->plla_in; in dsi0hsck_mux_update()
389 clock_update(s->out, clock_get(src)); in dsi0hsck_mux_update()
402 s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, in dsi0hsck_mux_init()
404 s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, in dsi0hsck_mux_init()
406 s->out = qdev_init_clock_out(DEVICE(s), "out"); in dsi0hsck_mux_init()
420 static void dsi0hsck_mux_class_init(ObjectClass *klass, const void *data) in dsi0hsck_mux_class_init() argument
424 dc->vmsd = &dsi0hsck_mux_vmstate; in dsi0hsck_mux_class_init()
426 dc->user_creatable = false; in dsi0hsck_mux_class_init()
454 r |= pll_is_locked(&s->plls[i]) << CM_LOCK_MAPPING[i]; in get_cm_lock()
473 r = s->regs[idx]; in cprman_read()
487 pll_update_all_channels(s, &s->plls[i]); in update_pll_and_channels_from_cm()
499 pll_channel_update(&s->channels[i]); in update_channel_from_a2w()
513 clock_mux_update(&s->clock_muxes[i]); in update_mux_from_cm()
541 s->regs[idx] = value; in cprman_write()
554 pll_update(&s->plls[CPRMAN_PLLA]); in cprman_write()
558 pll_update(&s->plls[CPRMAN_PLLC]); in cprman_write()
562 pll_update(&s->plls[CPRMAN_PLLD]); in cprman_write()
566 pll_update(&s->plls[CPRMAN_PLLH]); in cprman_write()
570 pll_update(&s->plls[CPRMAN_PLLB]); in cprman_write()
602 dsi0hsck_mux_update(&s->dsi0hsck_mux); in cprman_write()
633 memset(s->regs, 0, sizeof(s->regs)); in cprman_reset()
636 device_cold_reset(DEVICE(&s->plls[i])); in cprman_reset()
640 device_cold_reset(DEVICE(&s->channels[i])); in cprman_reset()
643 device_cold_reset(DEVICE(&s->dsi0hsck_mux)); in cprman_reset()
646 device_cold_reset(DEVICE(&s->clock_muxes[i])); in cprman_reset()
649 clock_update_hz(s->xosc, s->xosc_freq); in cprman_reset()
659 &s->plls[i], TYPE_CPRMAN_PLL); in cprman_init()
660 set_pll_init_info(s, &s->plls[i], i); in cprman_init()
665 &s->channels[i], in cprman_init()
667 set_pll_channel_init_info(s, &s->channels[i], i); in cprman_init()
670 object_initialize_child(obj, "dsi0hsck-mux", in cprman_init()
671 &s->dsi0hsck_mux, TYPE_CPRMAN_DSI0HSCK_MUX); in cprman_init()
672 s->dsi0hsck_mux.reg_cm = &s->regs[R_CM_DSI0HSCK]; in cprman_init()
678 &s->clock_muxes[i], in cprman_init()
680 set_clock_mux_init_info(s, &s->clock_muxes[i], i); in cprman_init()
683 alias = g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO[i].name); in cprman_init()
684 qdev_alias_clock(DEVICE(&s->clock_muxes[i]), "out", DEVICE(obj), alias); in cprman_init()
688 s->xosc = clock_new(obj, "xosc"); in cprman_init()
689 s->gnd = clock_new(obj, "gnd"); in cprman_init()
691 clock_set(s->gnd, 0); in cprman_init()
693 memory_region_init_io(&s->iomem, obj, &cprman_ops, in cprman_init()
694 s, "bcm2835-cprman", 0x2000); in cprman_init()
695 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); in cprman_init()
703 Clock *td0 = s->clock_muxes[CPRMAN_CLOCK_TD0].out; in connect_mux_sources()
704 Clock *td1 = s->clock_muxes[CPRMAN_CLOCK_TD1].out; in connect_mux_sources()
708 [CPRMAN_CLOCK_SRC_GND] = s->gnd, in connect_mux_sources()
709 [CPRMAN_CLOCK_SRC_XOSC] = s->xosc, in connect_mux_sources()
719 src = s->gnd; in connect_mux_sources()
721 src = s->dsi0hsck_mux.out; in connect_mux_sources()
725 src = s->channels[mapping].out; in connect_mux_sources()
728 clock_set_source(mux->srcs[i], src); in connect_mux_sources()
738 CprmanPllState *pll = &s->plls[i]; in cprman_realize()
740 clock_set_source(pll->xosc_in, s->xosc); in cprman_realize()
748 CprmanPllChannelState *channel = &s->channels[i]; in cprman_realize() local
750 Clock *parent_clk = s->plls[parent].out; in cprman_realize()
752 clock_set_source(channel->pll_in, parent_clk); in cprman_realize()
754 if (!qdev_realize(DEVICE(channel), NULL, errp)) { in cprman_realize()
759 clock_set_source(s->dsi0hsck_mux.plla_in, in cprman_realize()
760 s->channels[CPRMAN_PLLA_CHANNEL_DSI0].out); in cprman_realize()
761 clock_set_source(s->dsi0hsck_mux.plld_in, in cprman_realize()
762 s->channels[CPRMAN_PLLD_CHANNEL_DSI0].out); in cprman_realize()
764 if (!qdev_realize(DEVICE(&s->dsi0hsck_mux), NULL, errp)) { in cprman_realize()
769 CprmanClockMuxState *clock_mux = &s->clock_muxes[i]; in cprman_realize()
790 DEFINE_PROP_UINT32("xosc-freq-hz", BCM2835CprmanState, xosc_freq, 19200000),
793 static void cprman_class_init(ObjectClass *klass, const void *data) in cprman_class_init() argument
797 dc->realize = cprman_realize; in cprman_class_init()
799 dc->vmsd = &cprman_vmstate; in cprman_class_init()