xref: /qemu/include/hw/misc/npcm_clk.h (revision cc944932ecef3b7a56ae62d89dd92fb9e56c5cc8)
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/clock.h"
21 #include "hw/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 */
196