1781182e1SJean-Christophe Dubois /* 2781182e1SJean-Christophe Dubois * IMX6UL Clock Control Module 3781182e1SJean-Christophe Dubois * 4781182e1SJean-Christophe Dubois * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net> 5781182e1SJean-Christophe Dubois * 6781182e1SJean-Christophe Dubois * This work is licensed under the terms of the GNU GPL, version 2 or later. 7781182e1SJean-Christophe Dubois * See the COPYING file in the top-level directory. 8781182e1SJean-Christophe Dubois * 9781182e1SJean-Christophe Dubois * To get the timer frequencies right, we need to emulate at least part of 10781182e1SJean-Christophe Dubois * the CCM. 11781182e1SJean-Christophe Dubois */ 12781182e1SJean-Christophe Dubois 13781182e1SJean-Christophe Dubois #include "qemu/osdep.h" 14781182e1SJean-Christophe Dubois #include "hw/registerfields.h" 15*d6454270SMarkus Armbruster #include "migration/vmstate.h" 16781182e1SJean-Christophe Dubois #include "hw/misc/imx6ul_ccm.h" 17781182e1SJean-Christophe Dubois #include "qemu/log.h" 180b8fa32fSMarkus Armbruster #include "qemu/module.h" 19781182e1SJean-Christophe Dubois 20781182e1SJean-Christophe Dubois #include "trace.h" 21781182e1SJean-Christophe Dubois 22781182e1SJean-Christophe Dubois static const char *imx6ul_ccm_reg_name(uint32_t reg) 23781182e1SJean-Christophe Dubois { 24781182e1SJean-Christophe Dubois static char unknown[20]; 25781182e1SJean-Christophe Dubois 26781182e1SJean-Christophe Dubois switch (reg) { 27781182e1SJean-Christophe Dubois case CCM_CCR: 28781182e1SJean-Christophe Dubois return "CCR"; 29781182e1SJean-Christophe Dubois case CCM_CCDR: 30781182e1SJean-Christophe Dubois return "CCDR"; 31781182e1SJean-Christophe Dubois case CCM_CSR: 32781182e1SJean-Christophe Dubois return "CSR"; 33781182e1SJean-Christophe Dubois case CCM_CCSR: 34781182e1SJean-Christophe Dubois return "CCSR"; 35781182e1SJean-Christophe Dubois case CCM_CACRR: 36781182e1SJean-Christophe Dubois return "CACRR"; 37781182e1SJean-Christophe Dubois case CCM_CBCDR: 38781182e1SJean-Christophe Dubois return "CBCDR"; 39781182e1SJean-Christophe Dubois case CCM_CBCMR: 40781182e1SJean-Christophe Dubois return "CBCMR"; 41781182e1SJean-Christophe Dubois case CCM_CSCMR1: 42781182e1SJean-Christophe Dubois return "CSCMR1"; 43781182e1SJean-Christophe Dubois case CCM_CSCMR2: 44781182e1SJean-Christophe Dubois return "CSCMR2"; 45781182e1SJean-Christophe Dubois case CCM_CSCDR1: 46781182e1SJean-Christophe Dubois return "CSCDR1"; 47781182e1SJean-Christophe Dubois case CCM_CS1CDR: 48781182e1SJean-Christophe Dubois return "CS1CDR"; 49781182e1SJean-Christophe Dubois case CCM_CS2CDR: 50781182e1SJean-Christophe Dubois return "CS2CDR"; 51781182e1SJean-Christophe Dubois case CCM_CDCDR: 52781182e1SJean-Christophe Dubois return "CDCDR"; 53781182e1SJean-Christophe Dubois case CCM_CHSCCDR: 54781182e1SJean-Christophe Dubois return "CHSCCDR"; 55781182e1SJean-Christophe Dubois case CCM_CSCDR2: 56781182e1SJean-Christophe Dubois return "CSCDR2"; 57781182e1SJean-Christophe Dubois case CCM_CSCDR3: 58781182e1SJean-Christophe Dubois return "CSCDR3"; 59781182e1SJean-Christophe Dubois case CCM_CDHIPR: 60781182e1SJean-Christophe Dubois return "CDHIPR"; 61781182e1SJean-Christophe Dubois case CCM_CTOR: 62781182e1SJean-Christophe Dubois return "CTOR"; 63781182e1SJean-Christophe Dubois case CCM_CLPCR: 64781182e1SJean-Christophe Dubois return "CLPCR"; 65781182e1SJean-Christophe Dubois case CCM_CISR: 66781182e1SJean-Christophe Dubois return "CISR"; 67781182e1SJean-Christophe Dubois case CCM_CIMR: 68781182e1SJean-Christophe Dubois return "CIMR"; 69781182e1SJean-Christophe Dubois case CCM_CCOSR: 70781182e1SJean-Christophe Dubois return "CCOSR"; 71781182e1SJean-Christophe Dubois case CCM_CGPR: 72781182e1SJean-Christophe Dubois return "CGPR"; 73781182e1SJean-Christophe Dubois case CCM_CCGR0: 74781182e1SJean-Christophe Dubois return "CCGR0"; 75781182e1SJean-Christophe Dubois case CCM_CCGR1: 76781182e1SJean-Christophe Dubois return "CCGR1"; 77781182e1SJean-Christophe Dubois case CCM_CCGR2: 78781182e1SJean-Christophe Dubois return "CCGR2"; 79781182e1SJean-Christophe Dubois case CCM_CCGR3: 80781182e1SJean-Christophe Dubois return "CCGR3"; 81781182e1SJean-Christophe Dubois case CCM_CCGR4: 82781182e1SJean-Christophe Dubois return "CCGR4"; 83781182e1SJean-Christophe Dubois case CCM_CCGR5: 84781182e1SJean-Christophe Dubois return "CCGR5"; 85781182e1SJean-Christophe Dubois case CCM_CCGR6: 86781182e1SJean-Christophe Dubois return "CCGR6"; 87781182e1SJean-Christophe Dubois case CCM_CMEOR: 88781182e1SJean-Christophe Dubois return "CMEOR"; 89781182e1SJean-Christophe Dubois default: 90781182e1SJean-Christophe Dubois sprintf(unknown, "%d ?", reg); 91781182e1SJean-Christophe Dubois return unknown; 92781182e1SJean-Christophe Dubois } 93781182e1SJean-Christophe Dubois } 94781182e1SJean-Christophe Dubois 95781182e1SJean-Christophe Dubois static const char *imx6ul_analog_reg_name(uint32_t reg) 96781182e1SJean-Christophe Dubois { 97781182e1SJean-Christophe Dubois static char unknown[20]; 98781182e1SJean-Christophe Dubois 99781182e1SJean-Christophe Dubois switch (reg) { 100781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM: 101781182e1SJean-Christophe Dubois return "PLL_ARM"; 102781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 103781182e1SJean-Christophe Dubois return "PLL_ARM_SET"; 104781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 105781182e1SJean-Christophe Dubois return "PLL_ARM_CLR"; 106781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 107781182e1SJean-Christophe Dubois return "PLL_ARM_TOG"; 108781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1: 109781182e1SJean-Christophe Dubois return "PLL_USB1"; 110781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 111781182e1SJean-Christophe Dubois return "PLL_USB1_SET"; 112781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 113781182e1SJean-Christophe Dubois return "PLL_USB1_CLR"; 114781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 115781182e1SJean-Christophe Dubois return "PLL_USB1_TOG"; 116781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2: 117781182e1SJean-Christophe Dubois return "PLL_USB2"; 118781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 119781182e1SJean-Christophe Dubois return "PLL_USB2_SET"; 120781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 121781182e1SJean-Christophe Dubois return "PLL_USB2_CLR"; 122781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 123781182e1SJean-Christophe Dubois return "PLL_USB2_TOG"; 124781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS: 125781182e1SJean-Christophe Dubois return "PLL_SYS"; 126781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 127781182e1SJean-Christophe Dubois return "PLL_SYS_SET"; 128781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 129781182e1SJean-Christophe Dubois return "PLL_SYS_CLR"; 130781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 131781182e1SJean-Christophe Dubois return "PLL_SYS_TOG"; 132781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SS: 133781182e1SJean-Christophe Dubois return "PLL_SYS_SS"; 134781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_NUM: 135781182e1SJean-Christophe Dubois return "PLL_SYS_NUM"; 136781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_DENOM: 137781182e1SJean-Christophe Dubois return "PLL_SYS_DENOM"; 138781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO: 139781182e1SJean-Christophe Dubois return "PLL_AUDIO"; 140781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 141781182e1SJean-Christophe Dubois return "PLL_AUDIO_SET"; 142781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 143781182e1SJean-Christophe Dubois return "PLL_AUDIO_CLR"; 144781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 145781182e1SJean-Christophe Dubois return "PLL_AUDIO_TOG"; 146781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_NUM: 147781182e1SJean-Christophe Dubois return "PLL_AUDIO_NUM"; 148781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_DENOM: 149781182e1SJean-Christophe Dubois return "PLL_AUDIO_DENOM"; 150781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO: 151781182e1SJean-Christophe Dubois return "PLL_VIDEO"; 152781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 153781182e1SJean-Christophe Dubois return "PLL_VIDEO_SET"; 154781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 155781182e1SJean-Christophe Dubois return "PLL_VIDEO_CLR"; 156781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 157781182e1SJean-Christophe Dubois return "PLL_VIDEO_TOG"; 158781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_NUM: 159781182e1SJean-Christophe Dubois return "PLL_VIDEO_NUM"; 160781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_DENOM: 161781182e1SJean-Christophe Dubois return "PLL_VIDEO_DENOM"; 162781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET: 163781182e1SJean-Christophe Dubois return "PLL_ENET"; 164781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 165781182e1SJean-Christophe Dubois return "PLL_ENET_SET"; 166781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 167781182e1SJean-Christophe Dubois return "PLL_ENET_CLR"; 168781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 169781182e1SJean-Christophe Dubois return "PLL_ENET_TOG"; 170781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480: 171781182e1SJean-Christophe Dubois return "PFD_480"; 172781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 173781182e1SJean-Christophe Dubois return "PFD_480_SET"; 174781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 175781182e1SJean-Christophe Dubois return "PFD_480_CLR"; 176781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 177781182e1SJean-Christophe Dubois return "PFD_480_TOG"; 178781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528: 179781182e1SJean-Christophe Dubois return "PFD_528"; 180781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 181781182e1SJean-Christophe Dubois return "PFD_528_SET"; 182781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 183781182e1SJean-Christophe Dubois return "PFD_528_CLR"; 184781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 185781182e1SJean-Christophe Dubois return "PFD_528_TOG"; 186781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0: 187781182e1SJean-Christophe Dubois return "MISC0"; 188781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 189781182e1SJean-Christophe Dubois return "MISC0_SET"; 190781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 191781182e1SJean-Christophe Dubois return "MISC0_CLR"; 192781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 193781182e1SJean-Christophe Dubois return "MISC0_TOG"; 194781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2: 195781182e1SJean-Christophe Dubois return "MISC2"; 196781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 197781182e1SJean-Christophe Dubois return "MISC2_SET"; 198781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 199781182e1SJean-Christophe Dubois return "MISC2_CLR"; 200781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 201781182e1SJean-Christophe Dubois return "MISC2_TOG"; 202781182e1SJean-Christophe Dubois case PMU_REG_1P1: 203781182e1SJean-Christophe Dubois return "PMU_REG_1P1"; 204781182e1SJean-Christophe Dubois case PMU_REG_3P0: 205781182e1SJean-Christophe Dubois return "PMU_REG_3P0"; 206781182e1SJean-Christophe Dubois case PMU_REG_2P5: 207781182e1SJean-Christophe Dubois return "PMU_REG_2P5"; 208781182e1SJean-Christophe Dubois case PMU_REG_CORE: 209781182e1SJean-Christophe Dubois return "PMU_REG_CORE"; 210781182e1SJean-Christophe Dubois case PMU_MISC1: 211781182e1SJean-Christophe Dubois return "PMU_MISC1"; 212781182e1SJean-Christophe Dubois case PMU_MISC1_SET: 213781182e1SJean-Christophe Dubois return "PMU_MISC1_SET"; 214781182e1SJean-Christophe Dubois case PMU_MISC1_CLR: 215781182e1SJean-Christophe Dubois return "PMU_MISC1_CLR"; 216781182e1SJean-Christophe Dubois case PMU_MISC1_TOG: 217781182e1SJean-Christophe Dubois return "PMU_MISC1_TOG"; 218781182e1SJean-Christophe Dubois case USB_ANALOG_DIGPROG: 219781182e1SJean-Christophe Dubois return "USB_ANALOG_DIGPROG"; 220781182e1SJean-Christophe Dubois default: 221781182e1SJean-Christophe Dubois sprintf(unknown, "%d ?", reg); 222781182e1SJean-Christophe Dubois return unknown; 223781182e1SJean-Christophe Dubois } 224781182e1SJean-Christophe Dubois } 225781182e1SJean-Christophe Dubois 226781182e1SJean-Christophe Dubois #define CKIH_FREQ 24000000 /* 24MHz crystal input */ 227781182e1SJean-Christophe Dubois 228781182e1SJean-Christophe Dubois static const VMStateDescription vmstate_imx6ul_ccm = { 229781182e1SJean-Christophe Dubois .name = TYPE_IMX6UL_CCM, 230781182e1SJean-Christophe Dubois .version_id = 1, 231781182e1SJean-Christophe Dubois .minimum_version_id = 1, 232781182e1SJean-Christophe Dubois .fields = (VMStateField[]) { 233781182e1SJean-Christophe Dubois VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX), 234781182e1SJean-Christophe Dubois VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX), 235781182e1SJean-Christophe Dubois VMSTATE_END_OF_LIST() 236781182e1SJean-Christophe Dubois }, 237781182e1SJean-Christophe Dubois }; 238781182e1SJean-Christophe Dubois 239781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev) 240781182e1SJean-Christophe Dubois { 241781182e1SJean-Christophe Dubois uint64_t freq = CKIH_FREQ; 242781182e1SJean-Christophe Dubois 243781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 244781182e1SJean-Christophe Dubois 245781182e1SJean-Christophe Dubois return freq; 246781182e1SJean-Christophe Dubois } 247781182e1SJean-Christophe Dubois 248781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev) 249781182e1SJean-Christophe Dubois { 250781182e1SJean-Christophe Dubois uint64_t freq = imx6ul_analog_get_osc_clk(dev); 251781182e1SJean-Christophe Dubois 252781182e1SJean-Christophe Dubois if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS], 253781182e1SJean-Christophe Dubois ANALOG_PLL_SYS, DIV_SELECT)) { 254781182e1SJean-Christophe Dubois freq *= 22; 255781182e1SJean-Christophe Dubois } else { 256781182e1SJean-Christophe Dubois freq *= 20; 257781182e1SJean-Christophe Dubois } 258781182e1SJean-Christophe Dubois 259781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 260781182e1SJean-Christophe Dubois 261781182e1SJean-Christophe Dubois return freq; 262781182e1SJean-Christophe Dubois } 263781182e1SJean-Christophe Dubois 264781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev) 265781182e1SJean-Christophe Dubois { 266781182e1SJean-Christophe Dubois uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20; 267781182e1SJean-Christophe Dubois 268781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 269781182e1SJean-Christophe Dubois 270781182e1SJean-Christophe Dubois return freq; 271781182e1SJean-Christophe Dubois } 272781182e1SJean-Christophe Dubois 273781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev) 274781182e1SJean-Christophe Dubois { 275781182e1SJean-Christophe Dubois uint64_t freq = 0; 276781182e1SJean-Christophe Dubois 277781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_clk(dev) * 18 278781182e1SJean-Christophe Dubois / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528], 279781182e1SJean-Christophe Dubois ANALOG_PFD_528, PFD0_FRAC); 280781182e1SJean-Christophe Dubois 281781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 282781182e1SJean-Christophe Dubois 283781182e1SJean-Christophe Dubois return freq; 284781182e1SJean-Christophe Dubois } 285781182e1SJean-Christophe Dubois 286781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev) 287781182e1SJean-Christophe Dubois { 288781182e1SJean-Christophe Dubois uint64_t freq = 0; 289781182e1SJean-Christophe Dubois 290781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_clk(dev) * 18 291781182e1SJean-Christophe Dubois / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528], 292781182e1SJean-Christophe Dubois ANALOG_PFD_528, PFD2_FRAC); 293781182e1SJean-Christophe Dubois 294781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 295781182e1SJean-Christophe Dubois 296781182e1SJean-Christophe Dubois return freq; 297781182e1SJean-Christophe Dubois } 298781182e1SJean-Christophe Dubois 299781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev) 300781182e1SJean-Christophe Dubois { 301781182e1SJean-Christophe Dubois uint64_t freq = 0; 302781182e1SJean-Christophe Dubois 303781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 304781182e1SJean-Christophe Dubois 305781182e1SJean-Christophe Dubois return freq; 306781182e1SJean-Christophe Dubois } 307781182e1SJean-Christophe Dubois 308781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev) 309781182e1SJean-Christophe Dubois { 310781182e1SJean-Christophe Dubois uint64_t freq = 0; 311781182e1SJean-Christophe Dubois 312781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) { 313781182e1SJean-Christophe Dubois case 0: 314781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll3_clk(dev); 315781182e1SJean-Christophe Dubois break; 316781182e1SJean-Christophe Dubois case 1: 317781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_osc_clk(dev); 318781182e1SJean-Christophe Dubois break; 319781182e1SJean-Christophe Dubois case 2: 320781182e1SJean-Christophe Dubois freq = imx6ul_analog_pll2_bypass_clk(dev); 321781182e1SJean-Christophe Dubois break; 322781182e1SJean-Christophe Dubois case 3: 323781182e1SJean-Christophe Dubois /* We should never get there as 3 is a reserved value */ 324781182e1SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, 325781182e1SJean-Christophe Dubois "[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n", 326781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM, __func__); 327781182e1SJean-Christophe Dubois /* freq is set to 0 as we don't know what it should be */ 328781182e1SJean-Christophe Dubois break; 329781182e1SJean-Christophe Dubois default: 330781182e1SJean-Christophe Dubois g_assert_not_reached(); 331781182e1SJean-Christophe Dubois } 332781182e1SJean-Christophe Dubois 333781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 334781182e1SJean-Christophe Dubois 335781182e1SJean-Christophe Dubois return freq; 336781182e1SJean-Christophe Dubois } 337781182e1SJean-Christophe Dubois 338781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev) 339781182e1SJean-Christophe Dubois { 340781182e1SJean-Christophe Dubois uint64_t freq = 0; 341781182e1SJean-Christophe Dubois 342781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) { 343781182e1SJean-Christophe Dubois case 0: 344781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_clk(dev); 345781182e1SJean-Christophe Dubois break; 346781182e1SJean-Christophe Dubois case 1: 347781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_pfd2_clk(dev); 348781182e1SJean-Christophe Dubois break; 349781182e1SJean-Christophe Dubois case 2: 350781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_pfd0_clk(dev); 351781182e1SJean-Christophe Dubois break; 352781182e1SJean-Christophe Dubois case 3: 353781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2; 354781182e1SJean-Christophe Dubois break; 355781182e1SJean-Christophe Dubois default: 356781182e1SJean-Christophe Dubois g_assert_not_reached(); 357781182e1SJean-Christophe Dubois } 358781182e1SJean-Christophe Dubois 359781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 360781182e1SJean-Christophe Dubois 361781182e1SJean-Christophe Dubois return freq; 362781182e1SJean-Christophe Dubois } 363781182e1SJean-Christophe Dubois 364781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev) 365781182e1SJean-Christophe Dubois { 366781182e1SJean-Christophe Dubois uint64_t freq = 0; 367781182e1SJean-Christophe Dubois 368781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev) 369781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF)); 370781182e1SJean-Christophe Dubois 371781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 372781182e1SJean-Christophe Dubois 373781182e1SJean-Christophe Dubois return freq; 374781182e1SJean-Christophe Dubois } 375781182e1SJean-Christophe Dubois 376781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev) 377781182e1SJean-Christophe Dubois { 378781182e1SJean-Christophe Dubois uint64_t freq = 0; 379781182e1SJean-Christophe Dubois 380781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) { 381781182e1SJean-Christophe Dubois case 0: 382781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_clk_sel_clk(dev); 383781182e1SJean-Christophe Dubois break; 384781182e1SJean-Christophe Dubois case 1: 385781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_clk2_clk(dev); 386781182e1SJean-Christophe Dubois break; 387781182e1SJean-Christophe Dubois default: 388781182e1SJean-Christophe Dubois g_assert_not_reached(); 389781182e1SJean-Christophe Dubois } 390781182e1SJean-Christophe Dubois 391781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 392781182e1SJean-Christophe Dubois 393781182e1SJean-Christophe Dubois return freq; 394781182e1SJean-Christophe Dubois } 395781182e1SJean-Christophe Dubois 396781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev) 397781182e1SJean-Christophe Dubois { 398781182e1SJean-Christophe Dubois uint64_t freq = 0; 399781182e1SJean-Christophe Dubois 400781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_sel_clk(dev) 401781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF)); 402781182e1SJean-Christophe Dubois 403781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 404781182e1SJean-Christophe Dubois 405781182e1SJean-Christophe Dubois return freq; 406781182e1SJean-Christophe Dubois } 407781182e1SJean-Christophe Dubois 408781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev) 409781182e1SJean-Christophe Dubois { 410781182e1SJean-Christophe Dubois uint64_t freq = 0; 411781182e1SJean-Christophe Dubois 412781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_ahb_clk(dev) 413781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF)); 414781182e1SJean-Christophe Dubois 415781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 416781182e1SJean-Christophe Dubois 417781182e1SJean-Christophe Dubois return freq; 418781182e1SJean-Christophe Dubois } 419781182e1SJean-Christophe Dubois 420781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev) 421781182e1SJean-Christophe Dubois { 422781182e1SJean-Christophe Dubois uint64_t freq = 0; 423781182e1SJean-Christophe Dubois 424781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) { 425781182e1SJean-Christophe Dubois case 0: 426781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_ipg_clk(dev); 427781182e1SJean-Christophe Dubois break; 428781182e1SJean-Christophe Dubois case 1: 429781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_osc_clk(dev); 430781182e1SJean-Christophe Dubois break; 431781182e1SJean-Christophe Dubois default: 432781182e1SJean-Christophe Dubois g_assert_not_reached(); 433781182e1SJean-Christophe Dubois } 434781182e1SJean-Christophe Dubois 435781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 436781182e1SJean-Christophe Dubois 437781182e1SJean-Christophe Dubois return freq; 438781182e1SJean-Christophe Dubois } 439781182e1SJean-Christophe Dubois 440781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev) 441781182e1SJean-Christophe Dubois { 442781182e1SJean-Christophe Dubois uint64_t freq = 0; 443781182e1SJean-Christophe Dubois 444781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_per_sel_clk(dev) 445781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF)); 446781182e1SJean-Christophe Dubois 447781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 448781182e1SJean-Christophe Dubois 449781182e1SJean-Christophe Dubois return freq; 450781182e1SJean-Christophe Dubois } 451781182e1SJean-Christophe Dubois 452781182e1SJean-Christophe Dubois static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) 453781182e1SJean-Christophe Dubois { 454781182e1SJean-Christophe Dubois uint32_t freq = 0; 455781182e1SJean-Christophe Dubois IMX6ULCCMState *s = IMX6UL_CCM(dev); 456781182e1SJean-Christophe Dubois 457781182e1SJean-Christophe Dubois switch (clock) { 458781182e1SJean-Christophe Dubois case CLK_NONE: 459781182e1SJean-Christophe Dubois break; 460781182e1SJean-Christophe Dubois case CLK_IPG: 461781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_ipg_clk(s); 462781182e1SJean-Christophe Dubois break; 463781182e1SJean-Christophe Dubois case CLK_IPG_HIGH: 464781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_per_clk(s); 465781182e1SJean-Christophe Dubois break; 466781182e1SJean-Christophe Dubois case CLK_32k: 467781182e1SJean-Christophe Dubois freq = CKIL_FREQ; 468781182e1SJean-Christophe Dubois break; 469781182e1SJean-Christophe Dubois case CLK_HIGH: 470781182e1SJean-Christophe Dubois freq = CKIH_FREQ; 471781182e1SJean-Christophe Dubois break; 472781182e1SJean-Christophe Dubois case CLK_HIGH_DIV: 473781182e1SJean-Christophe Dubois freq = CKIH_FREQ / 8; 474781182e1SJean-Christophe Dubois break; 475781182e1SJean-Christophe Dubois default: 476781182e1SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", 477781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM, __func__, clock); 478781182e1SJean-Christophe Dubois break; 479781182e1SJean-Christophe Dubois } 480781182e1SJean-Christophe Dubois 481781182e1SJean-Christophe Dubois trace_ccm_clock_freq(clock, freq); 482781182e1SJean-Christophe Dubois 483781182e1SJean-Christophe Dubois return freq; 484781182e1SJean-Christophe Dubois } 485781182e1SJean-Christophe Dubois 486781182e1SJean-Christophe Dubois static void imx6ul_ccm_reset(DeviceState *dev) 487781182e1SJean-Christophe Dubois { 488781182e1SJean-Christophe Dubois IMX6ULCCMState *s = IMX6UL_CCM(dev); 489781182e1SJean-Christophe Dubois 490781182e1SJean-Christophe Dubois trace_ccm_entry(); 491781182e1SJean-Christophe Dubois 492781182e1SJean-Christophe Dubois s->ccm[CCM_CCR] = 0x0401167F; 493781182e1SJean-Christophe Dubois s->ccm[CCM_CCDR] = 0x00000000; 494781182e1SJean-Christophe Dubois s->ccm[CCM_CSR] = 0x00000010; 495781182e1SJean-Christophe Dubois s->ccm[CCM_CCSR] = 0x00000100; 496781182e1SJean-Christophe Dubois s->ccm[CCM_CACRR] = 0x00000000; 497781182e1SJean-Christophe Dubois s->ccm[CCM_CBCDR] = 0x00018D00; 498781182e1SJean-Christophe Dubois s->ccm[CCM_CBCMR] = 0x24860324; 499781182e1SJean-Christophe Dubois s->ccm[CCM_CSCMR1] = 0x04900080; 500781182e1SJean-Christophe Dubois s->ccm[CCM_CSCMR2] = 0x03192F06; 501781182e1SJean-Christophe Dubois s->ccm[CCM_CSCDR1] = 0x00490B00; 502781182e1SJean-Christophe Dubois s->ccm[CCM_CS1CDR] = 0x0EC102C1; 503781182e1SJean-Christophe Dubois s->ccm[CCM_CS2CDR] = 0x000336C1; 504781182e1SJean-Christophe Dubois s->ccm[CCM_CDCDR] = 0x33F71F92; 505781182e1SJean-Christophe Dubois s->ccm[CCM_CHSCCDR] = 0x000248A4; 506781182e1SJean-Christophe Dubois s->ccm[CCM_CSCDR2] = 0x00029B48; 507781182e1SJean-Christophe Dubois s->ccm[CCM_CSCDR3] = 0x00014841; 508781182e1SJean-Christophe Dubois s->ccm[CCM_CDHIPR] = 0x00000000; 509781182e1SJean-Christophe Dubois s->ccm[CCM_CTOR] = 0x00000000; 510781182e1SJean-Christophe Dubois s->ccm[CCM_CLPCR] = 0x00000079; 511781182e1SJean-Christophe Dubois s->ccm[CCM_CISR] = 0x00000000; 512781182e1SJean-Christophe Dubois s->ccm[CCM_CIMR] = 0xFFFFFFFF; 513781182e1SJean-Christophe Dubois s->ccm[CCM_CCOSR] = 0x000A0001; 514781182e1SJean-Christophe Dubois s->ccm[CCM_CGPR] = 0x0000FE62; 515781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR0] = 0xFFFFFFFF; 516781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR1] = 0xFFFFFFFF; 517781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR2] = 0xFC3FFFFF; 518781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR3] = 0xFFFFFFFF; 519781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR4] = 0xFFFFFFFF; 520781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR5] = 0xFFFFFFFF; 521781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR6] = 0xFFFFFFFF; 522781182e1SJean-Christophe Dubois s->ccm[CCM_CMEOR] = 0xFFFFFFFF; 523781182e1SJean-Christophe Dubois 524781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063; 525781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000; 526781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000; 527781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001; 528781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000; 529781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000; 530781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012; 531781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006; 532781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100; 533781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C; 534781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C; 535781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100; 536781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447; 537781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001; 538781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PFD_480] = 0x1311100C; 539781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PFD_528] = 0x1018101B; 540781182e1SJean-Christophe Dubois 541781182e1SJean-Christophe Dubois s->analog[PMU_REG_1P1] = 0x00001073; 542781182e1SJean-Christophe Dubois s->analog[PMU_REG_3P0] = 0x00000F74; 543781182e1SJean-Christophe Dubois s->analog[PMU_REG_2P5] = 0x00001073; 544781182e1SJean-Christophe Dubois s->analog[PMU_REG_CORE] = 0x00482012; 545781182e1SJean-Christophe Dubois s->analog[PMU_MISC0] = 0x04000000; 546781182e1SJean-Christophe Dubois s->analog[PMU_MISC1] = 0x00000000; 547781182e1SJean-Christophe Dubois s->analog[PMU_MISC2] = 0x00272727; 548781182e1SJean-Christophe Dubois s->analog[PMU_LOWPWR_CTRL] = 0x00004009; 549781182e1SJean-Christophe Dubois 550781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004; 551781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000; 552781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000; 553781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000; 554781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_MISC] = 0x00000002; 555781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004; 556781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000; 557781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB2_MISC] = 0x00000002; 558781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_DIGPROG] = 0x00640000; 559781182e1SJean-Christophe Dubois 560781182e1SJean-Christophe Dubois /* all PLLs need to be locked */ 561781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK; 562781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK; 563781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK; 564781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK; 565781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK; 566781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK; 567781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK; 568781182e1SJean-Christophe Dubois 569781182e1SJean-Christophe Dubois s->analog[TEMPMON_TEMPSENSE0] = 0x00000001; 570781182e1SJean-Christophe Dubois s->analog[TEMPMON_TEMPSENSE1] = 0x00000001; 571781182e1SJean-Christophe Dubois s->analog[TEMPMON_TEMPSENSE2] = 0x00000000; 572781182e1SJean-Christophe Dubois } 573781182e1SJean-Christophe Dubois 574781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size) 575781182e1SJean-Christophe Dubois { 576781182e1SJean-Christophe Dubois uint32_t value = 0; 577781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 578781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 579781182e1SJean-Christophe Dubois 580781182e1SJean-Christophe Dubois assert(index < CCM_MAX); 581781182e1SJean-Christophe Dubois 582781182e1SJean-Christophe Dubois value = s->ccm[index]; 583781182e1SJean-Christophe Dubois 584781182e1SJean-Christophe Dubois trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value); 585781182e1SJean-Christophe Dubois 586781182e1SJean-Christophe Dubois return (uint64_t)value; 587781182e1SJean-Christophe Dubois } 588781182e1SJean-Christophe Dubois 589781182e1SJean-Christophe Dubois static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value, 590781182e1SJean-Christophe Dubois unsigned size) 591781182e1SJean-Christophe Dubois { 592781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 593781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 594781182e1SJean-Christophe Dubois 595781182e1SJean-Christophe Dubois assert(index < CCM_MAX); 596781182e1SJean-Christophe Dubois 597781182e1SJean-Christophe Dubois trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value); 598781182e1SJean-Christophe Dubois 599781182e1SJean-Christophe Dubois /* 600781182e1SJean-Christophe Dubois * We will do a better implementation later. In particular some bits 601781182e1SJean-Christophe Dubois * cannot be written to. 602781182e1SJean-Christophe Dubois */ 603781182e1SJean-Christophe Dubois s->ccm[index] = (uint32_t)value; 604781182e1SJean-Christophe Dubois } 605781182e1SJean-Christophe Dubois 606781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size) 607781182e1SJean-Christophe Dubois { 608781182e1SJean-Christophe Dubois uint32_t value; 609781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 610781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 611781182e1SJean-Christophe Dubois 612781182e1SJean-Christophe Dubois assert(index < CCM_ANALOG_MAX); 613781182e1SJean-Christophe Dubois 614781182e1SJean-Christophe Dubois switch (index) { 615781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 616781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 617781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 618781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 619781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 620781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 621781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 622781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 623781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 624781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 625781182e1SJean-Christophe Dubois case PMU_MISC1_SET: 626781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 627781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_SET: 628781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_SET: 629781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_SET: 630781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_SET: 631781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_SET: 632781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_SET: 633781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE0_SET: 634781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE1_SET: 635781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE2_SET: 636781182e1SJean-Christophe Dubois /* 637781182e1SJean-Christophe Dubois * All REG_NAME_SET register access are in fact targeting 638781182e1SJean-Christophe Dubois * the REG_NAME register. 639781182e1SJean-Christophe Dubois */ 640781182e1SJean-Christophe Dubois value = s->analog[index - 1]; 641781182e1SJean-Christophe Dubois break; 642781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 643781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 644781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 645781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 646781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 647781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 648781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 649781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 650781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 651781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 652781182e1SJean-Christophe Dubois case PMU_MISC1_CLR: 653781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 654781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_CLR: 655781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_CLR: 656781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_CLR: 657781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_CLR: 658781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_CLR: 659781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_CLR: 660781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE0_CLR: 661781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE1_CLR: 662781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE2_CLR: 663781182e1SJean-Christophe Dubois /* 664781182e1SJean-Christophe Dubois * All REG_NAME_CLR register access are in fact targeting 665781182e1SJean-Christophe Dubois * the REG_NAME register. 666781182e1SJean-Christophe Dubois */ 667781182e1SJean-Christophe Dubois value = s->analog[index - 2]; 668781182e1SJean-Christophe Dubois break; 669781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 670781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 671781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 672781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 673781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 674781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 675781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 676781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 677781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 678781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 679781182e1SJean-Christophe Dubois case PMU_MISC1_TOG: 680781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 681781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_TOG: 682781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_TOG: 683781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_TOG: 684781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_TOG: 685781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_TOG: 686781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_TOG: 687781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE0_TOG: 688781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE1_TOG: 689781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE2_TOG: 690781182e1SJean-Christophe Dubois /* 691781182e1SJean-Christophe Dubois * All REG_NAME_TOG register access are in fact targeting 692781182e1SJean-Christophe Dubois * the REG_NAME register. 693781182e1SJean-Christophe Dubois */ 694781182e1SJean-Christophe Dubois value = s->analog[index - 3]; 695781182e1SJean-Christophe Dubois break; 696781182e1SJean-Christophe Dubois default: 697781182e1SJean-Christophe Dubois value = s->analog[index]; 698781182e1SJean-Christophe Dubois break; 699781182e1SJean-Christophe Dubois } 700781182e1SJean-Christophe Dubois 701781182e1SJean-Christophe Dubois trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value); 702781182e1SJean-Christophe Dubois 703781182e1SJean-Christophe Dubois return (uint64_t)value; 704781182e1SJean-Christophe Dubois } 705781182e1SJean-Christophe Dubois 706781182e1SJean-Christophe Dubois static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value, 707781182e1SJean-Christophe Dubois unsigned size) 708781182e1SJean-Christophe Dubois { 709781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 710781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 711781182e1SJean-Christophe Dubois 712781182e1SJean-Christophe Dubois assert(index < CCM_ANALOG_MAX); 713781182e1SJean-Christophe Dubois 714781182e1SJean-Christophe Dubois trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value); 715781182e1SJean-Christophe Dubois 716781182e1SJean-Christophe Dubois switch (index) { 717781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 718781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 719781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 720781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 721781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 722781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 723781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 724781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 725781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 726781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 727781182e1SJean-Christophe Dubois case PMU_MISC1_SET: 728781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 729781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_SET: 730781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_SET: 731781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_SET: 732781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_SET: 733781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_SET: 734781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_SET: 735781182e1SJean-Christophe Dubois /* 736781182e1SJean-Christophe Dubois * All REG_NAME_SET register access are in fact targeting 737781182e1SJean-Christophe Dubois * the REG_NAME register. So we change the value of the 738781182e1SJean-Christophe Dubois * REG_NAME register, setting bits passed in the value. 739781182e1SJean-Christophe Dubois */ 740781182e1SJean-Christophe Dubois s->analog[index - 1] |= value; 741781182e1SJean-Christophe Dubois break; 742781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 743781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 744781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 745781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 746781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 747781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 748781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 749781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 750781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 751781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 752781182e1SJean-Christophe Dubois case PMU_MISC1_CLR: 753781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 754781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_CLR: 755781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_CLR: 756781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_CLR: 757781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_CLR: 758781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_CLR: 759781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_CLR: 760781182e1SJean-Christophe Dubois /* 761781182e1SJean-Christophe Dubois * All REG_NAME_CLR register access are in fact targeting 762781182e1SJean-Christophe Dubois * the REG_NAME register. So we change the value of the 763781182e1SJean-Christophe Dubois * REG_NAME register, unsetting bits passed in the value. 764781182e1SJean-Christophe Dubois */ 765781182e1SJean-Christophe Dubois s->analog[index - 2] &= ~value; 766781182e1SJean-Christophe Dubois break; 767781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 768781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 769781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 770781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 771781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 772781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 773781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 774781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 775781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 776781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 777781182e1SJean-Christophe Dubois case PMU_MISC1_TOG: 778781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 779781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_TOG: 780781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_TOG: 781781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_TOG: 782781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_TOG: 783781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_TOG: 784781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_TOG: 785781182e1SJean-Christophe Dubois /* 786781182e1SJean-Christophe Dubois * All REG_NAME_TOG register access are in fact targeting 787781182e1SJean-Christophe Dubois * the REG_NAME register. So we change the value of the 788781182e1SJean-Christophe Dubois * REG_NAME register, toggling bits passed in the value. 789781182e1SJean-Christophe Dubois */ 790781182e1SJean-Christophe Dubois s->analog[index - 3] ^= value; 791781182e1SJean-Christophe Dubois break; 792781182e1SJean-Christophe Dubois default: 793781182e1SJean-Christophe Dubois /* 794781182e1SJean-Christophe Dubois * We will do a better implementation later. In particular some bits 795781182e1SJean-Christophe Dubois * cannot be written to. 796781182e1SJean-Christophe Dubois */ 797781182e1SJean-Christophe Dubois s->analog[index] = value; 798781182e1SJean-Christophe Dubois break; 799781182e1SJean-Christophe Dubois } 800781182e1SJean-Christophe Dubois } 801781182e1SJean-Christophe Dubois 802781182e1SJean-Christophe Dubois static const struct MemoryRegionOps imx6ul_ccm_ops = { 803781182e1SJean-Christophe Dubois .read = imx6ul_ccm_read, 804781182e1SJean-Christophe Dubois .write = imx6ul_ccm_write, 805781182e1SJean-Christophe Dubois .endianness = DEVICE_NATIVE_ENDIAN, 806781182e1SJean-Christophe Dubois .valid = { 807781182e1SJean-Christophe Dubois /* 808781182e1SJean-Christophe Dubois * Our device would not work correctly if the guest was doing 809781182e1SJean-Christophe Dubois * unaligned access. This might not be a limitation on the real 810781182e1SJean-Christophe Dubois * device but in practice there is no reason for a guest to access 811781182e1SJean-Christophe Dubois * this device unaligned. 812781182e1SJean-Christophe Dubois */ 813781182e1SJean-Christophe Dubois .min_access_size = 4, 814781182e1SJean-Christophe Dubois .max_access_size = 4, 815781182e1SJean-Christophe Dubois .unaligned = false, 816781182e1SJean-Christophe Dubois }, 817781182e1SJean-Christophe Dubois }; 818781182e1SJean-Christophe Dubois 819781182e1SJean-Christophe Dubois static const struct MemoryRegionOps imx6ul_analog_ops = { 820781182e1SJean-Christophe Dubois .read = imx6ul_analog_read, 821781182e1SJean-Christophe Dubois .write = imx6ul_analog_write, 822781182e1SJean-Christophe Dubois .endianness = DEVICE_NATIVE_ENDIAN, 823781182e1SJean-Christophe Dubois .valid = { 824781182e1SJean-Christophe Dubois /* 825781182e1SJean-Christophe Dubois * Our device would not work correctly if the guest was doing 826781182e1SJean-Christophe Dubois * unaligned access. This might not be a limitation on the real 827781182e1SJean-Christophe Dubois * device but in practice there is no reason for a guest to access 828781182e1SJean-Christophe Dubois * this device unaligned. 829781182e1SJean-Christophe Dubois */ 830781182e1SJean-Christophe Dubois .min_access_size = 4, 831781182e1SJean-Christophe Dubois .max_access_size = 4, 832781182e1SJean-Christophe Dubois .unaligned = false, 833781182e1SJean-Christophe Dubois }, 834781182e1SJean-Christophe Dubois }; 835781182e1SJean-Christophe Dubois 836781182e1SJean-Christophe Dubois static void imx6ul_ccm_init(Object *obj) 837781182e1SJean-Christophe Dubois { 838781182e1SJean-Christophe Dubois DeviceState *dev = DEVICE(obj); 839781182e1SJean-Christophe Dubois SysBusDevice *sd = SYS_BUS_DEVICE(obj); 840781182e1SJean-Christophe Dubois IMX6ULCCMState *s = IMX6UL_CCM(obj); 841781182e1SJean-Christophe Dubois 842781182e1SJean-Christophe Dubois /* initialize a container for the all memory range */ 843781182e1SJean-Christophe Dubois memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000); 844781182e1SJean-Christophe Dubois 845781182e1SJean-Christophe Dubois /* We initialize an IO memory region for the CCM part */ 846781182e1SJean-Christophe Dubois memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s, 847781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t)); 848781182e1SJean-Christophe Dubois 849781182e1SJean-Christophe Dubois /* Add the CCM as a subregion at offset 0 */ 850781182e1SJean-Christophe Dubois memory_region_add_subregion(&s->container, 0, &s->ioccm); 851781182e1SJean-Christophe Dubois 852781182e1SJean-Christophe Dubois /* We initialize an IO memory region for the ANALOG part */ 853781182e1SJean-Christophe Dubois memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s, 854781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM ".analog", 855781182e1SJean-Christophe Dubois CCM_ANALOG_MAX * sizeof(uint32_t)); 856781182e1SJean-Christophe Dubois 857781182e1SJean-Christophe Dubois /* Add the ANALOG as a subregion at offset 0x4000 */ 858781182e1SJean-Christophe Dubois memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog); 859781182e1SJean-Christophe Dubois 860781182e1SJean-Christophe Dubois sysbus_init_mmio(sd, &s->container); 861781182e1SJean-Christophe Dubois } 862781182e1SJean-Christophe Dubois 863781182e1SJean-Christophe Dubois static void imx6ul_ccm_class_init(ObjectClass *klass, void *data) 864781182e1SJean-Christophe Dubois { 865781182e1SJean-Christophe Dubois DeviceClass *dc = DEVICE_CLASS(klass); 866781182e1SJean-Christophe Dubois IMXCCMClass *ccm = IMX_CCM_CLASS(klass); 867781182e1SJean-Christophe Dubois 868781182e1SJean-Christophe Dubois dc->reset = imx6ul_ccm_reset; 869781182e1SJean-Christophe Dubois dc->vmsd = &vmstate_imx6ul_ccm; 870781182e1SJean-Christophe Dubois dc->desc = "i.MX6UL Clock Control Module"; 871781182e1SJean-Christophe Dubois 872781182e1SJean-Christophe Dubois ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency; 873781182e1SJean-Christophe Dubois } 874781182e1SJean-Christophe Dubois 875781182e1SJean-Christophe Dubois static const TypeInfo imx6ul_ccm_info = { 876781182e1SJean-Christophe Dubois .name = TYPE_IMX6UL_CCM, 877781182e1SJean-Christophe Dubois .parent = TYPE_IMX_CCM, 878781182e1SJean-Christophe Dubois .instance_size = sizeof(IMX6ULCCMState), 879781182e1SJean-Christophe Dubois .instance_init = imx6ul_ccm_init, 880781182e1SJean-Christophe Dubois .class_init = imx6ul_ccm_class_init, 881781182e1SJean-Christophe Dubois }; 882781182e1SJean-Christophe Dubois 883781182e1SJean-Christophe Dubois static void imx6ul_ccm_register_types(void) 884781182e1SJean-Christophe Dubois { 885781182e1SJean-Christophe Dubois type_register_static(&imx6ul_ccm_info); 886781182e1SJean-Christophe Dubois } 887781182e1SJean-Christophe Dubois 888781182e1SJean-Christophe Dubois type_init(imx6ul_ccm_register_types) 889