qemu/include/hw/misc/bcm2835_cprman.h

211 lines
4.4 KiB
C
Raw Normal View History

/*
* BCM2835 CPRMAN clock manager
*
* Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef HW_MISC_BCM2835_CPRMAN_H
#define HW_MISC_BCM2835_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,
hw/misc/bcm2835_cprman: add a clock mux skeleton implementation The clock multiplexers are the last clock stage in the CPRMAN. Each mux outputs one clock signal that goes out of the CPRMAN to the SoC peripherals. Each mux has at most 10 sources. The sources 0 to 3 are common to all muxes. They are: 0. ground (no clock signal) 1. the main oscillator (xosc) 2. "test debug 0" clock 3. "test debug 1" clock Test debug 0 and 1 are actual clock muxes that can be used as sources to other muxes (for debug purpose). Sources 4 to 9 are mux specific and can be unpopulated (grounded). Those sources are fed by the PLL channels outputs. One corner case exists for DSI0E and DSI0P muxes. They have their source number 4 connected to an intermediate multiplexer that can select between PLLA-DSI0 and PLLD-DSI0 channel. This multiplexer is called DSI0HSCK and is not a clock mux as such. It is really a simple mux from the hardware point of view (see https://elinux.org/The_Undocumented_Pi). This mux is not implemented in this commit. Note that there is some muxes for which sources are unknown (because of a lack of documentation). For those cases all the sources are connected to ground in this implementation. Each clock mux output is exported by the CPRMAN at the qdev level, adding the suffix '-out' to the mux name to form the output clock name. (E.g. the 'uart' mux sees its output exported as 'uart-out' at the CPRMAN level.) Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Luc Michel <luc@lmichel.fr> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2020-10-10 16:57:54 +03:00
/* 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;
hw/misc/bcm2835_cprman: add a clock mux skeleton implementation The clock multiplexers are the last clock stage in the CPRMAN. Each mux outputs one clock signal that goes out of the CPRMAN to the SoC peripherals. Each mux has at most 10 sources. The sources 0 to 3 are common to all muxes. They are: 0. ground (no clock signal) 1. the main oscillator (xosc) 2. "test debug 0" clock 3. "test debug 1" clock Test debug 0 and 1 are actual clock muxes that can be used as sources to other muxes (for debug purpose). Sources 4 to 9 are mux specific and can be unpopulated (grounded). Those sources are fed by the PLL channels outputs. One corner case exists for DSI0E and DSI0P muxes. They have their source number 4 connected to an intermediate multiplexer that can select between PLLA-DSI0 and PLLD-DSI0 channel. This multiplexer is called DSI0HSCK and is not a clock mux as such. It is really a simple mux from the hardware point of view (see https://elinux.org/The_Undocumented_Pi). This mux is not implemented in this commit. Note that there is some muxes for which sources are unknown (because of a lack of documentation). For those cases all the sources are connected to ground in this implementation. Each clock mux output is exported by the CPRMAN at the qdev level, adding the suffix '-out' to the mux name to form the output clock name. (E.g. the 'uart' mux sees its output exported as 'uart-out' at the CPRMAN level.) Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Luc Michel <luc@lmichel.fr> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2020-10-10 16:57:54 +03:00
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;
hw/misc/bcm2835_cprman: add a clock mux skeleton implementation The clock multiplexers are the last clock stage in the CPRMAN. Each mux outputs one clock signal that goes out of the CPRMAN to the SoC peripherals. Each mux has at most 10 sources. The sources 0 to 3 are common to all muxes. They are: 0. ground (no clock signal) 1. the main oscillator (xosc) 2. "test debug 0" clock 3. "test debug 1" clock Test debug 0 and 1 are actual clock muxes that can be used as sources to other muxes (for debug purpose). Sources 4 to 9 are mux specific and can be unpopulated (grounded). Those sources are fed by the PLL channels outputs. One corner case exists for DSI0E and DSI0P muxes. They have their source number 4 connected to an intermediate multiplexer that can select between PLLA-DSI0 and PLLD-DSI0 channel. This multiplexer is called DSI0HSCK and is not a clock mux as such. It is really a simple mux from the hardware point of view (see https://elinux.org/The_Undocumented_Pi). This mux is not implemented in this commit. Note that there is some muxes for which sources are unknown (because of a lack of documentation). For those cases all the sources are connected to ground in this implementation. Each clock mux output is exported by the CPRMAN at the qdev level, adding the suffix '-out' to the mux name to form the output clock name. (E.g. the 'uart' mux sees its output exported as 'uart-out' at the CPRMAN level.) Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Luc Michel <luc@lmichel.fr> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2020-10-10 16:57:54 +03:00
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];
hw/misc/bcm2835_cprman: add a clock mux skeleton implementation The clock multiplexers are the last clock stage in the CPRMAN. Each mux outputs one clock signal that goes out of the CPRMAN to the SoC peripherals. Each mux has at most 10 sources. The sources 0 to 3 are common to all muxes. They are: 0. ground (no clock signal) 1. the main oscillator (xosc) 2. "test debug 0" clock 3. "test debug 1" clock Test debug 0 and 1 are actual clock muxes that can be used as sources to other muxes (for debug purpose). Sources 4 to 9 are mux specific and can be unpopulated (grounded). Those sources are fed by the PLL channels outputs. One corner case exists for DSI0E and DSI0P muxes. They have their source number 4 connected to an intermediate multiplexer that can select between PLLA-DSI0 and PLLD-DSI0 channel. This multiplexer is called DSI0HSCK and is not a clock mux as such. It is really a simple mux from the hardware point of view (see https://elinux.org/The_Undocumented_Pi). This mux is not implemented in this commit. Note that there is some muxes for which sources are unknown (because of a lack of documentation). For those cases all the sources are connected to ground in this implementation. Each clock mux output is exported by the CPRMAN at the qdev level, adding the suffix '-out' to the mux name to form the output clock name. (E.g. the 'uart' mux sees its output exported as 'uart-out' at the CPRMAN level.) Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Luc Michel <luc@lmichel.fr> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2020-10-10 16:57:54 +03:00
CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX];
CprmanDsi0HsckMuxState dsi0hsck_mux;
uint32_t regs[CPRMAN_NUM_REGS];
uint32_t xosc_freq;
Clock *xosc;
hw/misc/bcm2835_cprman: add a clock mux skeleton implementation The clock multiplexers are the last clock stage in the CPRMAN. Each mux outputs one clock signal that goes out of the CPRMAN to the SoC peripherals. Each mux has at most 10 sources. The sources 0 to 3 are common to all muxes. They are: 0. ground (no clock signal) 1. the main oscillator (xosc) 2. "test debug 0" clock 3. "test debug 1" clock Test debug 0 and 1 are actual clock muxes that can be used as sources to other muxes (for debug purpose). Sources 4 to 9 are mux specific and can be unpopulated (grounded). Those sources are fed by the PLL channels outputs. One corner case exists for DSI0E and DSI0P muxes. They have their source number 4 connected to an intermediate multiplexer that can select between PLLA-DSI0 and PLLD-DSI0 channel. This multiplexer is called DSI0HSCK and is not a clock mux as such. It is really a simple mux from the hardware point of view (see https://elinux.org/The_Undocumented_Pi). This mux is not implemented in this commit. Note that there is some muxes for which sources are unknown (because of a lack of documentation). For those cases all the sources are connected to ground in this implementation. Each clock mux output is exported by the CPRMAN at the qdev level, adding the suffix '-out' to the mux name to form the output clock name. (E.g. the 'uart' mux sees its output exported as 'uart-out' at the CPRMAN level.) Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Luc Michel <luc@lmichel.fr> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2020-10-10 16:57:54 +03:00
Clock *gnd;
};
#endif