qemu/include/hw/misc/npcm_clk.h
Hao Wu 4e67d50dea hw/misc: Support NPCM8XX CLK Module Registers
NPCM8XX adds a few new registers and have a different set of reset
values to the CLK modules. This patch supports them.

This patch doesn't support the new clock values generated by these
registers. Currently no modules use these new clock values so they
are not necessary at this point.
Implementation of these clocks might be required when implementing
these modules.

Reviewed-by: Titus Rwantare <titusr@google.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Message-id: 20250219184609.1839281-14-wuhaotsh@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2025-02-20 15:22:22 +00:00

195 lines
5.5 KiB
C

/*
* Nuvoton NPCM7xx/8xx 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 NPCM_CLK_H
#define NPCM_CLK_H
#include "exec/memory.h"
#include "hw/clock.h"
#include "hw/sysbus.h"
#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
#define NPCM8XX_CLK_NR_REGS (0xc4 / sizeof(uint32_t))
/*
* Number of maximum registers in NPCM device state structure. Don't change
* this without incrementing the version_id in the vmstate.
*/
#define NPCM_CLK_MAX_NR_REGS NPCM8XX_CLK_NR_REGS
#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 NPCMCLKState NPCMCLKState;
/**
* 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;
NPCMCLKState *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;
NPCMCLKState *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;
NPCMCLKState *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 NPCMCLKState {
SysBusDevice parent;
MemoryRegion iomem;
/* Clock converters */
/*
* TODO: Implement unique clock converters for NPCM8xx.
* NPCM8xx adds a few more clock outputs.
*/
NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
uint32_t regs[NPCM_CLK_MAX_NR_REGS];
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
int64_t ref_ns;
/* The incoming reference clock. */
Clock *clkref;
};
typedef struct NPCMCLKClass {
SysBusDeviceClass parent;
size_t nr_regs;
const uint32_t *cold_reset_values;
} NPCMCLKClass;
#define TYPE_NPCM_CLK "npcm-clk"
OBJECT_DECLARE_TYPE(NPCMCLKState, NPCMCLKClass, NPCM_CLK)
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
#define TYPE_NPCM8XX_CLK "npcm8xx-clk"
#endif /* NPCM_CLK_H */