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