diff --git a/zircon/system/dev/clk/msm8x53-clk/BUILD.gn b/zircon/system/dev/clk/msm8x53-clk/BUILD.gn index e4cf2109a0d72acbf25e7b64bef793c32ca04770..4ba45f88a14a80f719befd629e984f92f9ec24fe 100644 --- a/zircon/system/dev/clk/msm8x53-clk/BUILD.gn +++ b/zircon/system/dev/clk/msm8x53-clk/BUILD.gn @@ -27,3 +27,35 @@ driver("msm8x53-clk") { "$zx/system/ulib/zxcpp", ] } + +test("msm8x53-clk-test") { + testonly = true + output_name = "msm8x53-clk-test" + sources = [ + "msm8x53-clk.cpp", + "msm8x53-clk-test.cpp" + ] + deps = [ + "$zx/system/banjo/ddk.protocol.clock", + "$zx/system/banjo/ddk.protocol.clockimpl", + "$zx/system/banjo/ddk.protocol.gpio", + "$zx/system/banjo/ddk.protocol.i2c", + "$zx/system/banjo/ddk.protocol.platform.bus", + "$zx/system/banjo/ddk.protocol.platform.device", + "$zx/system/dev/lib/mock-mmio-reg", + "$zx/system/dev/lib/mmio", + "$zx/system/dev/lib/msm8x53", + "$zx/system/fidl/fuchsia-hardware-clock:c", + "$zx/system/ulib/ddk", + "$zx/system/ulib/ddktl", + "$zx/system/ulib/driver", + "$zx/system/ulib/fbl", + "$zx/system/ulib/fidl", + "$zx/system/ulib/hwreg", + "$zx/system/ulib/sync", + "$zx/system/ulib/zircon", + "$zx/system/ulib/zx", + "$zx/system/ulib/zxcpp", + "$zx/system/ulib/zxtest", + ] +} diff --git a/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk-regs.h b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk-regs.h index 47a896402049ab02e1c64f0db0959f27f234786c..cda5d373c868ddd2390b399b4fdb39bcd0d19bf5 100644 --- a/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk-regs.h +++ b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk-regs.h @@ -141,4 +141,764 @@ constexpr uint32_t kApssTcuAsyncCbcr = 0x12018; constexpr uint32_t kApcsClockBranchEnaVote = 0x45004; constexpr uint32_t kApcsSmmuClockBranchEnaVote = 0x4500C; -} // namespace msm8x53 \ No newline at end of file +// RCG Command Registers +constexpr uint32_t kCamssTopAhbCmdRcgr = 0x5A000; +constexpr uint32_t kCsi0CmdRcgr = 0x4E020; +constexpr uint32_t kApssAhbCmdRcgr = 0x46000; +constexpr uint32_t kCsi1CmdRcgr = 0x4F020; +constexpr uint32_t kCsi2CmdRcgr = 0x3C020; +constexpr uint32_t kVfe0CmdRcgr = 0x58000; +constexpr uint32_t kGfx3dCmdRcgr = 0x59000; +constexpr uint32_t kVcodec0CmdRcgr = 0x4C000; +constexpr uint32_t kCppCmdRcgr = 0x58018; +constexpr uint32_t kJpeg0CmdRcgr = 0x57000; +constexpr uint32_t kMdpCmdRcgr = 0x4D014; +constexpr uint32_t kPclk0CmdRcgr = 0x4D000; +constexpr uint32_t kPclk1CmdRcgr = 0x4D0B8; +constexpr uint32_t kUsb30MasterCmdRcgr = 0x3F00C; +constexpr uint32_t kVfe1CmdRcgr = 0x58054; +constexpr uint32_t kApc0VoltageDroopDetectorCmdRcgr = 0x78008; +constexpr uint32_t kApc1VoltageDroopDetectorCmdRcgr = 0x79008; +constexpr uint32_t kBlsp1Qup1I2cAppsCmdRcgr = 0x0200C; +constexpr uint32_t kBlsp1Qup1SpiAppsCmdRcgr = 0x02024; +constexpr uint32_t kBlsp1Qup2I2cAppsCmdRcgr = 0x03000; +constexpr uint32_t kBlsp1Qup2SpiAppsCmdRcgr = 0x03014; +constexpr uint32_t kBlsp1Qup3I2cAppsCmdRcgr = 0x04000; +constexpr uint32_t kBlsp1Qup3SpiAppsCmdRcgr = 0x04024; +constexpr uint32_t kBlsp1Qup4I2cAppsCmdRcgr = 0x05000; +constexpr uint32_t kBlsp1Qup4SpiAppsCmdRcgr = 0x05024; +constexpr uint32_t kBlsp1Uart1AppsCmdRcgr = 0x02044; +constexpr uint32_t kBlsp1Uart2AppsCmdRcgr = 0x03034; +constexpr uint32_t kBlsp2Qup1I2cAppsCmdRcgr = 0x0C00C; +constexpr uint32_t kBlsp2Qup1SpiAppsCmdRcgr = 0x0C024; +constexpr uint32_t kBlsp2Qup2I2cAppsCmdRcgr = 0x0D000; +constexpr uint32_t kBlsp2Qup2SpiAppsCmdRcgr = 0x0D014; +constexpr uint32_t kBlsp2Qup3I2cAppsCmdRcgr = 0x0F000; +constexpr uint32_t kBlsp2Qup3SpiAppsCmdRcgr = 0x0F024; +constexpr uint32_t kBlsp2Qup4I2cAppsCmdRcgr = 0x18000; +constexpr uint32_t kBlsp2Qup4SpiAppsCmdRcgr = 0x18024; +constexpr uint32_t kBlsp2Uart1AppsCmdRcgr = 0x0C044; +constexpr uint32_t kBlsp2Uart2AppsCmdRcgr = 0x0D034; +constexpr uint32_t kCciCmdRcgr = 0x51000; +constexpr uint32_t kCsi0pCmdRcgr = 0x58084; +constexpr uint32_t kCsi1pCmdRcgr = 0x58094; +constexpr uint32_t kCsi2pCmdRcgr = 0x580A4; +constexpr uint32_t kCamssGp0CmdRcgr = 0x54000; +constexpr uint32_t kCamssGp1CmdRcgr = 0x55000; +constexpr uint32_t kMclk0CmdRcgr = 0x52000; +constexpr uint32_t kMclk1CmdRcgr = 0x53000; +constexpr uint32_t kMclk2CmdRcgr = 0x5C000; +constexpr uint32_t kMclk3CmdRcgr = 0x5E000; +constexpr uint32_t kCsi0phytimerCmdRcgr = 0x4E000; +constexpr uint32_t kCsi1phytimerCmdRcgr = 0x4F000; +constexpr uint32_t kCsi2phytimerCmdRcgr = 0x4F05C; +constexpr uint32_t kCryptoCmdRcgr = 0x16004; +constexpr uint32_t kGp1CmdRcgr = 0x08004; +constexpr uint32_t kGp2CmdRcgr = 0x09004; +constexpr uint32_t kGp3CmdRcgr = 0x0A004; +constexpr uint32_t kByte0CmdRcgr = 0x4D044; +constexpr uint32_t kByte1CmdRcgr = 0x4D0B0; +constexpr uint32_t kEsc0CmdRcgr = 0x4D05C; +constexpr uint32_t kEsc1CmdRcgr = 0x4D0A8; +constexpr uint32_t kVsyncCmdRcgr = 0x4D02C; +constexpr uint32_t kPdm2CmdRcgr = 0x44010; +constexpr uint32_t kRbcprGfxCmdRcgr = 0x3A00C; +constexpr uint32_t kSdcc1AppsCmdRcgr = 0x42004; +constexpr uint32_t kSdcc1IceCoreCmdRcgr = 0x5D000; +constexpr uint32_t kSdcc2AppsCmdRcgr = 0x43004; +constexpr uint32_t kUsb30MockUtmiCmdRcgr = 0x3F020; +constexpr uint32_t kUsb3AuxCmdRcgr = 0x3F05C; + +// Mux Constants +constexpr uint32_t kXoSrcVal = 0; +constexpr uint32_t kXoASrcVal = 0; +constexpr uint32_t kXoPipeSrcVal = 1; +constexpr uint32_t kGpll0SrcVal = 1; +constexpr uint32_t kGpll0MainSrcVal = 2; +constexpr uint32_t kGpll0MainMockSrcVal = 3; +constexpr uint32_t kGpll0MainDiv2Usb3SrcVal = 2; +constexpr uint32_t kGpll0MainDiv2SrcVal = 4; +constexpr uint32_t kGpll0MainDiv2CciSrcVal = 3; +constexpr uint32_t kGpll0MainDiv2MmSrcVal = 5; +constexpr uint32_t kGpll0MainDiv2AxiSrcVal = 6; +constexpr uint32_t kGpll2SrcVal = 4; +constexpr uint32_t kGpll2OutMainSrcVal = 5; +constexpr uint32_t kGpll2VcodecSrcVal = 3; +constexpr uint32_t kGpll3SrcVal = 2; +constexpr uint32_t kGpll4SrcVal = 2; +constexpr uint32_t kGpll4AuxSrcVal = 2; +constexpr uint32_t kGpll4OutAuxSrcVal = 4; +constexpr uint32_t kGpll6MainSrcVal = 1; +constexpr uint32_t kGpll6SrcVal = 2; +constexpr uint32_t kGpll6MainGfxSrcVal = 3; +constexpr uint32_t kGpll6MainDiv2MockSrcVal = 2; +constexpr uint32_t kGpll6MainDiv2SrcVal = 5; +constexpr uint32_t kGpll6MainDiv2GfxSrcVal = 6; +constexpr uint32_t kGpll6AuxSrcVal = 2; +constexpr uint32_t kGpll6OutAuxSrcVal = 3; +constexpr uint32_t kUsb3PipeSrcVal = 0; +constexpr uint32_t kDsi0PhypllMmSrcVal = 1; +constexpr uint32_t kDsi1PhypllMmSrcVal = 3; +constexpr uint32_t kDsi0PhypllClkMmSrcVal = 3; +constexpr uint32_t kDsi1PhypllClkMmSrcVal = 1; + +} // namespace msm8x53 + +namespace clk { + +typedef struct msm_clk_gate { + uint32_t reg; + uint32_t bit; + uint32_t delay_us; +} msm_clk_gate_t; + +struct msm_clk_branch { + uint32_t reg; +}; + +struct msm_clk_voter { + uint32_t cbcr_reg; + uint32_t vote_reg; + uint32_t bit; +}; + +enum class RcgDividerType { + HalfInteger, + Mnd +}; + +class RcgFrequencyTable { + static constexpr uint32_t kPredivMask = 0x1f; + static constexpr uint32_t kSrcMask = 0x7; + static constexpr uint32_t kSrcShift = 8; + +public: + constexpr RcgFrequencyTable(uint64_t rate, uint32_t m, uint32_t n, uint32_t d2, uint32_t parent) + : rate_(rate), m_(m), n_(n == 0 ? 0 : ~(n - m)), d_(~n), predev_parent_(((d2 - 1) & kPredivMask) | ((parent & kSrcMask) << kSrcShift)) {} + + uint64_t rate() const { return rate_; } + uint32_t m() const { return m_; } + uint32_t n() const { return n_; } + uint32_t d() const { return d_; } + uint32_t predev_parent() const { return predev_parent_; } + +private: + const uint64_t rate_; + const uint32_t m_; + const uint32_t n_; + const uint32_t d_; + const uint32_t predev_parent_; +}; + +class MsmClkRcg { +public: + constexpr MsmClkRcg(uint32_t reg, RcgDividerType type, const RcgFrequencyTable* table, + size_t frequency_table_count, bool unsupported = false) + : cmd_rcgr_reg_(reg), type_(type), frequency_table_(table), + frequency_table_count_(frequency_table_count), unsupported_(unsupported) {} + + static constexpr uint32_t kCmdOffset = 0x0; + uint32_t CmdReg() const { return cmd_rcgr_reg_ + kCmdOffset; } + + static constexpr uint32_t kCfgOffset = 0x4; + uint32_t CfgReg() const { return cmd_rcgr_reg_ + kCfgOffset; } + + static constexpr uint32_t kMOffset = 0x8; + uint32_t MReg() const { return cmd_rcgr_reg_ + kMOffset; } + + static constexpr uint32_t kNOffset = 0xC; + uint32_t NReg() const { return cmd_rcgr_reg_ + kNOffset; } + + static constexpr uint32_t KDOffset = 0x10; + uint32_t DReg() const { return cmd_rcgr_reg_ + KDOffset; } + + RcgDividerType Type() const { return type_; } + const RcgFrequencyTable* Table() const { return frequency_table_; } + size_t TableCount() const { return frequency_table_count_; } + bool Unsupported() const { return unsupported_; } + +private: + const uint32_t cmd_rcgr_reg_; + const RcgDividerType type_; + const RcgFrequencyTable* frequency_table_; + const size_t frequency_table_count_; + const bool unsupported_; +}; + +namespace { + +class RcgClkCmd : public hwreg::RegisterBase<RcgClkCmd, uint32_t> { +public: + DEF_BIT(0, cfg_update); + DEF_BIT(1, root_enable); + DEF_BIT(31, root_status); + + static auto Read(uint32_t offset) { + return hwreg::RegisterAddr<RcgClkCmd>(offset); + } +}; + +constexpr msm_clk_gate_t kMsmClkGates[] = { + [msm8x53::MsmClkIndex(msm8x53::kQUsbRefClk)] = {.reg = 0x41030, .bit = 0, .delay_us = 0}, + [msm8x53::MsmClkIndex(msm8x53::kUsbSSRefClk)] = {.reg = 0x5e07c, .bit = 0, .delay_us = 0}, + [msm8x53::MsmClkIndex(msm8x53::kUsb3PipeClk)] = {.reg = 0x5e040, .bit = 0, .delay_us = 50}, +}; + +constexpr uint32_t kBranchEnable = (0x1u << 0); +constexpr struct msm_clk_branch kMsmClkBranches[] = { + [msm8x53::MsmClkIndex(msm8x53::kApc0DroopDetectorGpll0Clk)] = { + .reg = msm8x53::kApc0VoltageDroopDetectorGpll0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kApc1DroopDetectorGpll0Clk)] = {.reg = msm8x53::kApc1VoltageDroopDetectorGpll0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup1I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup1I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup1SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup1SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup2I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup2I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup2SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup2SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup3I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup3I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup3SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup3SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup4I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup4I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup4SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup4SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Uart1AppsClk)] = {.reg = msm8x53::kBlsp1Uart1AppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Uart2AppsClk)] = {.reg = msm8x53::kBlsp1Uart2AppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup1I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup1I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup1SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup1SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup2I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup2I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup2SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup2SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup3I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup3I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup3SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup3SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup4I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup4I2cAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup4SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup4SpiAppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Uart1AppsClk)] = {.reg = msm8x53::kBlsp2Uart1AppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Uart2AppsClk)] = {.reg = msm8x53::kBlsp2Uart2AppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBimcGpuClk)] = {.reg = msm8x53::kBimcGpuCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCciAhbClk)] = {.reg = msm8x53::kCamssCciAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCciClk)] = {.reg = msm8x53::kCamssCciCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCppAhbClk)] = {.reg = msm8x53::kCamssCppAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCppAxiClk)] = {.reg = msm8x53::kCamssCppAxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCppClk)] = {.reg = msm8x53::kCamssCppCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0AhbClk)] = {.reg = msm8x53::kCamssCsi0AhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0Clk)] = {.reg = msm8x53::kCamssCsi0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0Csiphy3pClk)] = {.reg = msm8x53::kCamssCsi0Csiphy3pCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0phyClk)] = {.reg = msm8x53::kCamssCsi0phyCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0pixClk)] = {.reg = msm8x53::kCamssCsi0pixCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0rdiClk)] = {.reg = msm8x53::kCamssCsi0rdiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1AhbClk)] = {.reg = msm8x53::kCamssCsi1AhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1Clk)] = {.reg = msm8x53::kCamssCsi1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1Csiphy3pClk)] = {.reg = msm8x53::kCamssCsi1Csiphy3pCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1phyClk)] = {.reg = msm8x53::kCamssCsi1phyCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1pixClk)] = {.reg = msm8x53::kCamssCsi1pixCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1rdiClk)] = {.reg = msm8x53::kCamssCsi1rdiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2AhbClk)] = {.reg = msm8x53::kCamssCsi2AhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2Clk)] = {.reg = msm8x53::kCamssCsi2Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2Csiphy3pClk)] = {.reg = msm8x53::kCamssCsi2Csiphy3pCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2phyClk)] = {.reg = msm8x53::kCamssCsi2phyCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2pixClk)] = {.reg = msm8x53::kCamssCsi2pixCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2rdiClk)] = {.reg = msm8x53::kCamssCsi2rdiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsiVfe0Clk)] = {.reg = msm8x53::kCamssCsiVfe0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsiVfe1Clk)] = {.reg = msm8x53::kCamssCsiVfe1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssGp0Clk)] = {.reg = msm8x53::kCamssGp0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssGp1Clk)] = {.reg = msm8x53::kCamssGp1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssIspifAhbClk)] = {.reg = msm8x53::kCamssIspifAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssJpeg0Clk)] = {.reg = msm8x53::kCamssJpeg0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssJpegAhbClk)] = {.reg = msm8x53::kCamssJpegAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssJpegAxiClk)] = {.reg = msm8x53::kCamssJpegAxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssMclk0Clk)] = {.reg = msm8x53::kCamssMclk0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssMclk1Clk)] = {.reg = msm8x53::kCamssMclk1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssMclk2Clk)] = {.reg = msm8x53::kCamssMclk2Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssMclk3Clk)] = {.reg = msm8x53::kCamssMclk3Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssMicroAhbClk)] = {.reg = msm8x53::kCamssMicroAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0phytimerClk)] = {.reg = msm8x53::kCamssCsi0phytimerCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1phytimerClk)] = {.reg = msm8x53::kCamssCsi1phytimerCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2phytimerClk)] = {.reg = msm8x53::kCamssCsi2phytimerCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssAhbClk)] = {.reg = msm8x53::kCamssAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssTopAhbClk)] = {.reg = msm8x53::kCamssTopAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssVfe0Clk)] = {.reg = msm8x53::kCamssVfe0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssVfeAhbClk)] = {.reg = msm8x53::kCamssVfeAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssVfeAxiClk)] = {.reg = msm8x53::kCamssVfeAxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssVfe1AhbClk)] = {.reg = msm8x53::kCamssVfe1AhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssVfe1AxiClk)] = {.reg = msm8x53::kCamssVfe1AxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kCamssVfe1Clk)] = {.reg = msm8x53::kCamssVfe1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kDccClk)] = {.reg = msm8x53::kDccCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kGp1Clk)] = {.reg = msm8x53::kGp1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kGp2Clk)] = {.reg = msm8x53::kGp2Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kGp3Clk)] = {.reg = msm8x53::kGp3Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssAhbClk)] = {.reg = msm8x53::kMdssAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssAxiClk)] = {.reg = msm8x53::kMdssAxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssByte0Clk)] = {.reg = msm8x53::kMdssByte0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssByte1Clk)] = {.reg = msm8x53::kMdssByte1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssEsc0Clk)] = {.reg = msm8x53::kMdssEsc0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssEsc1Clk)] = {.reg = msm8x53::kMdssEsc1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssMdpClk)] = {.reg = msm8x53::kMdssMdpCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssPclk0Clk)] = {.reg = msm8x53::kMdssPclk0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssPclk1Clk)] = {.reg = msm8x53::kMdssPclk1Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMdssVsyncClk)] = {.reg = msm8x53::kMdssVsyncCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMssCfgAhbClk)] = {.reg = msm8x53::kMssCfgAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kMssQ6BimcAxiClk)] = {.reg = msm8x53::kMssQ6BimcAxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kBimcGfxClk)] = {.reg = msm8x53::kBimcGfxCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kOxiliAhbClk)] = {.reg = msm8x53::kOxiliAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kOxiliAonClk)] = {.reg = msm8x53::kOxiliAonCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kOxiliGfx3dClk)] = {.reg = msm8x53::kOxiliGfx3dCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kOxiliTimerClk)] = {.reg = msm8x53::kOxiliTimerCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kPcnocUsb3AxiClk)] = {.reg = msm8x53::kPcnocUsb3AxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kPdm2Clk)] = {.reg = msm8x53::kPdm2Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kPdmAhbClk)] = {.reg = msm8x53::kPdmAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kRbcprGfxClk)] = {.reg = msm8x53::kRbcprGfxCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kSdcc1AhbClk)] = {.reg = msm8x53::kSdcc1AhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kSdcc1AppsClk)] = {.reg = msm8x53::kSdcc1AppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kSdcc1IceCoreClk)] = {.reg = msm8x53::kSdcc1IceCoreCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kSdcc2AhbClk)] = {.reg = msm8x53::kSdcc2AhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kSdcc2AppsClk)] = {.reg = msm8x53::kSdcc2AppsCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kUsb30MasterClk)] = {.reg = msm8x53::kUsb30MasterCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kUsb30MockUtmiClk)] = {.reg = msm8x53::kUsb30MockUtmiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kUsb30SleepClk)] = {.reg = msm8x53::kUsb30SleepCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kUsb3AuxClk)] = {.reg = msm8x53::kUsb3AuxCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kUsbPhyCfgAhbClk)] = {.reg = msm8x53::kUsbPhyCfgAhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kVenus0AhbClk)] = {.reg = msm8x53::kVenus0AhbCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kVenus0AxiClk)] = {.reg = msm8x53::kVenus0AxiCbcr}, + [msm8x53::MsmClkIndex(msm8x53::kVenus0Core0Vcodec0Clk)] = {.reg = msm8x53::kVenus0Core0Vcodec0Cbcr}, + [msm8x53::MsmClkIndex(msm8x53::kVenus0Vcodec0Clk)] = {.reg = msm8x53::kVenus0Vcodec0Cbcr}, +}; + +constexpr RcgFrequencyTable kFtblCamssTopAhbClkSrc[] = { + RcgFrequencyTable(40000000, 0, 0, 20, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(80000000, 0, 0, 20, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi0ClkSrc[] = { + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2SrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2SrcVal), +}; + +constexpr RcgFrequencyTable kFtblApssAhbClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoASrcVal), + RcgFrequencyTable(25000000, 0, 0, 32, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(50000000, 0, 0, 32, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(100000000, 0, 0, 16, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi1ClkSrc[] = { + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2OutMainSrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2OutMainSrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi2ClkSrc[] = { + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2OutMainSrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2OutMainSrcVal), +}; + +constexpr RcgFrequencyTable kFtblVfe0ClkSrc[] = { + RcgFrequencyTable(50000000, 0, 0, 16, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(160000000, 0, 0, 10, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2SrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2SrcVal), +}; + +constexpr RcgFrequencyTable kFtblGfx3dClkSrc[] = {}; + +__UNUSED constexpr RcgFrequencyTable kFtblGfx3dClkSrcSdm450[] = {}; + +__UNUSED constexpr RcgFrequencyTable kFtblGfx3dClkSrcSdm632[] = {}; + +constexpr RcgFrequencyTable kFtblVcodec0ClkSrc[] = { + RcgFrequencyTable(114290000, 0, 0, 7, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(228570000, 0, 0, 7, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2VcodecSrcVal), + RcgFrequencyTable(360000000, 0, 0, 6, msm8x53::kGpll6SrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2VcodecSrcVal), +}; + +__UNUSED constexpr RcgFrequencyTable kFtblVcodec0ClkSrc540MHz[] = { + RcgFrequencyTable(114290000, 0, 0, 7, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(228570000, 0, 0, 7, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2VcodecSrcVal), + RcgFrequencyTable(360000000, 0, 0, 6, msm8x53::kGpll6SrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2VcodecSrcVal), + RcgFrequencyTable(540000000, 0, 0, 4, msm8x53::kGpll6SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCppClkSrc[] = { + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(320000000, 0, 0, 5, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2SrcVal), +}; + +constexpr RcgFrequencyTable kFtblJpeg0ClkSrc[] = { + RcgFrequencyTable(66670000, 0, 0, 12, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2OutMainSrcVal), + RcgFrequencyTable(320000000, 0, 0, 5, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblMdpClkSrc[] = { + RcgFrequencyTable(50000000, 0, 0, 16, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(80000000, 0, 0, 10, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(160000000, 0, 0, 5, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(320000000, 0, 0, 5, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblPclk0ClkSrc[] = {}; + +constexpr RcgFrequencyTable kFtblPclk1ClkSrc[] = {}; + +constexpr RcgFrequencyTable kFtblUsb30MasterClkSrc[] = { + RcgFrequencyTable(80000000, 0, 0, 10, msm8x53::kGpll0MainDiv2Usb3SrcVal), + RcgFrequencyTable(100000000, 0, 0, 16, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblVfe1ClkSrc[] = { + RcgFrequencyTable(50000000, 0, 0, 16, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(160000000, 0, 0, 10, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2SrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(465000000, 0, 0, 4, msm8x53::kGpll2SrcVal), +}; + +constexpr RcgFrequencyTable kFtblApc0DroopDetectorClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(576000000, 0, 0, 4, msm8x53::kGpll4SrcVal), +}; + +constexpr RcgFrequencyTable kFtblApc1DroopDetectorClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(400000000, 0, 0, 4, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(576000000, 0, 0, 4, msm8x53::kGpll4SrcVal), +}; + +constexpr RcgFrequencyTable kFtblBlspI2cAppsClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(25000000, 0, 0, 32, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(50000000, 0, 0, 32, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblBlspSpiAppsClkSrc[] = { + RcgFrequencyTable(960000, 1, 2, 20, msm8x53::kXoSrcVal), + RcgFrequencyTable(4800000, 0, 0, 8, msm8x53::kXoSrcVal), + RcgFrequencyTable(9600000, 0, 0, 4, msm8x53::kXoSrcVal), + RcgFrequencyTable(12500000, 1, 2, 32, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(16000000, 1, 5, 20, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(25000000, 1, 2, 32, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(50000000, 0, 0, 32, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblBlspUartAppsClkSrc[] = { + RcgFrequencyTable(3686400, 144, 15625, 2, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(7372800, 288, 15625, 2, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(14745600, 576, 15625, 2, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(16000000, 1, 5, 10, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(24000000, 3, 100, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(25000000, 1, 2, 32, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(32000000, 1, 25, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(40000000, 1, 20, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(46400000, 29, 500, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(48000000, 3, 50, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(51200000, 8, 125, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(56000000, 7, 100, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(58982400, 1152, 15625, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(60000000, 3, 40, 2, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(64000000, 2, 25, 2, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCciClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(37500000, 3, 32, 2, msm8x53::kGpll0MainDiv2CciSrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi0pClkSrc[] = { + RcgFrequencyTable(66670000, 0, 0, 12, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi1pClkSrc[] = { + RcgFrequencyTable(66670000, 0, 0, 12, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi2pClkSrc[] = { + RcgFrequencyTable(66670000, 0, 0, 12, msm8x53::kGpll0MainDiv2MmSrcVal), + RcgFrequencyTable(133330000, 0, 0, 12, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(310000000, 0, 0, 6, msm8x53::kGpll2SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCamssGp0ClkSrc[] = { + RcgFrequencyTable(50000000, 0, 0, 16, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(100000000, 0, 0, 16, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCamssGp1ClkSrc[] = { + RcgFrequencyTable(50000000, 0, 0, 16, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(100000000, 0, 0, 16, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblMclk0ClkSrc[] = { + RcgFrequencyTable(24000000, 2, 45, 2, msm8x53::kGpll6MainDiv2SrcVal), + RcgFrequencyTable(33330000, 0, 0, 24, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(36610000, 2, 59, 2, msm8x53::kGpll6SrcVal), + RcgFrequencyTable(66667000, 0, 0, 24, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblMclk1ClkSrc[] = { + RcgFrequencyTable(24000000, 2, 45, 2, msm8x53::kGpll6MainDiv2SrcVal), + RcgFrequencyTable(33330000, 0, 0, 24, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(36610000, 2, 59, 2, msm8x53::kGpll6SrcVal), + RcgFrequencyTable(66667000, 0, 0, 24, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblMclk2ClkSrc[] = { + RcgFrequencyTable(24000000, 2, 45, 2, msm8x53::kGpll6MainDiv2SrcVal), + RcgFrequencyTable(33330000, 0, 0, 24, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(36610000, 2, 59, 2, msm8x53::kGpll6SrcVal), + RcgFrequencyTable(66667000, 0, 0, 24, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblMclk3ClkSrc[] = { + RcgFrequencyTable(24000000, 2, 45, 2, msm8x53::kGpll6MainDiv2SrcVal), + RcgFrequencyTable(33330000, 0, 0, 24, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(36610000, 2, 59, 2, msm8x53::kGpll6SrcVal), + RcgFrequencyTable(66667000, 0, 0, 24, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi0phytimerClkSrc[] = { + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi1phytimerClkSrc[] = { + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCsi2phytimerClkSrc[] = { + RcgFrequencyTable(100000000, 0, 0, 8, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(266670000, 0, 0, 6, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblCryptoClkSrc[] = { + RcgFrequencyTable(40000000, 0, 0, 20, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(80000000, 0, 0, 20, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(100000000, 0, 0, 16, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(160000000, 0, 0, 10, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblGp1ClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), +}; + +constexpr RcgFrequencyTable kFtblGp2ClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), +}; + +constexpr RcgFrequencyTable kFtblGp3ClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), +}; + +constexpr RcgFrequencyTable kFtblByte0ClkSrc[] = {}; + +constexpr RcgFrequencyTable kFtblByte1ClkSrc[] = {}; + +constexpr RcgFrequencyTable kFtblEsc0ClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), +}; + +constexpr RcgFrequencyTable kFtblEsc1ClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), +}; + +constexpr RcgFrequencyTable kFtblVsyncClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), +}; + +constexpr RcgFrequencyTable kFtblPdm2ClkSrc[] = { + RcgFrequencyTable(32000000, 0, 0, 25, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(64000000, 0, 0, 25, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblRbcprGfxClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(50000000, 0, 0, 32, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblSdcc1AppsClkSrc[] = { + RcgFrequencyTable(144000, 3, 25, 32, msm8x53::kXoSrcVal), + RcgFrequencyTable(400000, 1, 4, 24, msm8x53::kXoSrcVal), + RcgFrequencyTable(20000000, 1, 4, 10, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(25000000, 0, 0, 32, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(50000000, 0, 0, 32, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(100000000, 0, 0, 16, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(177770000, 0, 0, 9, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(192000000, 0, 0, 12, msm8x53::kGpll4SrcVal), + RcgFrequencyTable(384000000, 0, 0, 6, msm8x53::kGpll4SrcVal), +}; + +constexpr RcgFrequencyTable kFtblSdcc1IceCoreClkSrc[] = { + RcgFrequencyTable(80000000, 0, 0, 10, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(160000000, 0, 0, 10, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(270000000, 0, 0, 8, msm8x53::kGpll6SrcVal), +}; + +constexpr RcgFrequencyTable kFtblSdcc2AppsClkSrc[] = { + RcgFrequencyTable(144000, 3, 25, 32, msm8x53::kXoSrcVal), + RcgFrequencyTable(400000, 1, 4, 24, msm8x53::kXoSrcVal), + RcgFrequencyTable(20000000, 1, 4, 10, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(25000000, 0, 0, 32, msm8x53::kGpll0MainDiv2SrcVal), + RcgFrequencyTable(50000000, 0, 0, 32, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(100000000, 0, 0, 16, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(177770000, 0, 0, 9, msm8x53::kGpll0SrcVal), + RcgFrequencyTable(192000000, 0, 0, 12, msm8x53::kGpll4AuxSrcVal), + RcgFrequencyTable(200000000, 0, 0, 8, msm8x53::kGpll0SrcVal), +}; + +constexpr RcgFrequencyTable kFtblUsb30MockUtmiClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), + RcgFrequencyTable(60000000, 1, 1, 18, msm8x53::kGpll6MainDiv2MockSrcVal), +}; + +constexpr RcgFrequencyTable kFtblUsb3AuxClkSrc[] = { + RcgFrequencyTable(19200000, 0, 0, 2, msm8x53::kXoSrcVal), +}; + +constexpr MsmClkRcg kMsmClkRcgs[] = { + [msm8x53::MsmClkIndex(msm8x53::kCamssTopAhbClkSrc)] = MsmClkRcg(msm8x53::kCamssTopAhbCmdRcgr, RcgDividerType::Mnd, kFtblCamssTopAhbClkSrc, countof(kFtblCamssTopAhbClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi0ClkSrc)] = MsmClkRcg(msm8x53::kCsi0CmdRcgr, RcgDividerType::HalfInteger, kFtblCsi0ClkSrc, countof(kFtblCsi0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kApssAhbClkSrc)] = MsmClkRcg(msm8x53::kApssAhbCmdRcgr, RcgDividerType::HalfInteger, kFtblApssAhbClkSrc, countof(kFtblApssAhbClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi1ClkSrc)] = MsmClkRcg(msm8x53::kCsi1CmdRcgr, RcgDividerType::HalfInteger, kFtblCsi1ClkSrc, countof(kFtblCsi1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi2ClkSrc)] = MsmClkRcg(msm8x53::kCsi2CmdRcgr, RcgDividerType::HalfInteger, kFtblCsi2ClkSrc, countof(kFtblCsi2ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kVfe0ClkSrc)] = MsmClkRcg(msm8x53::kVfe0CmdRcgr, RcgDividerType::HalfInteger, kFtblVfe0ClkSrc, countof(kFtblVfe0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kGfx3dClkSrc)] = MsmClkRcg(msm8x53::kGfx3dCmdRcgr, RcgDividerType::HalfInteger, kFtblGfx3dClkSrc, countof(kFtblGfx3dClkSrc), true), + [msm8x53::MsmClkIndex(msm8x53::kVcodec0ClkSrc)] = MsmClkRcg(msm8x53::kVcodec0CmdRcgr, RcgDividerType::Mnd, kFtblVcodec0ClkSrc, countof(kFtblVcodec0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCppClkSrc)] = MsmClkRcg(msm8x53::kCppCmdRcgr, RcgDividerType::HalfInteger, kFtblCppClkSrc, countof(kFtblCppClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kJpeg0ClkSrc)] = MsmClkRcg(msm8x53::kJpeg0CmdRcgr, RcgDividerType::HalfInteger, kFtblJpeg0ClkSrc, countof(kFtblJpeg0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kMdpClkSrc)] = MsmClkRcg(msm8x53::kMdpCmdRcgr, RcgDividerType::HalfInteger, kFtblMdpClkSrc, countof(kFtblMdpClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kPclk0ClkSrc)] = MsmClkRcg(msm8x53::kPclk0CmdRcgr, RcgDividerType::Mnd, kFtblPclk0ClkSrc, countof(kFtblPclk0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kPclk1ClkSrc)] = MsmClkRcg(msm8x53::kPclk1CmdRcgr, RcgDividerType::Mnd, kFtblPclk1ClkSrc, countof(kFtblPclk1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kUsb30MasterClkSrc)] = MsmClkRcg(msm8x53::kUsb30MasterCmdRcgr, RcgDividerType::Mnd, kFtblUsb30MasterClkSrc, countof(kFtblUsb30MasterClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kVfe1ClkSrc)] = MsmClkRcg(msm8x53::kVfe1CmdRcgr, RcgDividerType::HalfInteger, kFtblVfe1ClkSrc, countof(kFtblVfe1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kApc0DroopDetectorClkSrc)] = MsmClkRcg(msm8x53::kApc0VoltageDroopDetectorCmdRcgr, RcgDividerType::HalfInteger, kFtblApc0DroopDetectorClkSrc, countof(kFtblApc0DroopDetectorClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kApc1DroopDetectorClkSrc)] = MsmClkRcg(msm8x53::kApc1VoltageDroopDetectorCmdRcgr, RcgDividerType::HalfInteger, kFtblApc1DroopDetectorClkSrc, countof(kFtblApc1DroopDetectorClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup1I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup1I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup1SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup1SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup2I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup2I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup2SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup2SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup3I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup3I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup3SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup3SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup4I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup4I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup4SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Qup4SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Uart1AppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Uart1AppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspUartAppsClkSrc, countof(kFtblBlspUartAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp1Uart2AppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp1Uart2AppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspUartAppsClkSrc, countof(kFtblBlspUartAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup1I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup1I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup1SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup1SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup2I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup2I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup2SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup2SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup3I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup3I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup3SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup3SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup4I2cAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup4I2cAppsCmdRcgr, RcgDividerType::HalfInteger, kFtblBlspI2cAppsClkSrc, countof(kFtblBlspI2cAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup4SpiAppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Qup4SpiAppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspSpiAppsClkSrc, countof(kFtblBlspSpiAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Uart1AppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Uart1AppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspUartAppsClkSrc, countof(kFtblBlspUartAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kBlsp2Uart2AppsClkSrc)] = MsmClkRcg(msm8x53::kBlsp2Uart2AppsCmdRcgr, RcgDividerType::Mnd, kFtblBlspUartAppsClkSrc, countof(kFtblBlspUartAppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCciClkSrc)] = MsmClkRcg(msm8x53::kCciCmdRcgr, RcgDividerType::Mnd, kFtblCciClkSrc, countof(kFtblCciClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi0pClkSrc)] = MsmClkRcg(msm8x53::kCsi0pCmdRcgr, RcgDividerType::HalfInteger, kFtblCsi0pClkSrc, countof(kFtblCsi0pClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi1pClkSrc)] = MsmClkRcg(msm8x53::kCsi1pCmdRcgr, RcgDividerType::HalfInteger, kFtblCsi1pClkSrc, countof(kFtblCsi1pClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi2pClkSrc)] = MsmClkRcg(msm8x53::kCsi2pCmdRcgr, RcgDividerType::HalfInteger, kFtblCsi2pClkSrc, countof(kFtblCsi2pClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCamssGp0ClkSrc)] = MsmClkRcg(msm8x53::kCamssGp0CmdRcgr, RcgDividerType::Mnd, kFtblCamssGp0ClkSrc, countof(kFtblCamssGp0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCamssGp1ClkSrc)] = MsmClkRcg(msm8x53::kCamssGp1CmdRcgr, RcgDividerType::Mnd, kFtblCamssGp1ClkSrc, countof(kFtblCamssGp1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kMclk0ClkSrc)] = MsmClkRcg(msm8x53::kMclk0CmdRcgr, RcgDividerType::Mnd, kFtblMclk0ClkSrc, countof(kFtblMclk0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kMclk1ClkSrc)] = MsmClkRcg(msm8x53::kMclk1CmdRcgr, RcgDividerType::Mnd, kFtblMclk1ClkSrc, countof(kFtblMclk1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kMclk2ClkSrc)] = MsmClkRcg(msm8x53::kMclk2CmdRcgr, RcgDividerType::Mnd, kFtblMclk2ClkSrc, countof(kFtblMclk2ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kMclk3ClkSrc)] = MsmClkRcg(msm8x53::kMclk3CmdRcgr, RcgDividerType::Mnd, kFtblMclk3ClkSrc, countof(kFtblMclk3ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi0phytimerClkSrc)] = MsmClkRcg(msm8x53::kCsi0phytimerCmdRcgr, RcgDividerType::HalfInteger, kFtblCsi0phytimerClkSrc, countof(kFtblCsi0phytimerClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi1phytimerClkSrc)] = MsmClkRcg(msm8x53::kCsi1phytimerCmdRcgr, RcgDividerType::HalfInteger, kFtblCsi1phytimerClkSrc, countof(kFtblCsi1phytimerClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCsi2phytimerClkSrc)] = MsmClkRcg(msm8x53::kCsi2phytimerCmdRcgr, RcgDividerType::HalfInteger, kFtblCsi2phytimerClkSrc, countof(kFtblCsi2phytimerClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kCryptoClkSrc)] = MsmClkRcg(msm8x53::kCryptoCmdRcgr, RcgDividerType::HalfInteger, kFtblCryptoClkSrc, countof(kFtblCryptoClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kGp1ClkSrc)] = MsmClkRcg(msm8x53::kGp1CmdRcgr, RcgDividerType::Mnd, kFtblGp1ClkSrc, countof(kFtblGp1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kGp2ClkSrc)] = MsmClkRcg(msm8x53::kGp2CmdRcgr, RcgDividerType::Mnd, kFtblGp2ClkSrc, countof(kFtblGp2ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kGp3ClkSrc)] = MsmClkRcg(msm8x53::kGp3CmdRcgr, RcgDividerType::Mnd, kFtblGp3ClkSrc, countof(kFtblGp3ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kByte0ClkSrc)] = MsmClkRcg(msm8x53::kByte0CmdRcgr, RcgDividerType::HalfInteger, kFtblByte0ClkSrc, countof(kFtblByte0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kByte1ClkSrc)] = MsmClkRcg(msm8x53::kByte1CmdRcgr, RcgDividerType::HalfInteger, kFtblByte1ClkSrc, countof(kFtblByte1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kEsc0ClkSrc)] = MsmClkRcg(msm8x53::kEsc0CmdRcgr, RcgDividerType::HalfInteger, kFtblEsc0ClkSrc, countof(kFtblEsc0ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kEsc1ClkSrc)] = MsmClkRcg(msm8x53::kEsc1CmdRcgr, RcgDividerType::HalfInteger, kFtblEsc1ClkSrc, countof(kFtblEsc1ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kVsyncClkSrc)] = MsmClkRcg(msm8x53::kVsyncCmdRcgr, RcgDividerType::HalfInteger, kFtblVsyncClkSrc, countof(kFtblVsyncClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kPdm2ClkSrc)] = MsmClkRcg(msm8x53::kPdm2CmdRcgr, RcgDividerType::HalfInteger, kFtblPdm2ClkSrc, countof(kFtblPdm2ClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kRbcprGfxClkSrc)] = MsmClkRcg(msm8x53::kRbcprGfxCmdRcgr, RcgDividerType::HalfInteger, kFtblRbcprGfxClkSrc, countof(kFtblRbcprGfxClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kSdcc1AppsClkSrc)] = MsmClkRcg(msm8x53::kSdcc1AppsCmdRcgr, RcgDividerType::Mnd, kFtblSdcc1AppsClkSrc, countof(kFtblSdcc1AppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kSdcc1IceCoreClkSrc)] = MsmClkRcg(msm8x53::kSdcc1IceCoreCmdRcgr, RcgDividerType::Mnd, kFtblSdcc1IceCoreClkSrc, countof(kFtblSdcc1IceCoreClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kSdcc2AppsClkSrc)] = MsmClkRcg(msm8x53::kSdcc2AppsCmdRcgr, RcgDividerType::Mnd, kFtblSdcc2AppsClkSrc, countof(kFtblSdcc2AppsClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kUsb30MockUtmiClkSrc)] = MsmClkRcg(msm8x53::kUsb30MockUtmiCmdRcgr, RcgDividerType::Mnd, kFtblUsb30MockUtmiClkSrc, countof(kFtblUsb30MockUtmiClkSrc)), + [msm8x53::MsmClkIndex(msm8x53::kUsb3AuxClkSrc)] = MsmClkRcg(msm8x53::kUsb3AuxCmdRcgr, RcgDividerType::Mnd, kFtblUsb3AuxClkSrc, countof(kFtblUsb3AuxClkSrc)), +}; + +static_assert(msm8x53::kRcgClkCount == countof(kMsmClkRcgs), + "kRcgClkCount must match count of RCG clocks"); + +constexpr struct msm_clk_voter kMsmClkVoters[] = { + [msm8x53::MsmClkIndex(msm8x53::kApssAhbClk)] = { + .cbcr_reg = msm8x53::kApssAhbCbcr, + .vote_reg = msm8x53::kApcsClockBranchEnaVote, + .bit = (1 << 14)}, + [msm8x53::MsmClkIndex(msm8x53::kApssAxiClk)] = {.cbcr_reg = msm8x53::kApssAxiCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 13)}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp1AhbClk)] = {.cbcr_reg = msm8x53::kBlsp1AhbCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 10)}, + [msm8x53::MsmClkIndex(msm8x53::kBlsp2AhbClk)] = {.cbcr_reg = msm8x53::kBlsp2AhbCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 20)}, + [msm8x53::MsmClkIndex(msm8x53::kBootRomAhbClk)] = {.cbcr_reg = msm8x53::kBootRomAhbCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 7)}, + [msm8x53::MsmClkIndex(msm8x53::kCryptoAhbClk)] = {.cbcr_reg = msm8x53::kCryptoAhbCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 0)}, + [msm8x53::MsmClkIndex(msm8x53::kCryptoAxiClk)] = {.cbcr_reg = msm8x53::kCryptoAxiCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 1)}, + [msm8x53::MsmClkIndex(msm8x53::kCryptoClk)] = {.cbcr_reg = msm8x53::kCryptoCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 2)}, + [msm8x53::MsmClkIndex(msm8x53::kQdssDapClk)] = {.cbcr_reg = msm8x53::kQdssDapCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 11)}, + [msm8x53::MsmClkIndex(msm8x53::kPrngAhbClk)] = {.cbcr_reg = msm8x53::kPrngAhbCbcr, .vote_reg = msm8x53::kApcsClockBranchEnaVote, .bit = (1 << 8)}, + [msm8x53::MsmClkIndex(msm8x53::kApssTcuAsyncClk)] = {.cbcr_reg = msm8x53::kApssTcuAsyncCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 1)}, + [msm8x53::MsmClkIndex(msm8x53::kCppTbuClk)] = {.cbcr_reg = msm8x53::kCppTbuCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 14)}, + [msm8x53::MsmClkIndex(msm8x53::kJpegTbuClk)] = {.cbcr_reg = msm8x53::kJpegTbuCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 10)}, + [msm8x53::MsmClkIndex(msm8x53::kMdpTbuClk)] = {.cbcr_reg = msm8x53::kMdpTbuCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 4)}, + [msm8x53::MsmClkIndex(msm8x53::kSmmuCfgClk)] = {.cbcr_reg = msm8x53::kSmmuCfgCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 12)}, + [msm8x53::MsmClkIndex(msm8x53::kVenusTbuClk)] = {.cbcr_reg = msm8x53::kVenusTbuCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 5)}, + [msm8x53::MsmClkIndex(msm8x53::kVfe1TbuClk)] = {.cbcr_reg = msm8x53::kVfe1TbuCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 17)}, + [msm8x53::MsmClkIndex(msm8x53::kVfeTbuClk)] = {.cbcr_reg = msm8x53::kVfeTbuCbcr, .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, .bit = (1 << 9)}, +}; + +} // namespace + +} // namespace clk \ No newline at end of file diff --git a/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk-test.cpp b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk-test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55c931596d034929267756bb08693e1d1a7e1766 --- /dev/null +++ b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk-test.cpp @@ -0,0 +1,156 @@ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "msm8x53-clk.h" + +#include <soc/msm8x53/msm8x53-clock.h> +#include <mock-mmio-reg/mock-mmio-reg.h> + +#include "msm8x53-clk-regs.h" + + +namespace clk { + +class Msm8x53ClkTest : public Msm8x53Clk { +public: + Msm8x53ClkTest(ddk_mock::MockMmioRegRegion& mmio) + : Msm8x53Clk(nullptr, ddk::MmioBuffer(mmio.GetMmioBuffer())) {} +}; + +// Test MND divider path. +TEST(ClkTest8x53, TestSetRcgMnd) { + auto cc_regs_arr = std::make_unique<ddk_mock::MockMmioReg[]>(msm8x53::kCcSize); + ddk_mock::MockMmioRegRegion cc_regs(cc_regs_arr.get(), sizeof(uint32_t), msm8x53::kCcSize); + Msm8x53ClkTest clk(cc_regs); + + const MsmClkRcg& kTestClock = + kMsmClkRcgs[msm8x53::MsmClkIndex(msm8x53::kBlsp1Uart2AppsClkSrc)]; + const RcgFrequencyTable kTestFrequency = + kTestClock.Table()[0]; + cc_regs[kTestClock.MReg()].ExpectWrite(kTestFrequency.m()); + cc_regs[kTestClock.NReg()].ExpectWrite(kTestFrequency.n()); + cc_regs[kTestClock.DReg()].ExpectWrite(kTestFrequency.d()); + cc_regs[kTestClock.CmdReg()].ExpectWrite(0x1); + + // Invalid clock ID and bad rate. + zx_status_t st = clk.ClockImplRequestRate(0, 0); + EXPECT_NE(st, ZX_OK); + + // Set a good clock and a bad rate. + constexpr uint64_t kBadClkRate = 1; + st = clk.ClockImplRequestRate(msm8x53::kBlsp1Uart2AppsClkSrc, kBadClkRate); + EXPECT_NE(st, ZX_OK); + + // Try setting a clock that exists. + const uint64_t kGoodClkRate = kTestFrequency.rate(); + st = clk.ClockImplRequestRate(msm8x53::kBlsp1Uart2AppsClkSrc, kGoodClkRate); + EXPECT_OK(st); + + cc_regs.VerifyAll(); +} + +// Test Half Integer Divider path. +TEST(ClkTest8x53, TestSetRcgHid) { + auto cc_regs_arr = std::make_unique<ddk_mock::MockMmioReg[]>(msm8x53::kCcSize); + ddk_mock::MockMmioRegRegion cc_regs(cc_regs_arr.get(), sizeof(uint32_t), msm8x53::kCcSize); + Msm8x53ClkTest clk(cc_regs); + + const MsmClkRcg& kTestClock = + kMsmClkRcgs[msm8x53::MsmClkIndex(msm8x53::kCsi0pClkSrc)]; + const RcgFrequencyTable kTestFrequency = + kTestClock.Table()[0]; + cc_regs[msm8x53::kCsi0pCmdRcgr + 0x04].ExpectWrite(kTestFrequency.predev_parent()); + cc_regs[msm8x53::kCsi0pCmdRcgr + 0x00].ExpectWrite(0x1); + + // Set a good clock and a bad rate. + constexpr uint64_t kBadClkRate = 1; + zx_status_t st = clk.ClockImplRequestRate(msm8x53::kCsi0pClkSrc, kBadClkRate); + EXPECT_NE(st, ZX_OK); + + // Try setting a clock that exists. + const uint64_t kGoodClkRate = kTestFrequency.rate(); + st = clk.ClockImplRequestRate(msm8x53::kCsi0pClkSrc, kGoodClkRate); + EXPECT_OK(st); + + cc_regs.VerifyAll(); +} + +TEST(ClkTest8x53, TestRcgEnableDisabe) { + auto cc_regs_arr = std::make_unique<ddk_mock::MockMmioReg[]>(msm8x53::kCcSize); + ddk_mock::MockMmioRegRegion cc_regs(cc_regs_arr.get(), sizeof(uint32_t), msm8x53::kCcSize); + Msm8x53ClkTest clk(cc_regs); + + const uint32_t kTestClkId = msm8x53::kBlsp1Qup3SpiAppsClkSrc; + const MsmClkRcg& kTestClock = + kMsmClkRcgs[msm8x53::MsmClkIndex(kTestClkId)]; + const RcgFrequencyTable kTestFrequency = + kTestClock.Table()[0]; + + // You are prohibited from enabling an RCG before setting the rate. + zx_status_t st = clk.ClockImplEnable(kTestClkId); + EXPECT_NE(st, ZX_OK); + + // Okay, set a frequency and try again. + st = clk.ClockImplRequestRate(kTestClkId, kTestFrequency.rate()); + EXPECT_OK(st); + + // Try enabling the RCG again and make sure it works. + st = clk.ClockImplEnable(kTestClkId); + EXPECT_OK(st); + + cc_regs[kTestClock.CmdReg()].ExpectWrite(((1 << 1))); +} + +TEST(ClkTest8x53, TestGateClkEnableDisable) { + zx_status_t st; + auto cc_regs_arr = std::make_unique<ddk_mock::MockMmioReg[]>(msm8x53::kCcSize); + ddk_mock::MockMmioRegRegion cc_regs(cc_regs_arr.get(), sizeof(uint32_t), msm8x53::kCcSize); + Msm8x53ClkTest clk(cc_regs); + + constexpr uint32_t kTestClkId = msm8x53::kUsb3PipeClk; + + st = clk.ClockImplEnable(kTestClkId); + EXPECT_OK(st); + + st = clk.ClockImplDisable(kTestClkId); + EXPECT_OK(st); +} + +TEST(ClkTest8x53, TestBranchClkEnableDisable) { + zx_status_t st; + auto cc_regs_arr = std::make_unique<ddk_mock::MockMmioReg[]>(msm8x53::kCcSize); + ddk_mock::MockMmioRegRegion cc_regs(cc_regs_arr.get(), sizeof(uint32_t), msm8x53::kCcSize); + Msm8x53ClkTest clk(cc_regs); + + constexpr uint32_t kTestClkId = msm8x53::kBlsp2Qup3I2cAppsClk; + constexpr uint32_t kTestClkIdx = msm8x53::MsmClkIndex(kTestClkId); + const struct clk::msm_clk_branch& branch = kMsmClkBranches[kTestClkIdx]; + + cc_regs[branch.reg].ExpectWrite(kBranchEnable).ExpectRead(0x0); + st = clk.ClockImplEnable(kTestClkId); + EXPECT_OK(st); + + cc_regs[branch.reg].ExpectRead(0x0).ExpectWrite(0x0).ExpectRead(0x80000000); + st = clk.ClockImplDisable(kTestClkId); + EXPECT_OK(st); + + cc_regs.VerifyAll(); +} + +TEST(ClkTest8x53, TestVoterClkEnableDisable) { + zx_status_t st; + auto cc_regs_arr = std::make_unique<ddk_mock::MockMmioReg[]>(msm8x53::kCcSize); + ddk_mock::MockMmioRegRegion cc_regs(cc_regs_arr.get(), sizeof(uint32_t), msm8x53::kCcSize); + Msm8x53ClkTest clk(cc_regs); + + constexpr uint32_t kTestClkId = msm8x53::kBlsp2AhbClk; + + st = clk.ClockImplEnable(kTestClkId); + EXPECT_OK(st); + + st = clk.ClockImplDisable(kTestClkId); + EXPECT_OK(st); +} + +} // namespace clk diff --git a/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.cpp b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.cpp index c753b4e4cb5ca9ede52e5e74131545168e0918a6..1c94a6dab11364717ee0888a1d70bdf26a3c595c 100644 --- a/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.cpp +++ b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.cpp @@ -16,7 +16,6 @@ #include <fbl/unique_ptr.h> #include <fuchsia/hardware/clock/c/fidl.h> #include <hwreg/bitfields.h> -#include <soc/msm8x53/msm8x53-clock.h> #include <ddktl/protocol/platform/bus.h> @@ -24,253 +23,33 @@ namespace clk { -typedef struct msm_clk_gate { - uint32_t reg; - uint32_t bit; - uint32_t delay_us; -} msm_clk_gate_t; - -struct msm_clk_branch { - uint32_t reg; -}; - -struct msm_clk_voter { - uint32_t cbcr_reg; - uint32_t vote_reg; - uint32_t bit; -}; - namespace { -const char kMsmClkName[] = "msm-clk"; - -constexpr msm_clk_gate_t kMsmClkGates[] = { - [msm8x53::MsmClkIndex(msm8x53::kQUsbRefClk)] = {.reg = 0x41030, .bit = 0, .delay_us = 0}, - [msm8x53::MsmClkIndex(msm8x53::kUsbSSRefClk)] = {.reg = 0x5e07c, .bit = 0, .delay_us = 0}, - [msm8x53::MsmClkIndex(msm8x53::kUsb3PipeClk)] = {.reg = 0x5e040, .bit = 0, .delay_us = 50}, -}; - -constexpr uint32_t kBranchEnable = (0x1u << 0); -constexpr struct msm_clk_branch kMsmClkBranches[] = { - [msm8x53::MsmClkIndex(msm8x53::kApc0DroopDetectorGpll0Clk)] = { - .reg = msm8x53::kApc0VoltageDroopDetectorGpll0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kApc1DroopDetectorGpll0Clk)] = { - .reg = msm8x53::kApc1VoltageDroopDetectorGpll0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup1I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup1I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup1SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup1SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup2I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup2I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup2SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup2SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup3I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup3I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup3SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup3SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup4I2cAppsClk)] = {.reg = msm8x53::kBlsp1Qup4I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Qup4SpiAppsClk)] = {.reg = msm8x53::kBlsp1Qup4SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Uart1AppsClk)] = {.reg = msm8x53::kBlsp1Uart1AppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1Uart2AppsClk)] = {.reg = msm8x53::kBlsp1Uart2AppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup1I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup1I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup1SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup1SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup2I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup2I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup2SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup2SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup3I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup3I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup3SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup3SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup4I2cAppsClk)] = {.reg = msm8x53::kBlsp2Qup4I2cAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Qup4SpiAppsClk)] = {.reg = msm8x53::kBlsp2Qup4SpiAppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Uart1AppsClk)] = {.reg = msm8x53::kBlsp2Uart1AppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2Uart2AppsClk)] = {.reg = msm8x53::kBlsp2Uart2AppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBimcGpuClk)] = {.reg = msm8x53::kBimcGpuCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCciAhbClk)] = {.reg = msm8x53::kCamssCciAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCciClk)] = {.reg = msm8x53::kCamssCciCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCppAhbClk)] = {.reg = msm8x53::kCamssCppAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCppAxiClk)] = {.reg = msm8x53::kCamssCppAxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCppClk)] = {.reg = msm8x53::kCamssCppCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0AhbClk)] = {.reg = msm8x53::kCamssCsi0AhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0Clk)] = {.reg = msm8x53::kCamssCsi0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0Csiphy3pClk)] = { - .reg = msm8x53::kCamssCsi0Csiphy3pCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0phyClk)] = {.reg = msm8x53::kCamssCsi0phyCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0pixClk)] = {.reg = msm8x53::kCamssCsi0pixCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0rdiClk)] = {.reg = msm8x53::kCamssCsi0rdiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1AhbClk)] = {.reg = msm8x53::kCamssCsi1AhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1Clk)] = {.reg = msm8x53::kCamssCsi1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1Csiphy3pClk)] = { - .reg = msm8x53::kCamssCsi1Csiphy3pCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1phyClk)] = {.reg = msm8x53::kCamssCsi1phyCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1pixClk)] = {.reg = msm8x53::kCamssCsi1pixCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1rdiClk)] = {.reg = msm8x53::kCamssCsi1rdiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2AhbClk)] = {.reg = msm8x53::kCamssCsi2AhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2Clk)] = {.reg = msm8x53::kCamssCsi2Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2Csiphy3pClk)] = { - .reg = msm8x53::kCamssCsi2Csiphy3pCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2phyClk)] = {.reg = msm8x53::kCamssCsi2phyCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2pixClk)] = {.reg = msm8x53::kCamssCsi2pixCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2rdiClk)] = {.reg = msm8x53::kCamssCsi2rdiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsiVfe0Clk)] = {.reg = msm8x53::kCamssCsiVfe0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsiVfe1Clk)] = {.reg = msm8x53::kCamssCsiVfe1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssGp0Clk)] = {.reg = msm8x53::kCamssGp0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssGp1Clk)] = {.reg = msm8x53::kCamssGp1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssIspifAhbClk)] = {.reg = msm8x53::kCamssIspifAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssJpeg0Clk)] = {.reg = msm8x53::kCamssJpeg0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssJpegAhbClk)] = {.reg = msm8x53::kCamssJpegAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssJpegAxiClk)] = {.reg = msm8x53::kCamssJpegAxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssMclk0Clk)] = {.reg = msm8x53::kCamssMclk0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssMclk1Clk)] = {.reg = msm8x53::kCamssMclk1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssMclk2Clk)] = {.reg = msm8x53::kCamssMclk2Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssMclk3Clk)] = {.reg = msm8x53::kCamssMclk3Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssMicroAhbClk)] = {.reg = msm8x53::kCamssMicroAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi0phytimerClk)] = { - .reg = msm8x53::kCamssCsi0phytimerCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi1phytimerClk)] = { - .reg = msm8x53::kCamssCsi1phytimerCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssCsi2phytimerClk)] = { - .reg = msm8x53::kCamssCsi2phytimerCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssAhbClk)] = {.reg = msm8x53::kCamssAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssTopAhbClk)] = {.reg = msm8x53::kCamssTopAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssVfe0Clk)] = {.reg = msm8x53::kCamssVfe0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssVfeAhbClk)] = {.reg = msm8x53::kCamssVfeAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssVfeAxiClk)] = {.reg = msm8x53::kCamssVfeAxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssVfe1AhbClk)] = {.reg = msm8x53::kCamssVfe1AhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssVfe1AxiClk)] = {.reg = msm8x53::kCamssVfe1AxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kCamssVfe1Clk)] = {.reg = msm8x53::kCamssVfe1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kDccClk)] = {.reg = msm8x53::kDccCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kGp1Clk)] = {.reg = msm8x53::kGp1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kGp2Clk)] = {.reg = msm8x53::kGp2Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kGp3Clk)] = {.reg = msm8x53::kGp3Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssAhbClk)] = {.reg = msm8x53::kMdssAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssAxiClk)] = {.reg = msm8x53::kMdssAxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssByte0Clk)] = {.reg = msm8x53::kMdssByte0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssByte1Clk)] = {.reg = msm8x53::kMdssByte1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssEsc0Clk)] = {.reg = msm8x53::kMdssEsc0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssEsc1Clk)] = {.reg = msm8x53::kMdssEsc1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssMdpClk)] = {.reg = msm8x53::kMdssMdpCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssPclk0Clk)] = {.reg = msm8x53::kMdssPclk0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssPclk1Clk)] = {.reg = msm8x53::kMdssPclk1Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMdssVsyncClk)] = {.reg = msm8x53::kMdssVsyncCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMssCfgAhbClk)] = {.reg = msm8x53::kMssCfgAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kMssQ6BimcAxiClk)] = {.reg = msm8x53::kMssQ6BimcAxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kBimcGfxClk)] = {.reg = msm8x53::kBimcGfxCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kOxiliAhbClk)] = {.reg = msm8x53::kOxiliAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kOxiliAonClk)] = {.reg = msm8x53::kOxiliAonCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kOxiliGfx3dClk)] = {.reg = msm8x53::kOxiliGfx3dCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kOxiliTimerClk)] = {.reg = msm8x53::kOxiliTimerCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kPcnocUsb3AxiClk)] = {.reg = msm8x53::kPcnocUsb3AxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kPdm2Clk)] = {.reg = msm8x53::kPdm2Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kPdmAhbClk)] = {.reg = msm8x53::kPdmAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kRbcprGfxClk)] = {.reg = msm8x53::kRbcprGfxCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kSdcc1AhbClk)] = {.reg = msm8x53::kSdcc1AhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kSdcc1AppsClk)] = {.reg = msm8x53::kSdcc1AppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kSdcc1IceCoreClk)] = {.reg = msm8x53::kSdcc1IceCoreCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kSdcc2AhbClk)] = {.reg = msm8x53::kSdcc2AhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kSdcc2AppsClk)] = {.reg = msm8x53::kSdcc2AppsCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kUsb30MasterClk)] = {.reg = msm8x53::kUsb30MasterCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kUsb30MockUtmiClk)] = {.reg = msm8x53::kUsb30MockUtmiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kUsb30SleepClk)] = {.reg = msm8x53::kUsb30SleepCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kUsb3AuxClk)] = {.reg = msm8x53::kUsb3AuxCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kUsbPhyCfgAhbClk)] = {.reg = msm8x53::kUsbPhyCfgAhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kVenus0AhbClk)] = {.reg = msm8x53::kVenus0AhbCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kVenus0AxiClk)] = {.reg = msm8x53::kVenus0AxiCbcr}, - [msm8x53::MsmClkIndex(msm8x53::kVenus0Core0Vcodec0Clk)] = { - .reg = msm8x53::kVenus0Core0Vcodec0Cbcr}, - [msm8x53::MsmClkIndex(msm8x53::kVenus0Vcodec0Clk)] = {.reg = msm8x53::kVenus0Vcodec0Cbcr}, -}; - -constexpr struct msm_clk_voter kMsmClkVoters[] = { - [msm8x53::MsmClkIndex(msm8x53::kApssAhbClk)] = { - .cbcr_reg = msm8x53::kApssAhbCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 14) - }, - [msm8x53::MsmClkIndex(msm8x53::kApssAxiClk)] = { - .cbcr_reg = msm8x53::kApssAxiCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 13) - }, - [msm8x53::MsmClkIndex(msm8x53::kBlsp1AhbClk)] = { - .cbcr_reg = msm8x53::kBlsp1AhbCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 10) - }, - [msm8x53::MsmClkIndex(msm8x53::kBlsp2AhbClk)] = { - .cbcr_reg = msm8x53::kBlsp2AhbCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 20) - }, - [msm8x53::MsmClkIndex(msm8x53::kBootRomAhbClk)] = { - .cbcr_reg = msm8x53::kBootRomAhbCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 7) - }, - [msm8x53::MsmClkIndex(msm8x53::kCryptoAhbClk)] = { - .cbcr_reg = msm8x53::kCryptoAhbCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 0) - }, - [msm8x53::MsmClkIndex(msm8x53::kCryptoAxiClk)] = { - .cbcr_reg = msm8x53::kCryptoAxiCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 1) - }, - [msm8x53::MsmClkIndex(msm8x53::kCryptoClk)] = { - .cbcr_reg = msm8x53::kCryptoCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 2) - }, - [msm8x53::MsmClkIndex(msm8x53::kQdssDapClk)] = { - .cbcr_reg = msm8x53::kQdssDapCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 11) - }, - [msm8x53::MsmClkIndex(msm8x53::kPrngAhbClk)] = { - .cbcr_reg = msm8x53::kPrngAhbCbcr, - .vote_reg = msm8x53::kApcsClockBranchEnaVote, - .bit = (1 << 8) - }, - [msm8x53::MsmClkIndex(msm8x53::kApssTcuAsyncClk)] = { - .cbcr_reg = msm8x53::kApssTcuAsyncCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 1) - }, - [msm8x53::MsmClkIndex(msm8x53::kCppTbuClk)] = { - .cbcr_reg = msm8x53::kCppTbuCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 14) - }, - [msm8x53::MsmClkIndex(msm8x53::kJpegTbuClk)] = { - .cbcr_reg = msm8x53::kJpegTbuCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 10) - }, - [msm8x53::MsmClkIndex(msm8x53::kMdpTbuClk)] = { - .cbcr_reg = msm8x53::kMdpTbuCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 4) - }, - [msm8x53::MsmClkIndex(msm8x53::kSmmuCfgClk)] = { - .cbcr_reg = msm8x53::kSmmuCfgCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 12) - }, - [msm8x53::MsmClkIndex(msm8x53::kVenusTbuClk)] = { - .cbcr_reg = msm8x53::kVenusTbuCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 5) - }, - [msm8x53::MsmClkIndex(msm8x53::kVfe1TbuClk)] = { - .cbcr_reg = msm8x53::kVfe1TbuCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 17) - }, - [msm8x53::MsmClkIndex(msm8x53::kVfeTbuClk)] = { - .cbcr_reg = msm8x53::kVfeTbuCbcr, - .vote_reg = msm8x53::kApcsSmmuClockBranchEnaVote, - .bit = (1 << 9) - }, -}; +constexpr char kMsmClkName[] = "msm-clk"; +constexpr uint32_t kRcgUpdateTimeoutUsec = 500; +constexpr uint64_t kRcgRateUnset = 0; +constexpr uint32_t kCfgRcgrDivMask = (0x1f << 0); +constexpr uint32_t kCfgRcgrSrcSelMask = (0x7 << 8); } // namespace zx_status_t Msm8x53Clk::Create(void* ctx, zx_device_t* parent) { zx_status_t status; - std::unique_ptr<Msm8x53Clk> device(new Msm8x53Clk(parent)); + ddk::PDev pdev(parent); + if (!pdev.is_valid()) { + zxlogf(ERROR, "msm-clk: failed to get pdev protocol\n"); + return ZX_ERR_NO_RESOURCES; + } + + std::optional<ddk::MmioBuffer> mmio; + status = pdev.MapMmio(0, &mmio); + if (status != ZX_OK) { + zxlogf(ERROR, "msm-clk: failed to map cc_base mmio, st = %d\n", status); + return status; + } + + std::unique_ptr<Msm8x53Clk> device(new Msm8x53Clk(parent, *std::move(mmio))); status = device->Init(); if (status != ZX_OK) { @@ -291,19 +70,12 @@ zx_status_t Msm8x53Clk::Create(void* ctx, zx_device_t* parent) { } zx_status_t Msm8x53Clk::Init() { - ddk::PDev pdev(parent()); - if (!pdev.is_valid()) { - zxlogf(ERROR, "msm-clk: failed to get pdev protocol\n"); - return ZX_ERR_NO_RESOURCES; - } - - zx_status_t status = pdev.MapMmio(0, &mmio_); - if (status != ZX_OK) { - zxlogf(ERROR, "msm-clk: failed to map cc_base mmio, st = %d\n", status); - return status; + fbl::AutoLock lock(&rcg_rates_lock_); + for (size_t i = 0; i < msm8x53::kRcgClkCount; i++) { + rcg_rates_[i] = kRcgRateUnset; } - status = RegisterClockProtocol(); + zx_status_t status = RegisterClockProtocol(); if (status != ZX_OK) { zxlogf(ERROR, "msm-clk: failed to register clock impl protocol, st = %d\n", status); return status; @@ -324,6 +96,8 @@ zx_status_t Msm8x53Clk::ClockImplEnable(uint32_t index) { return BranchClockEnable(clock_id); case msm8x53::msm_clk_type::kVoter: return VoterClockEnable(clock_id); + case msm8x53::msm_clk_type::kRcg: + return RcgClockEnable(clock_id); } // Unimplemented clock type? @@ -342,6 +116,8 @@ zx_status_t Msm8x53Clk::ClockImplDisable(uint32_t index) { return BranchClockDisable(clock_id); case msm8x53::msm_clk_type::kVoter: return VoterClockDisable(clock_id); + case msm8x53::msm_clk_type::kRcg: + return RcgClockDisable(clock_id); } // Unimplemented clock type? @@ -349,11 +125,22 @@ zx_status_t Msm8x53Clk::ClockImplDisable(uint32_t index) { } zx_status_t Msm8x53Clk::ClockImplRequestRate(uint32_t id, uint64_t hz) { + const uint32_t index = msm8x53::MsmClkIndex(id); + const msm8x53::msm_clk_type clock_type = msm8x53::MsmClkType(id); + + switch (clock_type) { + case msm8x53::msm_clk_type::kRcg: { + fbl::AutoLock rcg_rates_lock(&rcg_rates_lock_); + return RcgClockSetRate(index, hz); + } + default: + zxlogf(WARN, "msm_clk: unsupported clock type: %u\n", (uint16_t)clock_type); + } + return ZX_ERR_NOT_SUPPORTED; } -zx_status_t Msm8x53Clk::AwaitBranchClock(AwaitBranchClockStatus status, - const uint32_t cbcr_reg) { +zx_status_t Msm8x53Clk::AwaitBranchClock(Toggle status, const uint32_t cbcr_reg) { // In case the status check register and the clock control register cross // a boundary. hw_mb(); @@ -367,15 +154,15 @@ zx_status_t Msm8x53Clk::AwaitBranchClock(AwaitBranchClockStatus status, constexpr uint32_t kMaxAttempts = 500; for (uint32_t attempts = 0; attempts < kMaxAttempts; attempts++) { - const uint32_t val = mmio_->Read32(cbcr_reg) & kReadyMask; + const uint32_t val = mmio_.Read32(cbcr_reg) & kReadyMask; switch (status) { - case AwaitBranchClockStatus::Enabled: + case Toggle::Enabled: if ((val == kBranchEnableVal) || (val == kBranchNocFsmEnableVal)) { return ZX_OK; } break; - case AwaitBranchClockStatus::Disabled: + case Toggle::Disabled: if (val == kBranchDisableVal) { return ZX_OK; } @@ -396,10 +183,10 @@ zx_status_t Msm8x53Clk::VoterClockEnable(uint32_t index) { const struct clk::msm_clk_voter& clk = kMsmClkVoters[index]; lock_.Acquire(); - mmio_->SetBits32(clk.bit, clk.vote_reg); + mmio_.SetBits32(clk.bit, clk.vote_reg); lock_.Release(); - return AwaitBranchClock(AwaitBranchClockStatus::Enabled, clk.cbcr_reg); + return AwaitBranchClock(Toggle::Enabled, clk.cbcr_reg); } zx_status_t Msm8x53Clk::VoterClockDisable(uint32_t index) { @@ -410,7 +197,7 @@ zx_status_t Msm8x53Clk::VoterClockDisable(uint32_t index) { const struct clk::msm_clk_voter& clk = kMsmClkVoters[index]; lock_.Acquire(); - mmio_->ClearBits32(clk.bit, clk.vote_reg); + mmio_.ClearBits32(clk.bit, clk.vote_reg); lock_.Release(); return ZX_OK; @@ -424,10 +211,10 @@ zx_status_t Msm8x53Clk::BranchClockEnable(uint32_t index) { const struct clk::msm_clk_branch& clk = kMsmClkBranches[index]; lock_.Acquire(); - mmio_->SetBits32(kBranchEnable, clk.reg); + mmio_.SetBits32(kBranchEnable, clk.reg); lock_.Release(); - return AwaitBranchClock(AwaitBranchClockStatus::Enabled, clk.reg); + return AwaitBranchClock(Toggle::Enabled, clk.reg); } zx_status_t Msm8x53Clk::BranchClockDisable(uint32_t index) { @@ -438,10 +225,10 @@ zx_status_t Msm8x53Clk::BranchClockDisable(uint32_t index) { const struct msm_clk_branch& clk = kMsmClkBranches[index]; lock_.Acquire(); - mmio_->ClearBits32(kBranchEnable, clk.reg); + mmio_.ClearBits32(kBranchEnable, clk.reg); lock_.Release(); - return AwaitBranchClock(AwaitBranchClockStatus::Disabled, clk.reg); + return AwaitBranchClock(Toggle::Disabled, clk.reg); } zx_status_t Msm8x53Clk::GateClockEnable(uint32_t index) { @@ -452,7 +239,7 @@ zx_status_t Msm8x53Clk::GateClockEnable(uint32_t index) { const msm_clk_gate_t& clk = kMsmClkGates[index]; lock_.Acquire(); - mmio_->SetBits32(clk.bit, clk.reg); + mmio_.SetBits32((1u << clk.bit), clk.reg); lock_.Release(); if (clk.delay_us) { @@ -469,7 +256,7 @@ zx_status_t Msm8x53Clk::GateClockDisable(uint32_t index) { const msm_clk_gate_t& clk = kMsmClkGates[index]; lock_.Acquire(); - mmio_->ClearBits32(clk.bit, clk.reg); + mmio_.ClearBits32(clk.bit, clk.reg); lock_.Release(); if (clk.delay_us) { @@ -479,12 +266,193 @@ zx_status_t Msm8x53Clk::GateClockDisable(uint32_t index) { return ZX_OK; } +zx_status_t Msm8x53Clk::RcgClockEnable(uint32_t index) { + if (unlikely(index > countof(kMsmClkRcgs))) { + return ZX_ERR_OUT_OF_RANGE; + } + + const MsmClkRcg& clk = kMsmClkRcgs[index]; + + // Check to see if frequency has been set. + fbl::AutoLock lock(&rcg_rates_lock_); + if (rcg_rates_[index] == kRcgRateUnset) { + zxlogf(ERROR, "Attempted to enable RCG %u before setting rate\n", index); + return ZX_ERR_BAD_STATE; + } + + zx_status_t st; + + st = ToggleRcgForceEnable(clk.CmdReg(), Toggle::Enabled); + if (st != ZX_OK) { + return st; + } + + st = RcgClockSetRate(index, rcg_rates_[index]); + if (st != ZX_OK) { + return st; + } + + st = ToggleRcgForceEnable(clk.CmdReg(), Toggle::Disabled); + if (st != ZX_OK) { + return st; + } + + return st; +} + +zx_status_t Msm8x53Clk::RcgClockDisable(uint32_t index) { + // This is a NOP for all clocks that we support. + // It only needs to be implemented for clocks with non-local children. + return ZX_OK; +} + +zx_status_t Msm8x53Clk::RcgClockSetRate(uint32_t index, uint64_t rate) { + if (unlikely(index >= countof(kMsmClkRcgs))) { + return ZX_ERR_OUT_OF_RANGE; + } + + const MsmClkRcg& clk = kMsmClkRcgs[index]; + + // Clocks with non-local children or nonlocal control timeouts are + // currently unimplemented. + // Clocks with source frequencies that are not fixed are also currently + // unimplemented. + if (clk.Unsupported()) { + zxlogf(ERROR, "Attempted to set rate for clock %u which is currently " + "unimplemented\n", + index); + return ZX_ERR_NOT_SUPPORTED; + } + + // Search for the requested frequency in the clock's frequency table. + const RcgFrequencyTable* table = nullptr; + for (size_t i = 0; i < clk.TableCount(); i++) { + if (rate == clk.Table()[i].rate()) { + table = &clk.Table()[i]; + break; + } + } + + if (table == nullptr) { + // This clock frequency is not supported. + zxlogf(WARN, "unsupported clock frequency, clk = %u, rate = %lu\n", + index, rate); + return ZX_ERR_NOT_SUPPORTED; + } + + { // Nested scope for scoped locking + fbl::AutoLock lock(&lock_); + + switch (clk.Type()) { + case RcgDividerType::HalfInteger: + RcgSetRateHalfInteger(clk, table); + break; + case RcgDividerType::Mnd: + RcgSetRateMnd(clk, table); + break; + } + } + + // Update the frequency that we have listed in the RCG table. + rcg_rates_[index] = rate; + + return ZX_OK; +} + +zx_status_t Msm8x53Clk::LatchRcgConfig(const MsmClkRcg& clk) { + // Whack the config update bit and wait for it to stabilize. + constexpr uint32_t kCmdRcgrConfigUpdateBit = (0x1 << 0); + mmio_.SetBits32(kCmdRcgrConfigUpdateBit, clk.CmdReg()); + + constexpr uint32_t kMaxAttempts = 500; + for (uint32_t i = 0; i < kMaxAttempts; i++) { + const uint32_t cmd_reg = mmio_.Read32(clk.CmdReg()); + + if ((cmd_reg & kCmdRcgrConfigUpdateBit) == 0) { + return ZX_OK; + } + + zx_nanosleep(zx_deadline_after(ZX_USEC(1))); + } + + zxlogf(WARN, "Failed to latch RCG config\n"); + return ZX_ERR_TIMED_OUT; +} + +zx_status_t Msm8x53Clk::RcgSetRateHalfInteger(const MsmClkRcg& clk, const RcgFrequencyTable* table) { + uint32_t val; + + val = mmio_.Read32(clk.CfgReg()); + val &= ~(kCfgRcgrDivMask | kCfgRcgrSrcSelMask); + val |= table->predev_parent(); + mmio_.Write32(val, clk.CfgReg()); + + return LatchRcgConfig(clk); +} + +zx_status_t Msm8x53Clk::RcgSetRateMnd(const MsmClkRcg& clk, const RcgFrequencyTable* table) { + uint32_t cfg = mmio_.Read32(clk.CfgReg()); + + constexpr uint32_t kMndModeMask = (0x3 << 12); + constexpr uint32_t kMndDualEdgeMode = (0x2 << 12); + + mmio_.Write32(table->m(), clk.MReg()); + mmio_.Write32(table->n(), clk.NReg()); + mmio_.Write32(table->d(), clk.DReg()); + + cfg = mmio_.Read32(clk.CfgReg()); + cfg &= ~(kCfgRcgrDivMask | kCfgRcgrSrcSelMask); + cfg |= table->predev_parent(); + + cfg &= ~kMndModeMask; + if (table->n() != 0) { + cfg |= kMndDualEdgeMode; + } + mmio_.Write32(cfg, clk.CfgReg()); + + return LatchRcgConfig(clk); +} + +zx_status_t Msm8x53Clk::ToggleRcgForceEnable(uint32_t rcgr_cmd_offset, Toggle toggle) { + constexpr uint32_t kRcgForceDisableDelayUSeconds = 100; + constexpr uint32_t kRcgRootEnableBit = (1 << 1); + zx_status_t result = ZX_OK; + + switch (toggle) { + case Toggle::Enabled: + lock_.Acquire(); + mmio_.SetBits32(kRcgRootEnableBit, rcgr_cmd_offset); + result = AwaitRcgEnableLocked(rcgr_cmd_offset); + lock_.Release(); + break; + case Toggle::Disabled: + lock_.Acquire(); + mmio_.ClearBits32(kRcgRootEnableBit, rcgr_cmd_offset); + lock_.Release(); + zx_nanosleep(zx_deadline_after(ZX_USEC(kRcgForceDisableDelayUSeconds))); + break; + } + return result; +} + +zx_status_t Msm8x53Clk::AwaitRcgEnableLocked(uint32_t rcgr_cmd_offset) { + for (uint32_t i = 0; i < kRcgUpdateTimeoutUsec; i++) { + auto rcg_ctrl = RcgClkCmd::Read(rcgr_cmd_offset).ReadFrom(&mmio_); + + if (rcg_ctrl.root_status() == 0) { + return ZX_OK; + } + + zx_nanosleep(zx_deadline_after(ZX_USEC(1))); + } + + return ZX_ERR_TIMED_OUT; +} + zx_status_t Msm8x53Clk::Bind() { return ZX_OK; } void Msm8x53Clk::DdkUnbind() { - // Hazard! Always acquire locks in the order that they were defined in the - // header. fbl::AutoLock lock(&lock_); mmio_.reset(); diff --git a/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.h b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.h index 45363f5e084b2e867bc0a7e2373845b9610c0bdc..9d87fcb600da6fc24ac6338210ddc6e384b8fe1c 100644 --- a/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.h +++ b/zircon/system/dev/clk/msm8x53-clk/msm8x53-clk.h @@ -9,10 +9,15 @@ #include <fbl/mutex.h> #include <fuchsia/hardware/clock/c/fidl.h> #include <lib/mmio/mmio.h> +#include <soc/msm8x53/msm8x53-clock.h> #include <zircon/thread_annotations.h> namespace clk { +// Fwd declarations +class RcgFrequencyTable; +class MsmClkRcg; + class Msm8x53Clk; using DeviceType = ddk::Device<Msm8x53Clk, ddk::Unbindable>; @@ -33,33 +38,48 @@ public: void DdkUnbind(); void DdkRelease(); -private: - Msm8x53Clk(zx_device_t* parent) - : DeviceType(parent) {} +// Protected for tests. +protected: + Msm8x53Clk(zx_device_t* parent, ddk::MmioBuffer mmio) + : DeviceType(parent) + , mmio_(std::move(mmio)) {} zx_status_t RegisterClockProtocol(); + enum class Toggle { + Enabled, + Disabled + }; + // Gate Clocks zx_status_t GateClockEnable(uint32_t index); zx_status_t GateClockDisable(uint32_t index); + // RCG Clocks + zx_status_t RcgClockEnable(uint32_t index); + zx_status_t RcgClockDisable(uint32_t index); + zx_status_t RcgClockSetRate(uint32_t index, uint64_t hz) __TA_REQUIRES(rcg_rates_lock_); + zx_status_t ToggleRcgForceEnable(uint32_t rcgr_cmd_offset, Toggle toggle); + zx_status_t AwaitRcgEnableLocked(uint32_t rcgr_cmd_offset) __TA_REQUIRES(lock_); + zx_status_t RcgSetRateMnd(const MsmClkRcg& clk, const RcgFrequencyTable* table); + zx_status_t RcgSetRateHalfInteger(const MsmClkRcg& clk, const RcgFrequencyTable* table); + zx_status_t LatchRcgConfig(const MsmClkRcg& clk); + // Branch Clocks zx_status_t BranchClockEnable(uint32_t index); zx_status_t BranchClockDisable(uint32_t index); - enum class AwaitBranchClockStatus { - Enabled, - Disabled - }; // Wait for a change to a particular branch clock to take effect. - zx_status_t AwaitBranchClock(AwaitBranchClockStatus s, - const uint32_t cbcr_reg); + zx_status_t AwaitBranchClock(Toggle s, const uint32_t cbcr_reg); // Voter Clocks zx_status_t VoterClockEnable(uint32_t index); zx_status_t VoterClockDisable(uint32_t index); - fbl::Mutex lock_; // Lock guards mmio_. - std::optional<ddk::MmioBuffer> mmio_; + fbl::Mutex lock_; // Lock guards mmio_. + ddk::MmioBuffer mmio_; + + fbl::Mutex rcg_rates_lock_; + uint64_t rcg_rates_[msm8x53::kRcgClkCount]; }; } // namespace clk diff --git a/zircon/system/dev/lib/msm8x53/include/soc/msm8x53/msm8x53-clock.h b/zircon/system/dev/lib/msm8x53/include/soc/msm8x53/msm8x53-clock.h index bf3080e4a04f8622777590d18a18188160fb89b0..5774ceb909fe952e9f269ed89602d2b873e9ed19 100644 --- a/zircon/system/dev/lib/msm8x53/include/soc/msm8x53/msm8x53-clock.h +++ b/zircon/system/dev/lib/msm8x53/include/soc/msm8x53/msm8x53-clock.h @@ -31,7 +31,7 @@ public: }; // Root clock gating config register. -class RCG_CFG: public hwreg::RegisterBase<RCG_CFG, uint32_t> { +class RCG_CFG : public hwreg::RegisterBase<RCG_CFG, uint32_t> { public: DEF_FIELD(12, 11, mode); DEF_FIELD(8, 6, src_sel); @@ -65,9 +65,10 @@ static constexpr uint32_t kCcBase = 0x1800000; static constexpr uint32_t kCcSize = 0x80000; enum class msm_clk_type : uint16_t { - kGate, + kGate = 0, kBranch, kVoter, + kRcg }; // Create a clock ID based on a type and an index @@ -224,4 +225,73 @@ constexpr uint32_t kVenusTbuClk = MsmClkId(15, msm_clk_type::kVoter); constexpr uint32_t kVfe1TbuClk = MsmClkId(16, msm_clk_type::kVoter); constexpr uint32_t kVfeTbuClk = MsmClkId(17, msm_clk_type::kVoter); +// MSM RCG Gates +constexpr uint32_t kCamssTopAhbClkSrc = MsmClkId(0, msm_clk_type::kRcg); +constexpr uint32_t kCsi0ClkSrc = MsmClkId(1, msm_clk_type::kRcg); +constexpr uint32_t kApssAhbClkSrc = MsmClkId(2, msm_clk_type::kRcg); +constexpr uint32_t kCsi1ClkSrc = MsmClkId(3, msm_clk_type::kRcg); +constexpr uint32_t kCsi2ClkSrc = MsmClkId(4, msm_clk_type::kRcg); +constexpr uint32_t kVfe0ClkSrc = MsmClkId(5, msm_clk_type::kRcg); +constexpr uint32_t kGfx3dClkSrc = MsmClkId(6, msm_clk_type::kRcg); +constexpr uint32_t kVcodec0ClkSrc = MsmClkId(7, msm_clk_type::kRcg); +constexpr uint32_t kCppClkSrc = MsmClkId(8, msm_clk_type::kRcg); +constexpr uint32_t kJpeg0ClkSrc = MsmClkId(9, msm_clk_type::kRcg); +constexpr uint32_t kMdpClkSrc = MsmClkId(10, msm_clk_type::kRcg); +constexpr uint32_t kPclk0ClkSrc = MsmClkId(11, msm_clk_type::kRcg); +constexpr uint32_t kPclk1ClkSrc = MsmClkId(12, msm_clk_type::kRcg); +constexpr uint32_t kUsb30MasterClkSrc = MsmClkId(13, msm_clk_type::kRcg); +constexpr uint32_t kVfe1ClkSrc = MsmClkId(14, msm_clk_type::kRcg); +constexpr uint32_t kApc0DroopDetectorClkSrc = MsmClkId(15, msm_clk_type::kRcg); +constexpr uint32_t kApc1DroopDetectorClkSrc = MsmClkId(16, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup1I2cAppsClkSrc = MsmClkId(17, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup1SpiAppsClkSrc = MsmClkId(18, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup2I2cAppsClkSrc = MsmClkId(19, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup2SpiAppsClkSrc = MsmClkId(20, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup3I2cAppsClkSrc = MsmClkId(21, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup3SpiAppsClkSrc = MsmClkId(22, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup4I2cAppsClkSrc = MsmClkId(23, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Qup4SpiAppsClkSrc = MsmClkId(24, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Uart1AppsClkSrc = MsmClkId(25, msm_clk_type::kRcg); +constexpr uint32_t kBlsp1Uart2AppsClkSrc = MsmClkId(26, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup1I2cAppsClkSrc = MsmClkId(27, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup1SpiAppsClkSrc = MsmClkId(28, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup2I2cAppsClkSrc = MsmClkId(29, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup2SpiAppsClkSrc = MsmClkId(30, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup3I2cAppsClkSrc = MsmClkId(31, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup3SpiAppsClkSrc = MsmClkId(32, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup4I2cAppsClkSrc = MsmClkId(33, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Qup4SpiAppsClkSrc = MsmClkId(34, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Uart1AppsClkSrc = MsmClkId(35, msm_clk_type::kRcg); +constexpr uint32_t kBlsp2Uart2AppsClkSrc = MsmClkId(36, msm_clk_type::kRcg); +constexpr uint32_t kCciClkSrc = MsmClkId(37, msm_clk_type::kRcg); +constexpr uint32_t kCsi0pClkSrc = MsmClkId(38, msm_clk_type::kRcg); +constexpr uint32_t kCsi1pClkSrc = MsmClkId(39, msm_clk_type::kRcg); +constexpr uint32_t kCsi2pClkSrc = MsmClkId(40, msm_clk_type::kRcg); +constexpr uint32_t kCamssGp0ClkSrc = MsmClkId(41, msm_clk_type::kRcg); +constexpr uint32_t kCamssGp1ClkSrc = MsmClkId(42, msm_clk_type::kRcg); +constexpr uint32_t kMclk0ClkSrc = MsmClkId(43, msm_clk_type::kRcg); +constexpr uint32_t kMclk1ClkSrc = MsmClkId(44, msm_clk_type::kRcg); +constexpr uint32_t kMclk2ClkSrc = MsmClkId(45, msm_clk_type::kRcg); +constexpr uint32_t kMclk3ClkSrc = MsmClkId(46, msm_clk_type::kRcg); +constexpr uint32_t kCsi0phytimerClkSrc = MsmClkId(47, msm_clk_type::kRcg); +constexpr uint32_t kCsi1phytimerClkSrc = MsmClkId(48, msm_clk_type::kRcg); +constexpr uint32_t kCsi2phytimerClkSrc = MsmClkId(49, msm_clk_type::kRcg); +constexpr uint32_t kCryptoClkSrc = MsmClkId(50, msm_clk_type::kRcg); +constexpr uint32_t kGp1ClkSrc = MsmClkId(51, msm_clk_type::kRcg); +constexpr uint32_t kGp2ClkSrc = MsmClkId(52, msm_clk_type::kRcg); +constexpr uint32_t kGp3ClkSrc = MsmClkId(53, msm_clk_type::kRcg); +constexpr uint32_t kByte0ClkSrc = MsmClkId(54, msm_clk_type::kRcg); +constexpr uint32_t kByte1ClkSrc = MsmClkId(55, msm_clk_type::kRcg); +constexpr uint32_t kEsc0ClkSrc = MsmClkId(56, msm_clk_type::kRcg); +constexpr uint32_t kEsc1ClkSrc = MsmClkId(57, msm_clk_type::kRcg); +constexpr uint32_t kVsyncClkSrc = MsmClkId(58, msm_clk_type::kRcg); +constexpr uint32_t kPdm2ClkSrc = MsmClkId(59, msm_clk_type::kRcg); +constexpr uint32_t kRbcprGfxClkSrc = MsmClkId(60, msm_clk_type::kRcg); +constexpr uint32_t kSdcc1AppsClkSrc = MsmClkId(61, msm_clk_type::kRcg); +constexpr uint32_t kSdcc1IceCoreClkSrc = MsmClkId(62, msm_clk_type::kRcg); +constexpr uint32_t kSdcc2AppsClkSrc = MsmClkId(63, msm_clk_type::kRcg); +constexpr uint32_t kUsb30MockUtmiClkSrc = MsmClkId(64, msm_clk_type::kRcg); +constexpr uint32_t kUsb3AuxClkSrc = MsmClkId(65, msm_clk_type::kRcg); +constexpr uint32_t kRcgClkCount = 66; + } // namespace msm8x53 diff --git a/zircon/system/utest/BUILD.gn b/zircon/system/utest/BUILD.gn index 31e1717cbe65cd2a892d8b3b80032eb9b97a2148..22d672875ad62fe1df386234a6d805e30d986f81 100644 --- a/zircon/system/utest/BUILD.gn +++ b/zircon/system/utest/BUILD.gn @@ -38,6 +38,7 @@ if (current_cpu != "") { "$zx/system/dev/nand/ram-nand:ram-nand-test", "$zx/system/dev/nand/skip-block:skip-block-test", "$zx/system/dev/power/msm8x53-power:msm8x53-power-test", + "$zx/system/dev/clk/msm8x53-clk:msm8x53-clk-test", "$zx/system/dev/sysmem/sysmem:sysmem-unittest", "$zx/system/dev/test/usb", "$zx/system/dev/thermal/mtk-thermal:mtk-thermal-test",