xref: /qemu/include/hw/misc/bcm2835_cprman_internals.h (revision 6d2b874cf1a6f595df805835325e9124c26f3dbf)
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
177