1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
/*
* Nuvoton NPCM7xx Clock Control Registers.
*
* Copyright 2020 Google LLC
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef NPCM7XX_CLK_H
#define NPCM7XX_CLK_H
#include "exec/memory.h"
#include "hw/clock.h"
#include "hw/sysbus.h"
/*
* Number of registers in our device state structure. Don't change this without
* incrementing the version_id in the vmstate.
*/
#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
/* Maximum amount of clock inputs in a SEL module. */
#define NPCM7XX_CLK_SEL_MAX_INPUT 5
/* PLLs in CLK module. */
typedef enum NPCM7xxClockPLL {
NPCM7XX_CLOCK_PLL0,
NPCM7XX_CLOCK_PLL1,
NPCM7XX_CLOCK_PLL2,
NPCM7XX_CLOCK_PLLG,
NPCM7XX_CLOCK_NR_PLLS,
} NPCM7xxClockPLL;
/* SEL/MUX in CLK module. */
typedef enum NPCM7xxClockSEL {
NPCM7XX_CLOCK_PIXCKSEL,
NPCM7XX_CLOCK_MCCKSEL,
NPCM7XX_CLOCK_CPUCKSEL,
NPCM7XX_CLOCK_CLKOUTSEL,
NPCM7XX_CLOCK_UARTCKSEL,
NPCM7XX_CLOCK_TIMCKSEL,
NPCM7XX_CLOCK_SDCKSEL,
NPCM7XX_CLOCK_GFXMSEL,
NPCM7XX_CLOCK_SUCKSEL,
NPCM7XX_CLOCK_NR_SELS,
} NPCM7xxClockSEL;
/* Dividers in CLK module. */
typedef enum NPCM7xxClockDivider {
NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
NPCM7XX_CLOCK_MC_DIVIDER,
NPCM7XX_CLOCK_AXI_DIVIDER,
NPCM7XX_CLOCK_AHB_DIVIDER,
NPCM7XX_CLOCK_AHB3_DIVIDER,
NPCM7XX_CLOCK_SPI0_DIVIDER,
NPCM7XX_CLOCK_SPIX_DIVIDER,
NPCM7XX_CLOCK_APB1_DIVIDER,
NPCM7XX_CLOCK_APB2_DIVIDER,
NPCM7XX_CLOCK_APB3_DIVIDER,
NPCM7XX_CLOCK_APB4_DIVIDER,
NPCM7XX_CLOCK_APB5_DIVIDER,
NPCM7XX_CLOCK_CLKOUT_DIVIDER,
NPCM7XX_CLOCK_UART_DIVIDER,
NPCM7XX_CLOCK_TIMER_DIVIDER,
NPCM7XX_CLOCK_ADC_DIVIDER,
NPCM7XX_CLOCK_MMC_DIVIDER,
NPCM7XX_CLOCK_SDHC_DIVIDER,
NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
NPCM7XX_CLOCK_UTMI_DIVIDER,
NPCM7XX_CLOCK_NR_DIVIDERS,
} NPCM7xxClockConverter;
typedef struct NPCM7xxCLKState NPCM7xxCLKState;
/**
* struct NPCM7xxClockPLLState - A PLL module in CLK module.
* @name: The name of the module.
* @clk: The CLK module that owns this module.
* @clock_in: The input clock of this module.
* @clock_out: The output clock of this module.
* @reg: The control registers for this PLL module.
*/
typedef struct NPCM7xxClockPLLState {
DeviceState parent;
const char *name;
NPCM7xxCLKState *clk;
Clock *clock_in;
Clock *clock_out;
int reg;
} NPCM7xxClockPLLState;
/**
* struct NPCM7xxClockSELState - A SEL module in CLK module.
* @name: The name of the module.
* @clk: The CLK module that owns this module.
* @input_size: The size of inputs of this module.
* @clock_in: The input clocks of this module.
* @clock_out: The output clocks of this module.
* @offset: The offset of this module in the control register.
* @len: The length of this module in the control register.
*/
typedef struct NPCM7xxClockSELState {
DeviceState parent;
const char *name;
NPCM7xxCLKState *clk;
uint8_t input_size;
Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
Clock *clock_out;
int offset;
int len;
} NPCM7xxClockSELState;
/**
* struct NPCM7xxClockDividerState - A Divider module in CLK module.
* @name: The name of the module.
* @clk: The CLK module that owns this module.
* @clock_in: The input clock of this module.
* @clock_out: The output clock of this module.
* @divide: The function the divider uses to divide the input.
* @reg: The index of the control register that contains the divisor.
* @offset: The offset of the divisor in the control register.
* @len: The length of the divisor in the control register.
* @divisor: The divisor for a constant divisor
*/
typedef struct NPCM7xxClockDividerState {
DeviceState parent;
const char *name;
NPCM7xxCLKState *clk;
Clock *clock_in;
Clock *clock_out;
uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
union {
struct {
int reg;
int offset;
int len;
};
int divisor;
};
} NPCM7xxClockDividerState;
struct NPCM7xxCLKState {
SysBusDevice parent;
MemoryRegion iomem;
/* Clock converters */
NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
uint32_t regs[NPCM7XX_CLK_NR_REGS];
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
int64_t ref_ns;
/* The incoming reference clock. */
Clock *clkref;
};
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
#endif /* NPCM7XX_CLK_H */
|