1*781182e1SJean-Christophe Dubois /* 2*781182e1SJean-Christophe Dubois * IMX6UL Clock Control Module 3*781182e1SJean-Christophe Dubois * 4*781182e1SJean-Christophe Dubois * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net> 5*781182e1SJean-Christophe Dubois * 6*781182e1SJean-Christophe Dubois * This work is licensed under the terms of the GNU GPL, version 2 or later. 7*781182e1SJean-Christophe Dubois * See the COPYING file in the top-level directory. 8*781182e1SJean-Christophe Dubois * 9*781182e1SJean-Christophe Dubois * To get the timer frequencies right, we need to emulate at least part of 10*781182e1SJean-Christophe Dubois * the CCM. 11*781182e1SJean-Christophe Dubois */ 12*781182e1SJean-Christophe Dubois 13*781182e1SJean-Christophe Dubois #include "qemu/osdep.h" 14*781182e1SJean-Christophe Dubois #include "hw/registerfields.h" 15*781182e1SJean-Christophe Dubois #include "hw/misc/imx6ul_ccm.h" 16*781182e1SJean-Christophe Dubois #include "qemu/log.h" 17*781182e1SJean-Christophe Dubois 18*781182e1SJean-Christophe Dubois #include "trace.h" 19*781182e1SJean-Christophe Dubois 20*781182e1SJean-Christophe Dubois static const char *imx6ul_ccm_reg_name(uint32_t reg) 21*781182e1SJean-Christophe Dubois { 22*781182e1SJean-Christophe Dubois static char unknown[20]; 23*781182e1SJean-Christophe Dubois 24*781182e1SJean-Christophe Dubois switch (reg) { 25*781182e1SJean-Christophe Dubois case CCM_CCR: 26*781182e1SJean-Christophe Dubois return "CCR"; 27*781182e1SJean-Christophe Dubois case CCM_CCDR: 28*781182e1SJean-Christophe Dubois return "CCDR"; 29*781182e1SJean-Christophe Dubois case CCM_CSR: 30*781182e1SJean-Christophe Dubois return "CSR"; 31*781182e1SJean-Christophe Dubois case CCM_CCSR: 32*781182e1SJean-Christophe Dubois return "CCSR"; 33*781182e1SJean-Christophe Dubois case CCM_CACRR: 34*781182e1SJean-Christophe Dubois return "CACRR"; 35*781182e1SJean-Christophe Dubois case CCM_CBCDR: 36*781182e1SJean-Christophe Dubois return "CBCDR"; 37*781182e1SJean-Christophe Dubois case CCM_CBCMR: 38*781182e1SJean-Christophe Dubois return "CBCMR"; 39*781182e1SJean-Christophe Dubois case CCM_CSCMR1: 40*781182e1SJean-Christophe Dubois return "CSCMR1"; 41*781182e1SJean-Christophe Dubois case CCM_CSCMR2: 42*781182e1SJean-Christophe Dubois return "CSCMR2"; 43*781182e1SJean-Christophe Dubois case CCM_CSCDR1: 44*781182e1SJean-Christophe Dubois return "CSCDR1"; 45*781182e1SJean-Christophe Dubois case CCM_CS1CDR: 46*781182e1SJean-Christophe Dubois return "CS1CDR"; 47*781182e1SJean-Christophe Dubois case CCM_CS2CDR: 48*781182e1SJean-Christophe Dubois return "CS2CDR"; 49*781182e1SJean-Christophe Dubois case CCM_CDCDR: 50*781182e1SJean-Christophe Dubois return "CDCDR"; 51*781182e1SJean-Christophe Dubois case CCM_CHSCCDR: 52*781182e1SJean-Christophe Dubois return "CHSCCDR"; 53*781182e1SJean-Christophe Dubois case CCM_CSCDR2: 54*781182e1SJean-Christophe Dubois return "CSCDR2"; 55*781182e1SJean-Christophe Dubois case CCM_CSCDR3: 56*781182e1SJean-Christophe Dubois return "CSCDR3"; 57*781182e1SJean-Christophe Dubois case CCM_CDHIPR: 58*781182e1SJean-Christophe Dubois return "CDHIPR"; 59*781182e1SJean-Christophe Dubois case CCM_CTOR: 60*781182e1SJean-Christophe Dubois return "CTOR"; 61*781182e1SJean-Christophe Dubois case CCM_CLPCR: 62*781182e1SJean-Christophe Dubois return "CLPCR"; 63*781182e1SJean-Christophe Dubois case CCM_CISR: 64*781182e1SJean-Christophe Dubois return "CISR"; 65*781182e1SJean-Christophe Dubois case CCM_CIMR: 66*781182e1SJean-Christophe Dubois return "CIMR"; 67*781182e1SJean-Christophe Dubois case CCM_CCOSR: 68*781182e1SJean-Christophe Dubois return "CCOSR"; 69*781182e1SJean-Christophe Dubois case CCM_CGPR: 70*781182e1SJean-Christophe Dubois return "CGPR"; 71*781182e1SJean-Christophe Dubois case CCM_CCGR0: 72*781182e1SJean-Christophe Dubois return "CCGR0"; 73*781182e1SJean-Christophe Dubois case CCM_CCGR1: 74*781182e1SJean-Christophe Dubois return "CCGR1"; 75*781182e1SJean-Christophe Dubois case CCM_CCGR2: 76*781182e1SJean-Christophe Dubois return "CCGR2"; 77*781182e1SJean-Christophe Dubois case CCM_CCGR3: 78*781182e1SJean-Christophe Dubois return "CCGR3"; 79*781182e1SJean-Christophe Dubois case CCM_CCGR4: 80*781182e1SJean-Christophe Dubois return "CCGR4"; 81*781182e1SJean-Christophe Dubois case CCM_CCGR5: 82*781182e1SJean-Christophe Dubois return "CCGR5"; 83*781182e1SJean-Christophe Dubois case CCM_CCGR6: 84*781182e1SJean-Christophe Dubois return "CCGR6"; 85*781182e1SJean-Christophe Dubois case CCM_CMEOR: 86*781182e1SJean-Christophe Dubois return "CMEOR"; 87*781182e1SJean-Christophe Dubois default: 88*781182e1SJean-Christophe Dubois sprintf(unknown, "%d ?", reg); 89*781182e1SJean-Christophe Dubois return unknown; 90*781182e1SJean-Christophe Dubois } 91*781182e1SJean-Christophe Dubois } 92*781182e1SJean-Christophe Dubois 93*781182e1SJean-Christophe Dubois static const char *imx6ul_analog_reg_name(uint32_t reg) 94*781182e1SJean-Christophe Dubois { 95*781182e1SJean-Christophe Dubois static char unknown[20]; 96*781182e1SJean-Christophe Dubois 97*781182e1SJean-Christophe Dubois switch (reg) { 98*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM: 99*781182e1SJean-Christophe Dubois return "PLL_ARM"; 100*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 101*781182e1SJean-Christophe Dubois return "PLL_ARM_SET"; 102*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 103*781182e1SJean-Christophe Dubois return "PLL_ARM_CLR"; 104*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 105*781182e1SJean-Christophe Dubois return "PLL_ARM_TOG"; 106*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1: 107*781182e1SJean-Christophe Dubois return "PLL_USB1"; 108*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 109*781182e1SJean-Christophe Dubois return "PLL_USB1_SET"; 110*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 111*781182e1SJean-Christophe Dubois return "PLL_USB1_CLR"; 112*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 113*781182e1SJean-Christophe Dubois return "PLL_USB1_TOG"; 114*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2: 115*781182e1SJean-Christophe Dubois return "PLL_USB2"; 116*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 117*781182e1SJean-Christophe Dubois return "PLL_USB2_SET"; 118*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 119*781182e1SJean-Christophe Dubois return "PLL_USB2_CLR"; 120*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 121*781182e1SJean-Christophe Dubois return "PLL_USB2_TOG"; 122*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS: 123*781182e1SJean-Christophe Dubois return "PLL_SYS"; 124*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 125*781182e1SJean-Christophe Dubois return "PLL_SYS_SET"; 126*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 127*781182e1SJean-Christophe Dubois return "PLL_SYS_CLR"; 128*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 129*781182e1SJean-Christophe Dubois return "PLL_SYS_TOG"; 130*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SS: 131*781182e1SJean-Christophe Dubois return "PLL_SYS_SS"; 132*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_NUM: 133*781182e1SJean-Christophe Dubois return "PLL_SYS_NUM"; 134*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_DENOM: 135*781182e1SJean-Christophe Dubois return "PLL_SYS_DENOM"; 136*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO: 137*781182e1SJean-Christophe Dubois return "PLL_AUDIO"; 138*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 139*781182e1SJean-Christophe Dubois return "PLL_AUDIO_SET"; 140*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 141*781182e1SJean-Christophe Dubois return "PLL_AUDIO_CLR"; 142*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 143*781182e1SJean-Christophe Dubois return "PLL_AUDIO_TOG"; 144*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_NUM: 145*781182e1SJean-Christophe Dubois return "PLL_AUDIO_NUM"; 146*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_DENOM: 147*781182e1SJean-Christophe Dubois return "PLL_AUDIO_DENOM"; 148*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO: 149*781182e1SJean-Christophe Dubois return "PLL_VIDEO"; 150*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 151*781182e1SJean-Christophe Dubois return "PLL_VIDEO_SET"; 152*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 153*781182e1SJean-Christophe Dubois return "PLL_VIDEO_CLR"; 154*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 155*781182e1SJean-Christophe Dubois return "PLL_VIDEO_TOG"; 156*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_NUM: 157*781182e1SJean-Christophe Dubois return "PLL_VIDEO_NUM"; 158*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_DENOM: 159*781182e1SJean-Christophe Dubois return "PLL_VIDEO_DENOM"; 160*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET: 161*781182e1SJean-Christophe Dubois return "PLL_ENET"; 162*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 163*781182e1SJean-Christophe Dubois return "PLL_ENET_SET"; 164*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 165*781182e1SJean-Christophe Dubois return "PLL_ENET_CLR"; 166*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 167*781182e1SJean-Christophe Dubois return "PLL_ENET_TOG"; 168*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480: 169*781182e1SJean-Christophe Dubois return "PFD_480"; 170*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 171*781182e1SJean-Christophe Dubois return "PFD_480_SET"; 172*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 173*781182e1SJean-Christophe Dubois return "PFD_480_CLR"; 174*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 175*781182e1SJean-Christophe Dubois return "PFD_480_TOG"; 176*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528: 177*781182e1SJean-Christophe Dubois return "PFD_528"; 178*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 179*781182e1SJean-Christophe Dubois return "PFD_528_SET"; 180*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 181*781182e1SJean-Christophe Dubois return "PFD_528_CLR"; 182*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 183*781182e1SJean-Christophe Dubois return "PFD_528_TOG"; 184*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0: 185*781182e1SJean-Christophe Dubois return "MISC0"; 186*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 187*781182e1SJean-Christophe Dubois return "MISC0_SET"; 188*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 189*781182e1SJean-Christophe Dubois return "MISC0_CLR"; 190*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 191*781182e1SJean-Christophe Dubois return "MISC0_TOG"; 192*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2: 193*781182e1SJean-Christophe Dubois return "MISC2"; 194*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 195*781182e1SJean-Christophe Dubois return "MISC2_SET"; 196*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 197*781182e1SJean-Christophe Dubois return "MISC2_CLR"; 198*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 199*781182e1SJean-Christophe Dubois return "MISC2_TOG"; 200*781182e1SJean-Christophe Dubois case PMU_REG_1P1: 201*781182e1SJean-Christophe Dubois return "PMU_REG_1P1"; 202*781182e1SJean-Christophe Dubois case PMU_REG_3P0: 203*781182e1SJean-Christophe Dubois return "PMU_REG_3P0"; 204*781182e1SJean-Christophe Dubois case PMU_REG_2P5: 205*781182e1SJean-Christophe Dubois return "PMU_REG_2P5"; 206*781182e1SJean-Christophe Dubois case PMU_REG_CORE: 207*781182e1SJean-Christophe Dubois return "PMU_REG_CORE"; 208*781182e1SJean-Christophe Dubois case PMU_MISC1: 209*781182e1SJean-Christophe Dubois return "PMU_MISC1"; 210*781182e1SJean-Christophe Dubois case PMU_MISC1_SET: 211*781182e1SJean-Christophe Dubois return "PMU_MISC1_SET"; 212*781182e1SJean-Christophe Dubois case PMU_MISC1_CLR: 213*781182e1SJean-Christophe Dubois return "PMU_MISC1_CLR"; 214*781182e1SJean-Christophe Dubois case PMU_MISC1_TOG: 215*781182e1SJean-Christophe Dubois return "PMU_MISC1_TOG"; 216*781182e1SJean-Christophe Dubois case USB_ANALOG_DIGPROG: 217*781182e1SJean-Christophe Dubois return "USB_ANALOG_DIGPROG"; 218*781182e1SJean-Christophe Dubois default: 219*781182e1SJean-Christophe Dubois sprintf(unknown, "%d ?", reg); 220*781182e1SJean-Christophe Dubois return unknown; 221*781182e1SJean-Christophe Dubois } 222*781182e1SJean-Christophe Dubois } 223*781182e1SJean-Christophe Dubois 224*781182e1SJean-Christophe Dubois #define CKIH_FREQ 24000000 /* 24MHz crystal input */ 225*781182e1SJean-Christophe Dubois 226*781182e1SJean-Christophe Dubois static const VMStateDescription vmstate_imx6ul_ccm = { 227*781182e1SJean-Christophe Dubois .name = TYPE_IMX6UL_CCM, 228*781182e1SJean-Christophe Dubois .version_id = 1, 229*781182e1SJean-Christophe Dubois .minimum_version_id = 1, 230*781182e1SJean-Christophe Dubois .fields = (VMStateField[]) { 231*781182e1SJean-Christophe Dubois VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX), 232*781182e1SJean-Christophe Dubois VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX), 233*781182e1SJean-Christophe Dubois VMSTATE_END_OF_LIST() 234*781182e1SJean-Christophe Dubois }, 235*781182e1SJean-Christophe Dubois }; 236*781182e1SJean-Christophe Dubois 237*781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev) 238*781182e1SJean-Christophe Dubois { 239*781182e1SJean-Christophe Dubois uint64_t freq = CKIH_FREQ; 240*781182e1SJean-Christophe Dubois 241*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 242*781182e1SJean-Christophe Dubois 243*781182e1SJean-Christophe Dubois return freq; 244*781182e1SJean-Christophe Dubois } 245*781182e1SJean-Christophe Dubois 246*781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev) 247*781182e1SJean-Christophe Dubois { 248*781182e1SJean-Christophe Dubois uint64_t freq = imx6ul_analog_get_osc_clk(dev); 249*781182e1SJean-Christophe Dubois 250*781182e1SJean-Christophe Dubois if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS], 251*781182e1SJean-Christophe Dubois ANALOG_PLL_SYS, DIV_SELECT)) { 252*781182e1SJean-Christophe Dubois freq *= 22; 253*781182e1SJean-Christophe Dubois } else { 254*781182e1SJean-Christophe Dubois freq *= 20; 255*781182e1SJean-Christophe Dubois } 256*781182e1SJean-Christophe Dubois 257*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 258*781182e1SJean-Christophe Dubois 259*781182e1SJean-Christophe Dubois return freq; 260*781182e1SJean-Christophe Dubois } 261*781182e1SJean-Christophe Dubois 262*781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev) 263*781182e1SJean-Christophe Dubois { 264*781182e1SJean-Christophe Dubois uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20; 265*781182e1SJean-Christophe Dubois 266*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 267*781182e1SJean-Christophe Dubois 268*781182e1SJean-Christophe Dubois return freq; 269*781182e1SJean-Christophe Dubois } 270*781182e1SJean-Christophe Dubois 271*781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev) 272*781182e1SJean-Christophe Dubois { 273*781182e1SJean-Christophe Dubois uint64_t freq = 0; 274*781182e1SJean-Christophe Dubois 275*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_clk(dev) * 18 276*781182e1SJean-Christophe Dubois / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528], 277*781182e1SJean-Christophe Dubois ANALOG_PFD_528, PFD0_FRAC); 278*781182e1SJean-Christophe Dubois 279*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 280*781182e1SJean-Christophe Dubois 281*781182e1SJean-Christophe Dubois return freq; 282*781182e1SJean-Christophe Dubois } 283*781182e1SJean-Christophe Dubois 284*781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev) 285*781182e1SJean-Christophe Dubois { 286*781182e1SJean-Christophe Dubois uint64_t freq = 0; 287*781182e1SJean-Christophe Dubois 288*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_clk(dev) * 18 289*781182e1SJean-Christophe Dubois / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528], 290*781182e1SJean-Christophe Dubois ANALOG_PFD_528, PFD2_FRAC); 291*781182e1SJean-Christophe Dubois 292*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 293*781182e1SJean-Christophe Dubois 294*781182e1SJean-Christophe Dubois return freq; 295*781182e1SJean-Christophe Dubois } 296*781182e1SJean-Christophe Dubois 297*781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev) 298*781182e1SJean-Christophe Dubois { 299*781182e1SJean-Christophe Dubois uint64_t freq = 0; 300*781182e1SJean-Christophe Dubois 301*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 302*781182e1SJean-Christophe Dubois 303*781182e1SJean-Christophe Dubois return freq; 304*781182e1SJean-Christophe Dubois } 305*781182e1SJean-Christophe Dubois 306*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev) 307*781182e1SJean-Christophe Dubois { 308*781182e1SJean-Christophe Dubois uint64_t freq = 0; 309*781182e1SJean-Christophe Dubois 310*781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) { 311*781182e1SJean-Christophe Dubois case 0: 312*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll3_clk(dev); 313*781182e1SJean-Christophe Dubois break; 314*781182e1SJean-Christophe Dubois case 1: 315*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_osc_clk(dev); 316*781182e1SJean-Christophe Dubois break; 317*781182e1SJean-Christophe Dubois case 2: 318*781182e1SJean-Christophe Dubois freq = imx6ul_analog_pll2_bypass_clk(dev); 319*781182e1SJean-Christophe Dubois break; 320*781182e1SJean-Christophe Dubois case 3: 321*781182e1SJean-Christophe Dubois /* We should never get there as 3 is a reserved value */ 322*781182e1SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, 323*781182e1SJean-Christophe Dubois "[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n", 324*781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM, __func__); 325*781182e1SJean-Christophe Dubois /* freq is set to 0 as we don't know what it should be */ 326*781182e1SJean-Christophe Dubois break; 327*781182e1SJean-Christophe Dubois default: 328*781182e1SJean-Christophe Dubois g_assert_not_reached(); 329*781182e1SJean-Christophe Dubois } 330*781182e1SJean-Christophe Dubois 331*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 332*781182e1SJean-Christophe Dubois 333*781182e1SJean-Christophe Dubois return freq; 334*781182e1SJean-Christophe Dubois } 335*781182e1SJean-Christophe Dubois 336*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev) 337*781182e1SJean-Christophe Dubois { 338*781182e1SJean-Christophe Dubois uint64_t freq = 0; 339*781182e1SJean-Christophe Dubois 340*781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) { 341*781182e1SJean-Christophe Dubois case 0: 342*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_clk(dev); 343*781182e1SJean-Christophe Dubois break; 344*781182e1SJean-Christophe Dubois case 1: 345*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_pfd2_clk(dev); 346*781182e1SJean-Christophe Dubois break; 347*781182e1SJean-Christophe Dubois case 2: 348*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_pfd0_clk(dev); 349*781182e1SJean-Christophe Dubois break; 350*781182e1SJean-Christophe Dubois case 3: 351*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2; 352*781182e1SJean-Christophe Dubois break; 353*781182e1SJean-Christophe Dubois default: 354*781182e1SJean-Christophe Dubois g_assert_not_reached(); 355*781182e1SJean-Christophe Dubois } 356*781182e1SJean-Christophe Dubois 357*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 358*781182e1SJean-Christophe Dubois 359*781182e1SJean-Christophe Dubois return freq; 360*781182e1SJean-Christophe Dubois } 361*781182e1SJean-Christophe Dubois 362*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev) 363*781182e1SJean-Christophe Dubois { 364*781182e1SJean-Christophe Dubois uint64_t freq = 0; 365*781182e1SJean-Christophe Dubois 366*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev) 367*781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF)); 368*781182e1SJean-Christophe Dubois 369*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 370*781182e1SJean-Christophe Dubois 371*781182e1SJean-Christophe Dubois return freq; 372*781182e1SJean-Christophe Dubois } 373*781182e1SJean-Christophe Dubois 374*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev) 375*781182e1SJean-Christophe Dubois { 376*781182e1SJean-Christophe Dubois uint64_t freq = 0; 377*781182e1SJean-Christophe Dubois 378*781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) { 379*781182e1SJean-Christophe Dubois case 0: 380*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_clk_sel_clk(dev); 381*781182e1SJean-Christophe Dubois break; 382*781182e1SJean-Christophe Dubois case 1: 383*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_clk2_clk(dev); 384*781182e1SJean-Christophe Dubois break; 385*781182e1SJean-Christophe Dubois default: 386*781182e1SJean-Christophe Dubois g_assert_not_reached(); 387*781182e1SJean-Christophe Dubois } 388*781182e1SJean-Christophe Dubois 389*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 390*781182e1SJean-Christophe Dubois 391*781182e1SJean-Christophe Dubois return freq; 392*781182e1SJean-Christophe Dubois } 393*781182e1SJean-Christophe Dubois 394*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev) 395*781182e1SJean-Christophe Dubois { 396*781182e1SJean-Christophe Dubois uint64_t freq = 0; 397*781182e1SJean-Christophe Dubois 398*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_periph_sel_clk(dev) 399*781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF)); 400*781182e1SJean-Christophe Dubois 401*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 402*781182e1SJean-Christophe Dubois 403*781182e1SJean-Christophe Dubois return freq; 404*781182e1SJean-Christophe Dubois } 405*781182e1SJean-Christophe Dubois 406*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev) 407*781182e1SJean-Christophe Dubois { 408*781182e1SJean-Christophe Dubois uint64_t freq = 0; 409*781182e1SJean-Christophe Dubois 410*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_ahb_clk(dev) 411*781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF)); 412*781182e1SJean-Christophe Dubois 413*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 414*781182e1SJean-Christophe Dubois 415*781182e1SJean-Christophe Dubois return freq; 416*781182e1SJean-Christophe Dubois } 417*781182e1SJean-Christophe Dubois 418*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev) 419*781182e1SJean-Christophe Dubois { 420*781182e1SJean-Christophe Dubois uint64_t freq = 0; 421*781182e1SJean-Christophe Dubois 422*781182e1SJean-Christophe Dubois switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) { 423*781182e1SJean-Christophe Dubois case 0: 424*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_ipg_clk(dev); 425*781182e1SJean-Christophe Dubois break; 426*781182e1SJean-Christophe Dubois case 1: 427*781182e1SJean-Christophe Dubois freq = imx6ul_analog_get_osc_clk(dev); 428*781182e1SJean-Christophe Dubois break; 429*781182e1SJean-Christophe Dubois default: 430*781182e1SJean-Christophe Dubois g_assert_not_reached(); 431*781182e1SJean-Christophe Dubois } 432*781182e1SJean-Christophe Dubois 433*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 434*781182e1SJean-Christophe Dubois 435*781182e1SJean-Christophe Dubois return freq; 436*781182e1SJean-Christophe Dubois } 437*781182e1SJean-Christophe Dubois 438*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev) 439*781182e1SJean-Christophe Dubois { 440*781182e1SJean-Christophe Dubois uint64_t freq = 0; 441*781182e1SJean-Christophe Dubois 442*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_per_sel_clk(dev) 443*781182e1SJean-Christophe Dubois / (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF)); 444*781182e1SJean-Christophe Dubois 445*781182e1SJean-Christophe Dubois trace_ccm_freq((uint32_t)freq); 446*781182e1SJean-Christophe Dubois 447*781182e1SJean-Christophe Dubois return freq; 448*781182e1SJean-Christophe Dubois } 449*781182e1SJean-Christophe Dubois 450*781182e1SJean-Christophe Dubois static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) 451*781182e1SJean-Christophe Dubois { 452*781182e1SJean-Christophe Dubois uint32_t freq = 0; 453*781182e1SJean-Christophe Dubois IMX6ULCCMState *s = IMX6UL_CCM(dev); 454*781182e1SJean-Christophe Dubois 455*781182e1SJean-Christophe Dubois switch (clock) { 456*781182e1SJean-Christophe Dubois case CLK_NONE: 457*781182e1SJean-Christophe Dubois break; 458*781182e1SJean-Christophe Dubois case CLK_IPG: 459*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_ipg_clk(s); 460*781182e1SJean-Christophe Dubois break; 461*781182e1SJean-Christophe Dubois case CLK_IPG_HIGH: 462*781182e1SJean-Christophe Dubois freq = imx6ul_ccm_get_per_clk(s); 463*781182e1SJean-Christophe Dubois break; 464*781182e1SJean-Christophe Dubois case CLK_32k: 465*781182e1SJean-Christophe Dubois freq = CKIL_FREQ; 466*781182e1SJean-Christophe Dubois break; 467*781182e1SJean-Christophe Dubois case CLK_HIGH: 468*781182e1SJean-Christophe Dubois freq = CKIH_FREQ; 469*781182e1SJean-Christophe Dubois break; 470*781182e1SJean-Christophe Dubois case CLK_HIGH_DIV: 471*781182e1SJean-Christophe Dubois freq = CKIH_FREQ / 8; 472*781182e1SJean-Christophe Dubois break; 473*781182e1SJean-Christophe Dubois default: 474*781182e1SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", 475*781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM, __func__, clock); 476*781182e1SJean-Christophe Dubois break; 477*781182e1SJean-Christophe Dubois } 478*781182e1SJean-Christophe Dubois 479*781182e1SJean-Christophe Dubois trace_ccm_clock_freq(clock, freq); 480*781182e1SJean-Christophe Dubois 481*781182e1SJean-Christophe Dubois return freq; 482*781182e1SJean-Christophe Dubois } 483*781182e1SJean-Christophe Dubois 484*781182e1SJean-Christophe Dubois static void imx6ul_ccm_reset(DeviceState *dev) 485*781182e1SJean-Christophe Dubois { 486*781182e1SJean-Christophe Dubois IMX6ULCCMState *s = IMX6UL_CCM(dev); 487*781182e1SJean-Christophe Dubois 488*781182e1SJean-Christophe Dubois trace_ccm_entry(); 489*781182e1SJean-Christophe Dubois 490*781182e1SJean-Christophe Dubois s->ccm[CCM_CCR] = 0x0401167F; 491*781182e1SJean-Christophe Dubois s->ccm[CCM_CCDR] = 0x00000000; 492*781182e1SJean-Christophe Dubois s->ccm[CCM_CSR] = 0x00000010; 493*781182e1SJean-Christophe Dubois s->ccm[CCM_CCSR] = 0x00000100; 494*781182e1SJean-Christophe Dubois s->ccm[CCM_CACRR] = 0x00000000; 495*781182e1SJean-Christophe Dubois s->ccm[CCM_CBCDR] = 0x00018D00; 496*781182e1SJean-Christophe Dubois s->ccm[CCM_CBCMR] = 0x24860324; 497*781182e1SJean-Christophe Dubois s->ccm[CCM_CSCMR1] = 0x04900080; 498*781182e1SJean-Christophe Dubois s->ccm[CCM_CSCMR2] = 0x03192F06; 499*781182e1SJean-Christophe Dubois s->ccm[CCM_CSCDR1] = 0x00490B00; 500*781182e1SJean-Christophe Dubois s->ccm[CCM_CS1CDR] = 0x0EC102C1; 501*781182e1SJean-Christophe Dubois s->ccm[CCM_CS2CDR] = 0x000336C1; 502*781182e1SJean-Christophe Dubois s->ccm[CCM_CDCDR] = 0x33F71F92; 503*781182e1SJean-Christophe Dubois s->ccm[CCM_CHSCCDR] = 0x000248A4; 504*781182e1SJean-Christophe Dubois s->ccm[CCM_CSCDR2] = 0x00029B48; 505*781182e1SJean-Christophe Dubois s->ccm[CCM_CSCDR3] = 0x00014841; 506*781182e1SJean-Christophe Dubois s->ccm[CCM_CDHIPR] = 0x00000000; 507*781182e1SJean-Christophe Dubois s->ccm[CCM_CTOR] = 0x00000000; 508*781182e1SJean-Christophe Dubois s->ccm[CCM_CLPCR] = 0x00000079; 509*781182e1SJean-Christophe Dubois s->ccm[CCM_CISR] = 0x00000000; 510*781182e1SJean-Christophe Dubois s->ccm[CCM_CIMR] = 0xFFFFFFFF; 511*781182e1SJean-Christophe Dubois s->ccm[CCM_CCOSR] = 0x000A0001; 512*781182e1SJean-Christophe Dubois s->ccm[CCM_CGPR] = 0x0000FE62; 513*781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR0] = 0xFFFFFFFF; 514*781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR1] = 0xFFFFFFFF; 515*781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR2] = 0xFC3FFFFF; 516*781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR3] = 0xFFFFFFFF; 517*781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR4] = 0xFFFFFFFF; 518*781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR5] = 0xFFFFFFFF; 519*781182e1SJean-Christophe Dubois s->ccm[CCM_CCGR6] = 0xFFFFFFFF; 520*781182e1SJean-Christophe Dubois s->ccm[CCM_CMEOR] = 0xFFFFFFFF; 521*781182e1SJean-Christophe Dubois 522*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063; 523*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000; 524*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000; 525*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001; 526*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000; 527*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000; 528*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012; 529*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006; 530*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100; 531*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C; 532*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C; 533*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100; 534*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447; 535*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001; 536*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PFD_480] = 0x1311100C; 537*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PFD_528] = 0x1018101B; 538*781182e1SJean-Christophe Dubois 539*781182e1SJean-Christophe Dubois s->analog[PMU_REG_1P1] = 0x00001073; 540*781182e1SJean-Christophe Dubois s->analog[PMU_REG_3P0] = 0x00000F74; 541*781182e1SJean-Christophe Dubois s->analog[PMU_REG_2P5] = 0x00001073; 542*781182e1SJean-Christophe Dubois s->analog[PMU_REG_CORE] = 0x00482012; 543*781182e1SJean-Christophe Dubois s->analog[PMU_MISC0] = 0x04000000; 544*781182e1SJean-Christophe Dubois s->analog[PMU_MISC1] = 0x00000000; 545*781182e1SJean-Christophe Dubois s->analog[PMU_MISC2] = 0x00272727; 546*781182e1SJean-Christophe Dubois s->analog[PMU_LOWPWR_CTRL] = 0x00004009; 547*781182e1SJean-Christophe Dubois 548*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004; 549*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000; 550*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000; 551*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000; 552*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB1_MISC] = 0x00000002; 553*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004; 554*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000; 555*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_USB2_MISC] = 0x00000002; 556*781182e1SJean-Christophe Dubois s->analog[USB_ANALOG_DIGPROG] = 0x00640000; 557*781182e1SJean-Christophe Dubois 558*781182e1SJean-Christophe Dubois /* all PLLs need to be locked */ 559*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK; 560*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK; 561*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK; 562*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK; 563*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK; 564*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK; 565*781182e1SJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK; 566*781182e1SJean-Christophe Dubois 567*781182e1SJean-Christophe Dubois s->analog[TEMPMON_TEMPSENSE0] = 0x00000001; 568*781182e1SJean-Christophe Dubois s->analog[TEMPMON_TEMPSENSE1] = 0x00000001; 569*781182e1SJean-Christophe Dubois s->analog[TEMPMON_TEMPSENSE2] = 0x00000000; 570*781182e1SJean-Christophe Dubois } 571*781182e1SJean-Christophe Dubois 572*781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size) 573*781182e1SJean-Christophe Dubois { 574*781182e1SJean-Christophe Dubois uint32_t value = 0; 575*781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 576*781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 577*781182e1SJean-Christophe Dubois 578*781182e1SJean-Christophe Dubois assert(index < CCM_MAX); 579*781182e1SJean-Christophe Dubois 580*781182e1SJean-Christophe Dubois value = s->ccm[index]; 581*781182e1SJean-Christophe Dubois 582*781182e1SJean-Christophe Dubois trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value); 583*781182e1SJean-Christophe Dubois 584*781182e1SJean-Christophe Dubois return (uint64_t)value; 585*781182e1SJean-Christophe Dubois } 586*781182e1SJean-Christophe Dubois 587*781182e1SJean-Christophe Dubois static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value, 588*781182e1SJean-Christophe Dubois unsigned size) 589*781182e1SJean-Christophe Dubois { 590*781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 591*781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 592*781182e1SJean-Christophe Dubois 593*781182e1SJean-Christophe Dubois assert(index < CCM_MAX); 594*781182e1SJean-Christophe Dubois 595*781182e1SJean-Christophe Dubois trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value); 596*781182e1SJean-Christophe Dubois 597*781182e1SJean-Christophe Dubois /* 598*781182e1SJean-Christophe Dubois * We will do a better implementation later. In particular some bits 599*781182e1SJean-Christophe Dubois * cannot be written to. 600*781182e1SJean-Christophe Dubois */ 601*781182e1SJean-Christophe Dubois s->ccm[index] = (uint32_t)value; 602*781182e1SJean-Christophe Dubois } 603*781182e1SJean-Christophe Dubois 604*781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size) 605*781182e1SJean-Christophe Dubois { 606*781182e1SJean-Christophe Dubois uint32_t value; 607*781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 608*781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 609*781182e1SJean-Christophe Dubois 610*781182e1SJean-Christophe Dubois assert(index < CCM_ANALOG_MAX); 611*781182e1SJean-Christophe Dubois 612*781182e1SJean-Christophe Dubois switch (index) { 613*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 614*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 615*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 616*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 617*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 618*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 619*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 620*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 621*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 622*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 623*781182e1SJean-Christophe Dubois case PMU_MISC1_SET: 624*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 625*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_SET: 626*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_SET: 627*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_SET: 628*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_SET: 629*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_SET: 630*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_SET: 631*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE0_SET: 632*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE1_SET: 633*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE2_SET: 634*781182e1SJean-Christophe Dubois /* 635*781182e1SJean-Christophe Dubois * All REG_NAME_SET register access are in fact targeting 636*781182e1SJean-Christophe Dubois * the REG_NAME register. 637*781182e1SJean-Christophe Dubois */ 638*781182e1SJean-Christophe Dubois value = s->analog[index - 1]; 639*781182e1SJean-Christophe Dubois break; 640*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 641*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 642*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 643*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 644*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 645*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 646*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 647*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 648*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 649*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 650*781182e1SJean-Christophe Dubois case PMU_MISC1_CLR: 651*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 652*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_CLR: 653*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_CLR: 654*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_CLR: 655*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_CLR: 656*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_CLR: 657*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_CLR: 658*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE0_CLR: 659*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE1_CLR: 660*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE2_CLR: 661*781182e1SJean-Christophe Dubois /* 662*781182e1SJean-Christophe Dubois * All REG_NAME_CLR register access are in fact targeting 663*781182e1SJean-Christophe Dubois * the REG_NAME register. 664*781182e1SJean-Christophe Dubois */ 665*781182e1SJean-Christophe Dubois value = s->analog[index - 2]; 666*781182e1SJean-Christophe Dubois break; 667*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 668*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 669*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 670*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 671*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 672*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 673*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 674*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 675*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 676*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 677*781182e1SJean-Christophe Dubois case PMU_MISC1_TOG: 678*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 679*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_TOG: 680*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_TOG: 681*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_TOG: 682*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_TOG: 683*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_TOG: 684*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_TOG: 685*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE0_TOG: 686*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE1_TOG: 687*781182e1SJean-Christophe Dubois case TEMPMON_TEMPSENSE2_TOG: 688*781182e1SJean-Christophe Dubois /* 689*781182e1SJean-Christophe Dubois * All REG_NAME_TOG register access are in fact targeting 690*781182e1SJean-Christophe Dubois * the REG_NAME register. 691*781182e1SJean-Christophe Dubois */ 692*781182e1SJean-Christophe Dubois value = s->analog[index - 3]; 693*781182e1SJean-Christophe Dubois break; 694*781182e1SJean-Christophe Dubois default: 695*781182e1SJean-Christophe Dubois value = s->analog[index]; 696*781182e1SJean-Christophe Dubois break; 697*781182e1SJean-Christophe Dubois } 698*781182e1SJean-Christophe Dubois 699*781182e1SJean-Christophe Dubois trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value); 700*781182e1SJean-Christophe Dubois 701*781182e1SJean-Christophe Dubois return (uint64_t)value; 702*781182e1SJean-Christophe Dubois } 703*781182e1SJean-Christophe Dubois 704*781182e1SJean-Christophe Dubois static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value, 705*781182e1SJean-Christophe Dubois unsigned size) 706*781182e1SJean-Christophe Dubois { 707*781182e1SJean-Christophe Dubois uint32_t index = offset >> 2; 708*781182e1SJean-Christophe Dubois IMX6ULCCMState *s = (IMX6ULCCMState *)opaque; 709*781182e1SJean-Christophe Dubois 710*781182e1SJean-Christophe Dubois assert(index < CCM_ANALOG_MAX); 711*781182e1SJean-Christophe Dubois 712*781182e1SJean-Christophe Dubois trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value); 713*781182e1SJean-Christophe Dubois 714*781182e1SJean-Christophe Dubois switch (index) { 715*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 716*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 717*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 718*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 719*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 720*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 721*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 722*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 723*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 724*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 725*781182e1SJean-Christophe Dubois case PMU_MISC1_SET: 726*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 727*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_SET: 728*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_SET: 729*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_SET: 730*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_SET: 731*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_SET: 732*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_SET: 733*781182e1SJean-Christophe Dubois /* 734*781182e1SJean-Christophe Dubois * All REG_NAME_SET register access are in fact targeting 735*781182e1SJean-Christophe Dubois * the REG_NAME register. So we change the value of the 736*781182e1SJean-Christophe Dubois * REG_NAME register, setting bits passed in the value. 737*781182e1SJean-Christophe Dubois */ 738*781182e1SJean-Christophe Dubois s->analog[index - 1] |= value; 739*781182e1SJean-Christophe Dubois break; 740*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 741*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 742*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 743*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 744*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 745*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 746*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 747*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 748*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 749*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 750*781182e1SJean-Christophe Dubois case PMU_MISC1_CLR: 751*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 752*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_CLR: 753*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_CLR: 754*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_CLR: 755*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_CLR: 756*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_CLR: 757*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_CLR: 758*781182e1SJean-Christophe Dubois /* 759*781182e1SJean-Christophe Dubois * All REG_NAME_CLR register access are in fact targeting 760*781182e1SJean-Christophe Dubois * the REG_NAME register. So we change the value of the 761*781182e1SJean-Christophe Dubois * REG_NAME register, unsetting bits passed in the value. 762*781182e1SJean-Christophe Dubois */ 763*781182e1SJean-Christophe Dubois s->analog[index - 2] &= ~value; 764*781182e1SJean-Christophe Dubois break; 765*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 766*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 767*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 768*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 769*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 770*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 771*781182e1SJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 772*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 773*781182e1SJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 774*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 775*781182e1SJean-Christophe Dubois case PMU_MISC1_TOG: 776*781182e1SJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 777*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_TOG: 778*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_TOG: 779*781182e1SJean-Christophe Dubois case USB_ANALOG_USB1_MISC_TOG: 780*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_TOG: 781*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_TOG: 782*781182e1SJean-Christophe Dubois case USB_ANALOG_USB2_MISC_TOG: 783*781182e1SJean-Christophe Dubois /* 784*781182e1SJean-Christophe Dubois * All REG_NAME_TOG register access are in fact targeting 785*781182e1SJean-Christophe Dubois * the REG_NAME register. So we change the value of the 786*781182e1SJean-Christophe Dubois * REG_NAME register, toggling bits passed in the value. 787*781182e1SJean-Christophe Dubois */ 788*781182e1SJean-Christophe Dubois s->analog[index - 3] ^= value; 789*781182e1SJean-Christophe Dubois break; 790*781182e1SJean-Christophe Dubois default: 791*781182e1SJean-Christophe Dubois /* 792*781182e1SJean-Christophe Dubois * We will do a better implementation later. In particular some bits 793*781182e1SJean-Christophe Dubois * cannot be written to. 794*781182e1SJean-Christophe Dubois */ 795*781182e1SJean-Christophe Dubois s->analog[index] = value; 796*781182e1SJean-Christophe Dubois break; 797*781182e1SJean-Christophe Dubois } 798*781182e1SJean-Christophe Dubois } 799*781182e1SJean-Christophe Dubois 800*781182e1SJean-Christophe Dubois static const struct MemoryRegionOps imx6ul_ccm_ops = { 801*781182e1SJean-Christophe Dubois .read = imx6ul_ccm_read, 802*781182e1SJean-Christophe Dubois .write = imx6ul_ccm_write, 803*781182e1SJean-Christophe Dubois .endianness = DEVICE_NATIVE_ENDIAN, 804*781182e1SJean-Christophe Dubois .valid = { 805*781182e1SJean-Christophe Dubois /* 806*781182e1SJean-Christophe Dubois * Our device would not work correctly if the guest was doing 807*781182e1SJean-Christophe Dubois * unaligned access. This might not be a limitation on the real 808*781182e1SJean-Christophe Dubois * device but in practice there is no reason for a guest to access 809*781182e1SJean-Christophe Dubois * this device unaligned. 810*781182e1SJean-Christophe Dubois */ 811*781182e1SJean-Christophe Dubois .min_access_size = 4, 812*781182e1SJean-Christophe Dubois .max_access_size = 4, 813*781182e1SJean-Christophe Dubois .unaligned = false, 814*781182e1SJean-Christophe Dubois }, 815*781182e1SJean-Christophe Dubois }; 816*781182e1SJean-Christophe Dubois 817*781182e1SJean-Christophe Dubois static const struct MemoryRegionOps imx6ul_analog_ops = { 818*781182e1SJean-Christophe Dubois .read = imx6ul_analog_read, 819*781182e1SJean-Christophe Dubois .write = imx6ul_analog_write, 820*781182e1SJean-Christophe Dubois .endianness = DEVICE_NATIVE_ENDIAN, 821*781182e1SJean-Christophe Dubois .valid = { 822*781182e1SJean-Christophe Dubois /* 823*781182e1SJean-Christophe Dubois * Our device would not work correctly if the guest was doing 824*781182e1SJean-Christophe Dubois * unaligned access. This might not be a limitation on the real 825*781182e1SJean-Christophe Dubois * device but in practice there is no reason for a guest to access 826*781182e1SJean-Christophe Dubois * this device unaligned. 827*781182e1SJean-Christophe Dubois */ 828*781182e1SJean-Christophe Dubois .min_access_size = 4, 829*781182e1SJean-Christophe Dubois .max_access_size = 4, 830*781182e1SJean-Christophe Dubois .unaligned = false, 831*781182e1SJean-Christophe Dubois }, 832*781182e1SJean-Christophe Dubois }; 833*781182e1SJean-Christophe Dubois 834*781182e1SJean-Christophe Dubois static void imx6ul_ccm_init(Object *obj) 835*781182e1SJean-Christophe Dubois { 836*781182e1SJean-Christophe Dubois DeviceState *dev = DEVICE(obj); 837*781182e1SJean-Christophe Dubois SysBusDevice *sd = SYS_BUS_DEVICE(obj); 838*781182e1SJean-Christophe Dubois IMX6ULCCMState *s = IMX6UL_CCM(obj); 839*781182e1SJean-Christophe Dubois 840*781182e1SJean-Christophe Dubois /* initialize a container for the all memory range */ 841*781182e1SJean-Christophe Dubois memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000); 842*781182e1SJean-Christophe Dubois 843*781182e1SJean-Christophe Dubois /* We initialize an IO memory region for the CCM part */ 844*781182e1SJean-Christophe Dubois memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s, 845*781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t)); 846*781182e1SJean-Christophe Dubois 847*781182e1SJean-Christophe Dubois /* Add the CCM as a subregion at offset 0 */ 848*781182e1SJean-Christophe Dubois memory_region_add_subregion(&s->container, 0, &s->ioccm); 849*781182e1SJean-Christophe Dubois 850*781182e1SJean-Christophe Dubois /* We initialize an IO memory region for the ANALOG part */ 851*781182e1SJean-Christophe Dubois memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s, 852*781182e1SJean-Christophe Dubois TYPE_IMX6UL_CCM ".analog", 853*781182e1SJean-Christophe Dubois CCM_ANALOG_MAX * sizeof(uint32_t)); 854*781182e1SJean-Christophe Dubois 855*781182e1SJean-Christophe Dubois /* Add the ANALOG as a subregion at offset 0x4000 */ 856*781182e1SJean-Christophe Dubois memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog); 857*781182e1SJean-Christophe Dubois 858*781182e1SJean-Christophe Dubois sysbus_init_mmio(sd, &s->container); 859*781182e1SJean-Christophe Dubois } 860*781182e1SJean-Christophe Dubois 861*781182e1SJean-Christophe Dubois static void imx6ul_ccm_class_init(ObjectClass *klass, void *data) 862*781182e1SJean-Christophe Dubois { 863*781182e1SJean-Christophe Dubois DeviceClass *dc = DEVICE_CLASS(klass); 864*781182e1SJean-Christophe Dubois IMXCCMClass *ccm = IMX_CCM_CLASS(klass); 865*781182e1SJean-Christophe Dubois 866*781182e1SJean-Christophe Dubois dc->reset = imx6ul_ccm_reset; 867*781182e1SJean-Christophe Dubois dc->vmsd = &vmstate_imx6ul_ccm; 868*781182e1SJean-Christophe Dubois dc->desc = "i.MX6UL Clock Control Module"; 869*781182e1SJean-Christophe Dubois 870*781182e1SJean-Christophe Dubois ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency; 871*781182e1SJean-Christophe Dubois } 872*781182e1SJean-Christophe Dubois 873*781182e1SJean-Christophe Dubois static const TypeInfo imx6ul_ccm_info = { 874*781182e1SJean-Christophe Dubois .name = TYPE_IMX6UL_CCM, 875*781182e1SJean-Christophe Dubois .parent = TYPE_IMX_CCM, 876*781182e1SJean-Christophe Dubois .instance_size = sizeof(IMX6ULCCMState), 877*781182e1SJean-Christophe Dubois .instance_init = imx6ul_ccm_init, 878*781182e1SJean-Christophe Dubois .class_init = imx6ul_ccm_class_init, 879*781182e1SJean-Christophe Dubois }; 880*781182e1SJean-Christophe Dubois 881*781182e1SJean-Christophe Dubois static void imx6ul_ccm_register_types(void) 882*781182e1SJean-Christophe Dubois { 883*781182e1SJean-Christophe Dubois type_register_static(&imx6ul_ccm_info); 884*781182e1SJean-Christophe Dubois } 885*781182e1SJean-Christophe Dubois 886*781182e1SJean-Christophe Dubois type_init(imx6ul_ccm_register_types) 887