master
h 195 lines 5.54 KB
Raw
1 /*
2 * Nuvoton NPCM7xx/8xx 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 #ifndef NPCM_CLK_H
17 #define NPCM_CLK_H
18
19 #include "system/memory.h"
20 #include "hw/core/clock.h"
21 #include "hw/core/sysbus.h"
22
23 #define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
24 #define NPCM8XX_CLK_NR_REGS (0xc4 / sizeof(uint32_t))
25 /*
26 * Number of maximum registers in NPCM device state structure. Don't change
27 * this without incrementing the version_id in the vmstate.
28 */
29 #define NPCM_CLK_MAX_NR_REGS NPCM8XX_CLK_NR_REGS
30
31 #define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
32
33 /* Maximum amount of clock inputs in a SEL module. */
34 #define NPCM7XX_CLK_SEL_MAX_INPUT 5
35
36 /* PLLs in CLK module. */
37 typedef enum NPCM7xxClockPLL {
38 NPCM7XX_CLOCK_PLL0,
39 NPCM7XX_CLOCK_PLL1,
40 NPCM7XX_CLOCK_PLL2,
41 NPCM7XX_CLOCK_PLLG,
42 NPCM7XX_CLOCK_NR_PLLS,
43 } NPCM7xxClockPLL;
44
45 /* SEL/MUX in CLK module. */
46 typedef enum NPCM7xxClockSEL {
47 NPCM7XX_CLOCK_PIXCKSEL,
48 NPCM7XX_CLOCK_MCCKSEL,
49 NPCM7XX_CLOCK_CPUCKSEL,
50 NPCM7XX_CLOCK_CLKOUTSEL,
51 NPCM7XX_CLOCK_UARTCKSEL,
52 NPCM7XX_CLOCK_TIMCKSEL,
53 NPCM7XX_CLOCK_SDCKSEL,
54 NPCM7XX_CLOCK_GFXMSEL,
55 NPCM7XX_CLOCK_SUCKSEL,
56 NPCM7XX_CLOCK_NR_SELS,
57 } NPCM7xxClockSEL;
58
59 /* Dividers in CLK module. */
60 typedef enum NPCM7xxClockDivider {
61 NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
62 NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
63 NPCM7XX_CLOCK_MC_DIVIDER,
64 NPCM7XX_CLOCK_AXI_DIVIDER,
65 NPCM7XX_CLOCK_AHB_DIVIDER,
66 NPCM7XX_CLOCK_AHB3_DIVIDER,
67 NPCM7XX_CLOCK_SPI0_DIVIDER,
68 NPCM7XX_CLOCK_SPIX_DIVIDER,
69 NPCM7XX_CLOCK_APB1_DIVIDER,
70 NPCM7XX_CLOCK_APB2_DIVIDER,
71 NPCM7XX_CLOCK_APB3_DIVIDER,
72 NPCM7XX_CLOCK_APB4_DIVIDER,
73 NPCM7XX_CLOCK_APB5_DIVIDER,
74 NPCM7XX_CLOCK_CLKOUT_DIVIDER,
75 NPCM7XX_CLOCK_UART_DIVIDER,
76 NPCM7XX_CLOCK_TIMER_DIVIDER,
77 NPCM7XX_CLOCK_ADC_DIVIDER,
78 NPCM7XX_CLOCK_MMC_DIVIDER,
79 NPCM7XX_CLOCK_SDHC_DIVIDER,
80 NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
81 NPCM7XX_CLOCK_UTMI_DIVIDER,
82 NPCM7XX_CLOCK_NR_DIVIDERS,
83 } NPCM7xxClockConverter;
84
85 typedef struct NPCMCLKState NPCMCLKState;
86
87 /**
88 * struct NPCM7xxClockPLLState - A PLL module in CLK module.
89 * @name: The name of the module.
90 * @clk: The CLK module that owns this module.
91 * @clock_in: The input clock of this module.
92 * @clock_out: The output clock of this module.
93 * @reg: The control registers for this PLL module.
94 */
95 typedef struct NPCM7xxClockPLLState {
96 DeviceState parent;
97
98 const char *name;
99 NPCMCLKState *clk;
100 Clock *clock_in;
101 Clock *clock_out;
102
103 int reg;
104 } NPCM7xxClockPLLState;
105
106 /**
107 * struct NPCM7xxClockSELState - A SEL module in CLK module.
108 * @name: The name of the module.
109 * @clk: The CLK module that owns this module.
110 * @input_size: The size of inputs of this module.
111 * @clock_in: The input clocks of this module.
112 * @clock_out: The output clocks of this module.
113 * @offset: The offset of this module in the control register.
114 * @len: The length of this module in the control register.
115 */
116 typedef struct NPCM7xxClockSELState {
117 DeviceState parent;
118
119 const char *name;
120 NPCMCLKState *clk;
121 uint8_t input_size;
122 Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
123 Clock *clock_out;
124
125 int offset;
126 int len;
127 } NPCM7xxClockSELState;
128
129 /**
130 * struct NPCM7xxClockDividerState - A Divider module in CLK module.
131 * @name: The name of the module.
132 * @clk: The CLK module that owns this module.
133 * @clock_in: The input clock of this module.
134 * @clock_out: The output clock of this module.
135 * @divide: The function the divider uses to divide the input.
136 * @reg: The index of the control register that contains the divisor.
137 * @offset: The offset of the divisor in the control register.
138 * @len: The length of the divisor in the control register.
139 * @divisor: The divisor for a constant divisor
140 */
141 typedef struct NPCM7xxClockDividerState {
142 DeviceState parent;
143
144 const char *name;
145 NPCMCLKState *clk;
146 Clock *clock_in;
147 Clock *clock_out;
148
149 uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
150 union {
151 struct {
152 int reg;
153 int offset;
154 int len;
155 };
156 int divisor;
157 };
158 } NPCM7xxClockDividerState;
159
160 struct NPCMCLKState {
161 SysBusDevice parent;
162
163 MemoryRegion iomem;
164
165 /* Clock converters */
166 /*
167 * TODO: Implement unique clock converters for NPCM8xx.
168 * NPCM8xx adds a few more clock outputs.
169 */
170 NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
171 NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
172 NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
173
174 uint32_t regs[NPCM_CLK_MAX_NR_REGS];
175
176 /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
177 int64_t ref_ns;
178
179 /* The incoming reference clock. */
180 Clock *clkref;
181 };
182
183 typedef struct NPCMCLKClass {
184 SysBusDeviceClass parent;
185
186 size_t nr_regs;
187 const uint32_t *cold_reset_values;
188 } NPCMCLKClass;
189
190 #define TYPE_NPCM_CLK "npcm-clk"
191 OBJECT_DECLARE_TYPE(NPCMCLKState, NPCMCLKClass, NPCM_CLK)
192 #define TYPE_NPCM7XX_CLK "npcm7xx-clk"
193 #define TYPE_NPCM8XX_CLK "npcm8xx-clk"
194
195 #endif /* NPCM_CLK_H */