/* * BCM2835 CPRMAN clock manager * * Copyright (c) 2020 Luc Michel * * SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef HW_MISC_CPRMAN_H #define HW_MISC_CPRMAN_H #include "hw/sysbus.h" #include "hw/qdev-clock.h" #define TYPE_BCM2835_CPRMAN "bcm2835-cprman" typedef struct BCM2835CprmanState BCM2835CprmanState; DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN, TYPE_BCM2835_CPRMAN) #define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t)) typedef enum CprmanPll { CPRMAN_PLLA = 0, CPRMAN_PLLC, CPRMAN_PLLD, CPRMAN_PLLH, CPRMAN_PLLB, CPRMAN_NUM_PLL } CprmanPll; typedef enum CprmanPllChannel { CPRMAN_PLLA_CHANNEL_DSI0 = 0, CPRMAN_PLLA_CHANNEL_CORE, CPRMAN_PLLA_CHANNEL_PER, CPRMAN_PLLA_CHANNEL_CCP2, CPRMAN_PLLC_CHANNEL_CORE2, CPRMAN_PLLC_CHANNEL_CORE1, CPRMAN_PLLC_CHANNEL_PER, CPRMAN_PLLC_CHANNEL_CORE0, CPRMAN_PLLD_CHANNEL_DSI0, CPRMAN_PLLD_CHANNEL_CORE, CPRMAN_PLLD_CHANNEL_PER, CPRMAN_PLLD_CHANNEL_DSI1, CPRMAN_PLLH_CHANNEL_AUX, CPRMAN_PLLH_CHANNEL_RCAL, CPRMAN_PLLH_CHANNEL_PIX, CPRMAN_PLLB_CHANNEL_ARM, CPRMAN_NUM_PLL_CHANNEL, /* Special values used when connecting clock sources to clocks */ CPRMAN_CLOCK_SRC_NORMAL = -1, CPRMAN_CLOCK_SRC_FORCE_GROUND = -2, CPRMAN_CLOCK_SRC_DSI0HSCK = -3, } CprmanPllChannel; typedef enum CprmanClockMux { CPRMAN_CLOCK_GNRIC, CPRMAN_CLOCK_VPU, CPRMAN_CLOCK_SYS, CPRMAN_CLOCK_PERIA, CPRMAN_CLOCK_PERII, CPRMAN_CLOCK_H264, CPRMAN_CLOCK_ISP, CPRMAN_CLOCK_V3D, CPRMAN_CLOCK_CAM0, CPRMAN_CLOCK_CAM1, CPRMAN_CLOCK_CCP2, CPRMAN_CLOCK_DSI0E, CPRMAN_CLOCK_DSI0P, CPRMAN_CLOCK_DPI, CPRMAN_CLOCK_GP0, CPRMAN_CLOCK_GP1, CPRMAN_CLOCK_GP2, CPRMAN_CLOCK_HSM, CPRMAN_CLOCK_OTP, CPRMAN_CLOCK_PCM, CPRMAN_CLOCK_PWM, CPRMAN_CLOCK_SLIM, CPRMAN_CLOCK_SMI, CPRMAN_CLOCK_TEC, CPRMAN_CLOCK_TD0, CPRMAN_CLOCK_TD1, CPRMAN_CLOCK_TSENS, CPRMAN_CLOCK_TIMER, CPRMAN_CLOCK_UART, CPRMAN_CLOCK_VEC, CPRMAN_CLOCK_PULSE, CPRMAN_CLOCK_SDC, CPRMAN_CLOCK_ARM, CPRMAN_CLOCK_AVEO, CPRMAN_CLOCK_EMMC, CPRMAN_CLOCK_EMMC2, CPRMAN_NUM_CLOCK_MUX } CprmanClockMux; typedef enum CprmanClockMuxSource { CPRMAN_CLOCK_SRC_GND = 0, CPRMAN_CLOCK_SRC_XOSC, CPRMAN_CLOCK_SRC_TD0, CPRMAN_CLOCK_SRC_TD1, CPRMAN_CLOCK_SRC_PLLA, CPRMAN_CLOCK_SRC_PLLC, CPRMAN_CLOCK_SRC_PLLD, CPRMAN_CLOCK_SRC_PLLH, CPRMAN_CLOCK_SRC_PLLC_CORE1, CPRMAN_CLOCK_SRC_PLLC_CORE2, CPRMAN_NUM_CLOCK_MUX_SRC } CprmanClockMuxSource; typedef struct CprmanPllState { /*< private >*/ DeviceState parent_obj; /*< public >*/ CprmanPll id; uint32_t *reg_cm; uint32_t *reg_a2w_ctrl; uint32_t *reg_a2w_ana; /* ANA[0] .. ANA[3] */ uint32_t prediv_mask; /* prediv bit in ana[1] */ uint32_t *reg_a2w_frac; Clock *xosc_in; Clock *out; } CprmanPllState; typedef struct CprmanPllChannelState { /*< private >*/ DeviceState parent_obj; /*< public >*/ CprmanPllChannel id; CprmanPll parent; uint32_t *reg_cm; uint32_t hold_mask; uint32_t load_mask; uint32_t *reg_a2w_ctrl; int fixed_divider; Clock *pll_in; Clock *out; } CprmanPllChannelState; typedef struct CprmanClockMuxState { /*< private >*/ DeviceState parent_obj; /*< public >*/ CprmanClockMux id; uint32_t *reg_ctl; uint32_t *reg_div; int int_bits; int frac_bits; Clock *srcs[CPRMAN_NUM_CLOCK_MUX_SRC]; Clock *out; /* * Used by clock srcs update callback to retrieve both the clock and the * source number. */ struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC]; } CprmanClockMuxState; typedef struct CprmanDsi0HsckMuxState { /*< private >*/ DeviceState parent_obj; /*< public >*/ CprmanClockMux id; uint32_t *reg_cm; Clock *plla_in; Clock *plld_in; Clock *out; } CprmanDsi0HsckMuxState; struct BCM2835CprmanState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; CprmanPllState plls[CPRMAN_NUM_PLL]; CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL]; CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX]; CprmanDsi0HsckMuxState dsi0hsck_mux; uint32_t regs[CPRMAN_NUM_REGS]; uint32_t xosc_freq; Clock *xosc; Clock *gnd; }; #endif