hw/misc/bcm2835_cprman: implement PLLs behaviour
[qemu.git] / include / hw / misc / bcm2835_cprman_internals.h
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 #ifndef HW_MISC_CPRMAN_INTERNALS_H
10 #define HW_MISC_CPRMAN_INTERNALS_H
11
12 #include "hw/registerfields.h"
13 #include "hw/misc/bcm2835_cprman.h"
14
15 #define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
16
17 DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
18 TYPE_CPRMAN_PLL)
19
20 /* Register map */
21
22 /* PLLs */
23 REG32(CM_PLLA, 0x104)
24 FIELD(CM_PLLA, LOADDSI0, 0, 1)
25 FIELD(CM_PLLA, HOLDDSI0, 1, 1)
26 FIELD(CM_PLLA, LOADCCP2, 2, 1)
27 FIELD(CM_PLLA, HOLDCCP2, 3, 1)
28 FIELD(CM_PLLA, LOADCORE, 4, 1)
29 FIELD(CM_PLLA, HOLDCORE, 5, 1)
30 FIELD(CM_PLLA, LOADPER, 6, 1)
31 FIELD(CM_PLLA, HOLDPER, 7, 1)
32 FIELD(CM_PLLx, ANARST, 8, 1)
33 REG32(CM_PLLC, 0x108)
34 FIELD(CM_PLLC, LOADCORE0, 0, 1)
35 FIELD(CM_PLLC, HOLDCORE0, 1, 1)
36 FIELD(CM_PLLC, LOADCORE1, 2, 1)
37 FIELD(CM_PLLC, HOLDCORE1, 3, 1)
38 FIELD(CM_PLLC, LOADCORE2, 4, 1)
39 FIELD(CM_PLLC, HOLDCORE2, 5, 1)
40 FIELD(CM_PLLC, LOADPER, 6, 1)
41 FIELD(CM_PLLC, HOLDPER, 7, 1)
42 REG32(CM_PLLD, 0x10c)
43 FIELD(CM_PLLD, LOADDSI0, 0, 1)
44 FIELD(CM_PLLD, HOLDDSI0, 1, 1)
45 FIELD(CM_PLLD, LOADDSI1, 2, 1)
46 FIELD(CM_PLLD, HOLDDSI1, 3, 1)
47 FIELD(CM_PLLD, LOADCORE, 4, 1)
48 FIELD(CM_PLLD, HOLDCORE, 5, 1)
49 FIELD(CM_PLLD, LOADPER, 6, 1)
50 FIELD(CM_PLLD, HOLDPER, 7, 1)
51 REG32(CM_PLLH, 0x110)
52 FIELD(CM_PLLH, LOADPIX, 0, 1)
53 FIELD(CM_PLLH, LOADAUX, 1, 1)
54 FIELD(CM_PLLH, LOADRCAL, 2, 1)
55 REG32(CM_PLLB, 0x170)
56 FIELD(CM_PLLB, LOADARM, 0, 1)
57 FIELD(CM_PLLB, HOLDARM, 1, 1)
58
59 REG32(A2W_PLLA_CTRL, 0x1100)
60 FIELD(A2W_PLLx_CTRL, NDIV, 0, 10)
61 FIELD(A2W_PLLx_CTRL, PDIV, 12, 3)
62 FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1)
63 FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1)
64 REG32(A2W_PLLC_CTRL, 0x1120)
65 REG32(A2W_PLLD_CTRL, 0x1140)
66 REG32(A2W_PLLH_CTRL, 0x1160)
67 REG32(A2W_PLLB_CTRL, 0x11e0)
68
69 REG32(A2W_PLLA_ANA0, 0x1010)
70 REG32(A2W_PLLA_ANA1, 0x1014)
71 FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1)
72 REG32(A2W_PLLA_ANA2, 0x1018)
73 REG32(A2W_PLLA_ANA3, 0x101c)
74
75 REG32(A2W_PLLC_ANA0, 0x1030)
76 REG32(A2W_PLLC_ANA1, 0x1034)
77 REG32(A2W_PLLC_ANA2, 0x1038)
78 REG32(A2W_PLLC_ANA3, 0x103c)
79
80 REG32(A2W_PLLD_ANA0, 0x1050)
81 REG32(A2W_PLLD_ANA1, 0x1054)
82 REG32(A2W_PLLD_ANA2, 0x1058)
83 REG32(A2W_PLLD_ANA3, 0x105c)
84
85 REG32(A2W_PLLH_ANA0, 0x1070)
86 REG32(A2W_PLLH_ANA1, 0x1074)
87 FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1)
88 REG32(A2W_PLLH_ANA2, 0x1078)
89 REG32(A2W_PLLH_ANA3, 0x107c)
90
91 REG32(A2W_PLLB_ANA0, 0x10f0)
92 REG32(A2W_PLLB_ANA1, 0x10f4)
93 REG32(A2W_PLLB_ANA2, 0x10f8)
94 REG32(A2W_PLLB_ANA3, 0x10fc)
95
96 REG32(A2W_PLLA_FRAC, 0x1200)
97 FIELD(A2W_PLLx_FRAC, FRAC, 0, 20)
98 REG32(A2W_PLLC_FRAC, 0x1220)
99 REG32(A2W_PLLD_FRAC, 0x1240)
100 REG32(A2W_PLLH_FRAC, 0x1260)
101 REG32(A2W_PLLB_FRAC, 0x12e0)
102
103 /* misc registers */
104 REG32(CM_LOCK, 0x114)
105 FIELD(CM_LOCK, FLOCKH, 12, 1)
106 FIELD(CM_LOCK, FLOCKD, 11, 1)
107 FIELD(CM_LOCK, FLOCKC, 10, 1)
108 FIELD(CM_LOCK, FLOCKB, 9, 1)
109 FIELD(CM_LOCK, FLOCKA, 8, 1)
110
111 /*
112 * This field is common to all registers. Each register write value must match
113 * the CPRMAN_PASSWORD magic value in its 8 MSB.
114 */
115 FIELD(CPRMAN, PASSWORD, 24, 8)
116 #define CPRMAN_PASSWORD 0x5a
117
118 /* PLL init info */
119 typedef struct PLLInitInfo {
120 const char *name;
121 size_t cm_offset;
122 size_t a2w_ctrl_offset;
123 size_t a2w_ana_offset;
124 uint32_t prediv_mask; /* Prediv bit in ana[1] */
125 size_t a2w_frac_offset;
126 } PLLInitInfo;
127
128 #define FILL_PLL_INIT_INFO(pll_) \
129 .cm_offset = R_CM_ ## pll_, \
130 .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \
131 .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0, \
132 .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC
133
134 static const PLLInitInfo PLL_INIT_INFO[] = {
135 [CPRMAN_PLLA] = {
136 .name = "plla",
137 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
138 FILL_PLL_INIT_INFO(PLLA),
139 },
140 [CPRMAN_PLLC] = {
141 .name = "pllc",
142 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
143 FILL_PLL_INIT_INFO(PLLC),
144 },
145 [CPRMAN_PLLD] = {
146 .name = "plld",
147 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
148 FILL_PLL_INIT_INFO(PLLD),
149 },
150 [CPRMAN_PLLH] = {
151 .name = "pllh",
152 .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK,
153 FILL_PLL_INIT_INFO(PLLH),
154 },
155 [CPRMAN_PLLB] = {
156 .name = "pllb",
157 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
158 FILL_PLL_INIT_INFO(PLLB),
159 },
160 };
161
162 #undef FILL_PLL_CHANNEL_INIT_INFO
163
164 static inline void set_pll_init_info(BCM2835CprmanState *s,
165 CprmanPllState *pll,
166 CprmanPll id)
167 {
168 pll->id = id;
169 pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset];
170 pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset];
171 pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset];
172 pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask;
173 pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset];
174 }
175
176 #endif