1a66d815cSJean-Christophe Dubois /* 2a66d815cSJean-Christophe Dubois * IMX6 Clock Control Module 3a66d815cSJean-Christophe Dubois * 4a66d815cSJean-Christophe Dubois * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net> 5a66d815cSJean-Christophe Dubois * 6a66d815cSJean-Christophe Dubois * This work is licensed under the terms of the GNU GPL, version 2 or later. 7a66d815cSJean-Christophe Dubois * See the COPYING file in the top-level directory. 8a66d815cSJean-Christophe Dubois * 9a66d815cSJean-Christophe Dubois * To get the timer frequencies right, we need to emulate at least part of 10a66d815cSJean-Christophe Dubois * the CCM. 11a66d815cSJean-Christophe Dubois */ 12a66d815cSJean-Christophe Dubois 13a66d815cSJean-Christophe Dubois #include "qemu/osdep.h" 14a66d815cSJean-Christophe Dubois #include "hw/misc/imx6_ccm.h" 15d6454270SMarkus Armbruster #include "migration/vmstate.h" 1603dd024fSPaolo Bonzini #include "qemu/log.h" 170b8fa32fSMarkus Armbruster #include "qemu/module.h" 183839aff8SBernhard Beschow #include "trace.h" 19a66d815cSJean-Christophe Dubois 20d675765aSPeter Maydell static const char *imx6_ccm_reg_name(uint32_t reg) 21a66d815cSJean-Christophe Dubois { 22a66d815cSJean-Christophe Dubois static char unknown[20]; 23a66d815cSJean-Christophe Dubois 24a66d815cSJean-Christophe Dubois switch (reg) { 25a66d815cSJean-Christophe Dubois case CCM_CCR: 26a66d815cSJean-Christophe Dubois return "CCR"; 27a66d815cSJean-Christophe Dubois case CCM_CCDR: 28a66d815cSJean-Christophe Dubois return "CCDR"; 29a66d815cSJean-Christophe Dubois case CCM_CSR: 30a66d815cSJean-Christophe Dubois return "CSR"; 31a66d815cSJean-Christophe Dubois case CCM_CCSR: 32a66d815cSJean-Christophe Dubois return "CCSR"; 33a66d815cSJean-Christophe Dubois case CCM_CACRR: 34a66d815cSJean-Christophe Dubois return "CACRR"; 35a66d815cSJean-Christophe Dubois case CCM_CBCDR: 36a66d815cSJean-Christophe Dubois return "CBCDR"; 37a66d815cSJean-Christophe Dubois case CCM_CBCMR: 38a66d815cSJean-Christophe Dubois return "CBCMR"; 39a66d815cSJean-Christophe Dubois case CCM_CSCMR1: 40a66d815cSJean-Christophe Dubois return "CSCMR1"; 41a66d815cSJean-Christophe Dubois case CCM_CSCMR2: 42a66d815cSJean-Christophe Dubois return "CSCMR2"; 43a66d815cSJean-Christophe Dubois case CCM_CSCDR1: 44a66d815cSJean-Christophe Dubois return "CSCDR1"; 45a66d815cSJean-Christophe Dubois case CCM_CS1CDR: 46a66d815cSJean-Christophe Dubois return "CS1CDR"; 47a66d815cSJean-Christophe Dubois case CCM_CS2CDR: 48a66d815cSJean-Christophe Dubois return "CS2CDR"; 49a66d815cSJean-Christophe Dubois case CCM_CDCDR: 50a66d815cSJean-Christophe Dubois return "CDCDR"; 51a66d815cSJean-Christophe Dubois case CCM_CHSCCDR: 52a66d815cSJean-Christophe Dubois return "CHSCCDR"; 53a66d815cSJean-Christophe Dubois case CCM_CSCDR2: 54a66d815cSJean-Christophe Dubois return "CSCDR2"; 55a66d815cSJean-Christophe Dubois case CCM_CSCDR3: 56a66d815cSJean-Christophe Dubois return "CSCDR3"; 57a66d815cSJean-Christophe Dubois case CCM_CDHIPR: 58a66d815cSJean-Christophe Dubois return "CDHIPR"; 59a66d815cSJean-Christophe Dubois case CCM_CTOR: 60a66d815cSJean-Christophe Dubois return "CTOR"; 61a66d815cSJean-Christophe Dubois case CCM_CLPCR: 62a66d815cSJean-Christophe Dubois return "CLPCR"; 63a66d815cSJean-Christophe Dubois case CCM_CISR: 64a66d815cSJean-Christophe Dubois return "CISR"; 65a66d815cSJean-Christophe Dubois case CCM_CIMR: 66a66d815cSJean-Christophe Dubois return "CIMR"; 67a66d815cSJean-Christophe Dubois case CCM_CCOSR: 68a66d815cSJean-Christophe Dubois return "CCOSR"; 69a66d815cSJean-Christophe Dubois case CCM_CGPR: 70a66d815cSJean-Christophe Dubois return "CGPR"; 71a66d815cSJean-Christophe Dubois case CCM_CCGR0: 72a66d815cSJean-Christophe Dubois return "CCGR0"; 73a66d815cSJean-Christophe Dubois case CCM_CCGR1: 74a66d815cSJean-Christophe Dubois return "CCGR1"; 75a66d815cSJean-Christophe Dubois case CCM_CCGR2: 76a66d815cSJean-Christophe Dubois return "CCGR2"; 77a66d815cSJean-Christophe Dubois case CCM_CCGR3: 78a66d815cSJean-Christophe Dubois return "CCGR3"; 79a66d815cSJean-Christophe Dubois case CCM_CCGR4: 80a66d815cSJean-Christophe Dubois return "CCGR4"; 81a66d815cSJean-Christophe Dubois case CCM_CCGR5: 82a66d815cSJean-Christophe Dubois return "CCGR5"; 83a66d815cSJean-Christophe Dubois case CCM_CCGR6: 84a66d815cSJean-Christophe Dubois return "CCGR6"; 85a66d815cSJean-Christophe Dubois case CCM_CMEOR: 86a66d815cSJean-Christophe Dubois return "CMEOR"; 87a66d815cSJean-Christophe Dubois default: 889197c7bdSAlex Chen sprintf(unknown, "%u ?", reg); 89a66d815cSJean-Christophe Dubois return unknown; 90a66d815cSJean-Christophe Dubois } 91a66d815cSJean-Christophe Dubois } 92a66d815cSJean-Christophe Dubois 93d675765aSPeter Maydell static const char *imx6_analog_reg_name(uint32_t reg) 94a66d815cSJean-Christophe Dubois { 95a66d815cSJean-Christophe Dubois static char unknown[20]; 96a66d815cSJean-Christophe Dubois 97a66d815cSJean-Christophe Dubois switch (reg) { 98a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM: 99a66d815cSJean-Christophe Dubois return "PLL_ARM"; 100a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 101a66d815cSJean-Christophe Dubois return "PLL_ARM_SET"; 102a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 103a66d815cSJean-Christophe Dubois return "PLL_ARM_CLR"; 104a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 105a66d815cSJean-Christophe Dubois return "PLL_ARM_TOG"; 106a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1: 107a66d815cSJean-Christophe Dubois return "PLL_USB1"; 108a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 109a66d815cSJean-Christophe Dubois return "PLL_USB1_SET"; 110a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 111a66d815cSJean-Christophe Dubois return "PLL_USB1_CLR"; 112a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 113a66d815cSJean-Christophe Dubois return "PLL_USB1_TOG"; 114a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2: 115a66d815cSJean-Christophe Dubois return "PLL_USB2"; 116a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 117a66d815cSJean-Christophe Dubois return "PLL_USB2_SET"; 118a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 119a66d815cSJean-Christophe Dubois return "PLL_USB2_CLR"; 120a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 121a66d815cSJean-Christophe Dubois return "PLL_USB2_TOG"; 122a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS: 123a66d815cSJean-Christophe Dubois return "PLL_SYS"; 124a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 125a66d815cSJean-Christophe Dubois return "PLL_SYS_SET"; 126a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 127a66d815cSJean-Christophe Dubois return "PLL_SYS_CLR"; 128a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 129a66d815cSJean-Christophe Dubois return "PLL_SYS_TOG"; 130a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SS: 131a66d815cSJean-Christophe Dubois return "PLL_SYS_SS"; 132a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_NUM: 133a66d815cSJean-Christophe Dubois return "PLL_SYS_NUM"; 134a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_DENOM: 135a66d815cSJean-Christophe Dubois return "PLL_SYS_DENOM"; 136a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO: 137a66d815cSJean-Christophe Dubois return "PLL_AUDIO"; 138a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 139a66d815cSJean-Christophe Dubois return "PLL_AUDIO_SET"; 140a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 141a66d815cSJean-Christophe Dubois return "PLL_AUDIO_CLR"; 142a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 143a66d815cSJean-Christophe Dubois return "PLL_AUDIO_TOG"; 144a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_NUM: 145a66d815cSJean-Christophe Dubois return "PLL_AUDIO_NUM"; 146a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_DENOM: 147a66d815cSJean-Christophe Dubois return "PLL_AUDIO_DENOM"; 148a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO: 149a66d815cSJean-Christophe Dubois return "PLL_VIDEO"; 150a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 151a66d815cSJean-Christophe Dubois return "PLL_VIDEO_SET"; 152a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 153a66d815cSJean-Christophe Dubois return "PLL_VIDEO_CLR"; 154a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 155a66d815cSJean-Christophe Dubois return "PLL_VIDEO_TOG"; 156a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_NUM: 157a66d815cSJean-Christophe Dubois return "PLL_VIDEO_NUM"; 158a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_DENOM: 159a66d815cSJean-Christophe Dubois return "PLL_VIDEO_DENOM"; 160a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB: 161a66d815cSJean-Christophe Dubois return "PLL_MLB"; 162a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_SET: 163a66d815cSJean-Christophe Dubois return "PLL_MLB_SET"; 164a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_CLR: 165a66d815cSJean-Christophe Dubois return "PLL_MLB_CLR"; 166a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_TOG: 167a66d815cSJean-Christophe Dubois return "PLL_MLB_TOG"; 168a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET: 169a66d815cSJean-Christophe Dubois return "PLL_ENET"; 170a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 171a66d815cSJean-Christophe Dubois return "PLL_ENET_SET"; 172a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 173a66d815cSJean-Christophe Dubois return "PLL_ENET_CLR"; 174a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 175a66d815cSJean-Christophe Dubois return "PLL_ENET_TOG"; 176a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480: 177a66d815cSJean-Christophe Dubois return "PFD_480"; 178a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 179a66d815cSJean-Christophe Dubois return "PFD_480_SET"; 180a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 181a66d815cSJean-Christophe Dubois return "PFD_480_CLR"; 182a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 183a66d815cSJean-Christophe Dubois return "PFD_480_TOG"; 184a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528: 185a66d815cSJean-Christophe Dubois return "PFD_528"; 186a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 187a66d815cSJean-Christophe Dubois return "PFD_528_SET"; 188a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 189a66d815cSJean-Christophe Dubois return "PFD_528_CLR"; 190a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 191a66d815cSJean-Christophe Dubois return "PFD_528_TOG"; 192a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0: 193a66d815cSJean-Christophe Dubois return "MISC0"; 194a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 195a66d815cSJean-Christophe Dubois return "MISC0_SET"; 196a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 197a66d815cSJean-Christophe Dubois return "MISC0_CLR"; 198a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 199a66d815cSJean-Christophe Dubois return "MISC0_TOG"; 200a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2: 201a66d815cSJean-Christophe Dubois return "MISC2"; 202a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 203a66d815cSJean-Christophe Dubois return "MISC2_SET"; 204a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 205a66d815cSJean-Christophe Dubois return "MISC2_CLR"; 206a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 207a66d815cSJean-Christophe Dubois return "MISC2_TOG"; 208a66d815cSJean-Christophe Dubois case PMU_REG_1P1: 209a66d815cSJean-Christophe Dubois return "PMU_REG_1P1"; 210a66d815cSJean-Christophe Dubois case PMU_REG_3P0: 211a66d815cSJean-Christophe Dubois return "PMU_REG_3P0"; 212a66d815cSJean-Christophe Dubois case PMU_REG_2P5: 213a66d815cSJean-Christophe Dubois return "PMU_REG_2P5"; 214a66d815cSJean-Christophe Dubois case PMU_REG_CORE: 215a66d815cSJean-Christophe Dubois return "PMU_REG_CORE"; 216a66d815cSJean-Christophe Dubois case PMU_MISC1: 217a66d815cSJean-Christophe Dubois return "PMU_MISC1"; 218a66d815cSJean-Christophe Dubois case PMU_MISC1_SET: 219a66d815cSJean-Christophe Dubois return "PMU_MISC1_SET"; 220a66d815cSJean-Christophe Dubois case PMU_MISC1_CLR: 221a66d815cSJean-Christophe Dubois return "PMU_MISC1_CLR"; 222a66d815cSJean-Christophe Dubois case PMU_MISC1_TOG: 223a66d815cSJean-Christophe Dubois return "PMU_MISC1_TOG"; 224a66d815cSJean-Christophe Dubois case USB_ANALOG_DIGPROG: 225a66d815cSJean-Christophe Dubois return "USB_ANALOG_DIGPROG"; 226a66d815cSJean-Christophe Dubois default: 2279197c7bdSAlex Chen sprintf(unknown, "%u ?", reg); 228a66d815cSJean-Christophe Dubois return unknown; 229a66d815cSJean-Christophe Dubois } 230a66d815cSJean-Christophe Dubois } 231a66d815cSJean-Christophe Dubois 232a66d815cSJean-Christophe Dubois #define CKIH_FREQ 24000000 /* 24MHz crystal input */ 233a66d815cSJean-Christophe Dubois 234a66d815cSJean-Christophe Dubois static const VMStateDescription vmstate_imx6_ccm = { 235a66d815cSJean-Christophe Dubois .name = TYPE_IMX6_CCM, 236a66d815cSJean-Christophe Dubois .version_id = 1, 237a66d815cSJean-Christophe Dubois .minimum_version_id = 1, 238*e4ea952fSRichard Henderson .fields = (const VMStateField[]) { 239a66d815cSJean-Christophe Dubois VMSTATE_UINT32_ARRAY(ccm, IMX6CCMState, CCM_MAX), 240a66d815cSJean-Christophe Dubois VMSTATE_UINT32_ARRAY(analog, IMX6CCMState, CCM_ANALOG_MAX), 241a66d815cSJean-Christophe Dubois VMSTATE_END_OF_LIST() 242a66d815cSJean-Christophe Dubois }, 243a66d815cSJean-Christophe Dubois }; 244a66d815cSJean-Christophe Dubois 245a66d815cSJean-Christophe Dubois static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev) 246a66d815cSJean-Christophe Dubois { 247a66d815cSJean-Christophe Dubois uint64_t freq = 24000000; 248a66d815cSJean-Christophe Dubois 249a66d815cSJean-Christophe Dubois if (EXTRACT(dev->analog[CCM_ANALOG_PLL_SYS], DIV_SELECT)) { 250a66d815cSJean-Christophe Dubois freq *= 22; 251a66d815cSJean-Christophe Dubois } else { 252a66d815cSJean-Christophe Dubois freq *= 20; 253a66d815cSJean-Christophe Dubois } 254a66d815cSJean-Christophe Dubois 2553839aff8SBernhard Beschow trace_imx6_analog_get_pll2_clk(freq); 256a66d815cSJean-Christophe Dubois 257a66d815cSJean-Christophe Dubois return freq; 258a66d815cSJean-Christophe Dubois } 259a66d815cSJean-Christophe Dubois 260a66d815cSJean-Christophe Dubois static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev) 261a66d815cSJean-Christophe Dubois { 262a66d815cSJean-Christophe Dubois uint64_t freq = 0; 263a66d815cSJean-Christophe Dubois 264a66d815cSJean-Christophe Dubois freq = imx6_analog_get_pll2_clk(dev) * 18 265a66d815cSJean-Christophe Dubois / EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC); 266a66d815cSJean-Christophe Dubois 2673839aff8SBernhard Beschow trace_imx6_analog_get_pll2_pfd0_clk(freq); 268a66d815cSJean-Christophe Dubois 269a66d815cSJean-Christophe Dubois return freq; 270a66d815cSJean-Christophe Dubois } 271a66d815cSJean-Christophe Dubois 272a66d815cSJean-Christophe Dubois static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev) 273a66d815cSJean-Christophe Dubois { 274a66d815cSJean-Christophe Dubois uint64_t freq = 0; 275a66d815cSJean-Christophe Dubois 276a66d815cSJean-Christophe Dubois freq = imx6_analog_get_pll2_clk(dev) * 18 277a66d815cSJean-Christophe Dubois / EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC); 278a66d815cSJean-Christophe Dubois 2793839aff8SBernhard Beschow trace_imx6_analog_get_pll2_pfd2_clk(freq); 280a66d815cSJean-Christophe Dubois 281a66d815cSJean-Christophe Dubois return freq; 282a66d815cSJean-Christophe Dubois } 283a66d815cSJean-Christophe Dubois 284a66d815cSJean-Christophe Dubois static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev) 285a66d815cSJean-Christophe Dubois { 286a66d815cSJean-Christophe Dubois uint64_t freq = 0; 287a66d815cSJean-Christophe Dubois 288a66d815cSJean-Christophe Dubois switch (EXTRACT(dev->ccm[CCM_CBCMR], PRE_PERIPH_CLK_SEL)) { 289a66d815cSJean-Christophe Dubois case 0: 290a66d815cSJean-Christophe Dubois freq = imx6_analog_get_pll2_clk(dev); 291a66d815cSJean-Christophe Dubois break; 292a66d815cSJean-Christophe Dubois case 1: 293a66d815cSJean-Christophe Dubois freq = imx6_analog_get_pll2_pfd2_clk(dev); 294a66d815cSJean-Christophe Dubois break; 295a66d815cSJean-Christophe Dubois case 2: 296a66d815cSJean-Christophe Dubois freq = imx6_analog_get_pll2_pfd0_clk(dev); 297a66d815cSJean-Christophe Dubois break; 298a66d815cSJean-Christophe Dubois case 3: 299a66d815cSJean-Christophe Dubois freq = imx6_analog_get_pll2_pfd2_clk(dev) / 2; 300a66d815cSJean-Christophe Dubois break; 301a66d815cSJean-Christophe Dubois default: 302a66d815cSJean-Christophe Dubois /* We should never get there */ 303a66d815cSJean-Christophe Dubois g_assert_not_reached(); 304a66d815cSJean-Christophe Dubois break; 305a66d815cSJean-Christophe Dubois } 306a66d815cSJean-Christophe Dubois 3073839aff8SBernhard Beschow trace_imx6_analog_get_periph_clk(freq); 308a66d815cSJean-Christophe Dubois 309a66d815cSJean-Christophe Dubois return freq; 310a66d815cSJean-Christophe Dubois } 311a66d815cSJean-Christophe Dubois 312a66d815cSJean-Christophe Dubois static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev) 313a66d815cSJean-Christophe Dubois { 314a66d815cSJean-Christophe Dubois uint64_t freq = 0; 315a66d815cSJean-Christophe Dubois 316a66d815cSJean-Christophe Dubois freq = imx6_analog_get_periph_clk(dev) 317a66d815cSJean-Christophe Dubois / (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF)); 318a66d815cSJean-Christophe Dubois 3193839aff8SBernhard Beschow trace_imx6_ccm_get_ahb_clk(freq); 320a66d815cSJean-Christophe Dubois 321a66d815cSJean-Christophe Dubois return freq; 322a66d815cSJean-Christophe Dubois } 323a66d815cSJean-Christophe Dubois 324a66d815cSJean-Christophe Dubois static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev) 325a66d815cSJean-Christophe Dubois { 326a66d815cSJean-Christophe Dubois uint64_t freq = 0; 327a66d815cSJean-Christophe Dubois 328a66d815cSJean-Christophe Dubois freq = imx6_ccm_get_ahb_clk(dev) 3293c254ab8SLadi Prosek / (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF)); 330a66d815cSJean-Christophe Dubois 3313839aff8SBernhard Beschow trace_imx6_ccm_get_ipg_clk(freq); 332a66d815cSJean-Christophe Dubois 333a66d815cSJean-Christophe Dubois return freq; 334a66d815cSJean-Christophe Dubois } 335a66d815cSJean-Christophe Dubois 336a66d815cSJean-Christophe Dubois static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev) 337a66d815cSJean-Christophe Dubois { 338a66d815cSJean-Christophe Dubois uint64_t freq = 0; 339a66d815cSJean-Christophe Dubois 340a66d815cSJean-Christophe Dubois freq = imx6_ccm_get_ipg_clk(dev) 341a66d815cSJean-Christophe Dubois / (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF)); 342a66d815cSJean-Christophe Dubois 3433839aff8SBernhard Beschow trace_imx6_ccm_get_per_clk(freq); 344a66d815cSJean-Christophe Dubois 345a66d815cSJean-Christophe Dubois return freq; 346a66d815cSJean-Christophe Dubois } 347a66d815cSJean-Christophe Dubois 348a66d815cSJean-Christophe Dubois static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) 349a66d815cSJean-Christophe Dubois { 350a66d815cSJean-Christophe Dubois uint32_t freq = 0; 351a66d815cSJean-Christophe Dubois IMX6CCMState *s = IMX6_CCM(dev); 352a66d815cSJean-Christophe Dubois 353a66d815cSJean-Christophe Dubois switch (clock) { 354a66d815cSJean-Christophe Dubois case CLK_NONE: 355a66d815cSJean-Christophe Dubois break; 356a66d815cSJean-Christophe Dubois case CLK_IPG: 357a66d815cSJean-Christophe Dubois freq = imx6_ccm_get_ipg_clk(s); 358a66d815cSJean-Christophe Dubois break; 359a66d815cSJean-Christophe Dubois case CLK_IPG_HIGH: 360a66d815cSJean-Christophe Dubois freq = imx6_ccm_get_per_clk(s); 361a66d815cSJean-Christophe Dubois break; 362a66d815cSJean-Christophe Dubois case CLK_32k: 363a66d815cSJean-Christophe Dubois freq = CKIL_FREQ; 364a66d815cSJean-Christophe Dubois break; 36566542f63SJean-Christophe Dubois case CLK_HIGH: 36666542f63SJean-Christophe Dubois freq = 24000000; 36766542f63SJean-Christophe Dubois break; 36866542f63SJean-Christophe Dubois case CLK_HIGH_DIV: 36966542f63SJean-Christophe Dubois freq = 24000000 / 8; 37066542f63SJean-Christophe Dubois break; 371a66d815cSJean-Christophe Dubois default: 372a66d815cSJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", 373a66d815cSJean-Christophe Dubois TYPE_IMX6_CCM, __func__, clock); 374a66d815cSJean-Christophe Dubois break; 375a66d815cSJean-Christophe Dubois } 376a66d815cSJean-Christophe Dubois 3773839aff8SBernhard Beschow trace_imx6_ccm_get_clock_frequency(clock, freq); 378a66d815cSJean-Christophe Dubois 379a66d815cSJean-Christophe Dubois return freq; 380a66d815cSJean-Christophe Dubois } 381a66d815cSJean-Christophe Dubois 382a66d815cSJean-Christophe Dubois static void imx6_ccm_reset(DeviceState *dev) 383a66d815cSJean-Christophe Dubois { 384a66d815cSJean-Christophe Dubois IMX6CCMState *s = IMX6_CCM(dev); 385a66d815cSJean-Christophe Dubois 3863839aff8SBernhard Beschow trace_imx6_ccm_reset(); 387a66d815cSJean-Christophe Dubois 388a66d815cSJean-Christophe Dubois s->ccm[CCM_CCR] = 0x040116FF; 389a66d815cSJean-Christophe Dubois s->ccm[CCM_CCDR] = 0x00000000; 390a66d815cSJean-Christophe Dubois s->ccm[CCM_CSR] = 0x00000010; 391a66d815cSJean-Christophe Dubois s->ccm[CCM_CCSR] = 0x00000100; 392a66d815cSJean-Christophe Dubois s->ccm[CCM_CACRR] = 0x00000000; 393a66d815cSJean-Christophe Dubois s->ccm[CCM_CBCDR] = 0x00018D40; 394a66d815cSJean-Christophe Dubois s->ccm[CCM_CBCMR] = 0x00022324; 395a66d815cSJean-Christophe Dubois s->ccm[CCM_CSCMR1] = 0x00F00000; 396a66d815cSJean-Christophe Dubois s->ccm[CCM_CSCMR2] = 0x02B92F06; 397a66d815cSJean-Christophe Dubois s->ccm[CCM_CSCDR1] = 0x00490B00; 398a66d815cSJean-Christophe Dubois s->ccm[CCM_CS1CDR] = 0x0EC102C1; 399a66d815cSJean-Christophe Dubois s->ccm[CCM_CS2CDR] = 0x000736C1; 400a66d815cSJean-Christophe Dubois s->ccm[CCM_CDCDR] = 0x33F71F92; 401a66d815cSJean-Christophe Dubois s->ccm[CCM_CHSCCDR] = 0x0002A150; 402a66d815cSJean-Christophe Dubois s->ccm[CCM_CSCDR2] = 0x0002A150; 403a66d815cSJean-Christophe Dubois s->ccm[CCM_CSCDR3] = 0x00014841; 404a66d815cSJean-Christophe Dubois s->ccm[CCM_CDHIPR] = 0x00000000; 405a66d815cSJean-Christophe Dubois s->ccm[CCM_CTOR] = 0x00000000; 406a66d815cSJean-Christophe Dubois s->ccm[CCM_CLPCR] = 0x00000079; 407a66d815cSJean-Christophe Dubois s->ccm[CCM_CISR] = 0x00000000; 408a66d815cSJean-Christophe Dubois s->ccm[CCM_CIMR] = 0xFFFFFFFF; 409a66d815cSJean-Christophe Dubois s->ccm[CCM_CCOSR] = 0x000A0001; 410a66d815cSJean-Christophe Dubois s->ccm[CCM_CGPR] = 0x0000FE62; 411a66d815cSJean-Christophe Dubois s->ccm[CCM_CCGR0] = 0xFFFFFFFF; 412a66d815cSJean-Christophe Dubois s->ccm[CCM_CCGR1] = 0xFFFFFFFF; 413a66d815cSJean-Christophe Dubois s->ccm[CCM_CCGR2] = 0xFC3FFFFF; 414a66d815cSJean-Christophe Dubois s->ccm[CCM_CCGR3] = 0xFFFFFFFF; 415a66d815cSJean-Christophe Dubois s->ccm[CCM_CCGR4] = 0xFFFFFFFF; 416a66d815cSJean-Christophe Dubois s->ccm[CCM_CCGR5] = 0xFFFFFFFF; 417a66d815cSJean-Christophe Dubois s->ccm[CCM_CCGR6] = 0xFFFFFFFF; 418a66d815cSJean-Christophe Dubois s->ccm[CCM_CMEOR] = 0xFFFFFFFF; 419a66d815cSJean-Christophe Dubois 420a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ARM] = 0x00013042; 421a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000; 422a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000; 423a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001; 424a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000; 425a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000; 426a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012; 427a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006; 428a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100; 429a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C; 430a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C; 431a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100; 432a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447; 433a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_MLB] = 0x00010000; 434a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001; 435a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PFD_480] = 0x1311100C; 436a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PFD_528] = 0x1018101B; 437a66d815cSJean-Christophe Dubois 438a66d815cSJean-Christophe Dubois s->analog[PMU_REG_1P1] = 0x00001073; 439a66d815cSJean-Christophe Dubois s->analog[PMU_REG_3P0] = 0x00000F74; 440a66d815cSJean-Christophe Dubois s->analog[PMU_REG_2P5] = 0x00005071; 441a66d815cSJean-Christophe Dubois s->analog[PMU_REG_CORE] = 0x00402010; 44256a11a9bSBin Meng s->analog[PMU_MISC0] = 0x04000080; 443a66d815cSJean-Christophe Dubois s->analog[PMU_MISC1] = 0x00000000; 444a66d815cSJean-Christophe Dubois s->analog[PMU_MISC2] = 0x00272727; 445a66d815cSJean-Christophe Dubois 446a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x00000004; 447a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000; 448a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000; 449a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000; 450a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB1_MISC] = 0x00000002; 451a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x00000004; 452a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000; 453a66d815cSJean-Christophe Dubois s->analog[USB_ANALOG_USB2_MISC] = 0x00000002; 45445914971SBin Meng s->analog[USB_ANALOG_DIGPROG] = 0x00630000; 455a66d815cSJean-Christophe Dubois 456a66d815cSJean-Christophe Dubois /* all PLLs need to be locked */ 457a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK; 458a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK; 459a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK; 460a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK; 461a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK; 462a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK; 463a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_MLB] |= CCM_ANALOG_PLL_LOCK; 464a66d815cSJean-Christophe Dubois s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK; 465a66d815cSJean-Christophe Dubois } 466a66d815cSJean-Christophe Dubois 467a66d815cSJean-Christophe Dubois static uint64_t imx6_ccm_read(void *opaque, hwaddr offset, unsigned size) 468a66d815cSJean-Christophe Dubois { 469a66d815cSJean-Christophe Dubois uint32_t value = 0; 470a66d815cSJean-Christophe Dubois uint32_t index = offset >> 2; 471a66d815cSJean-Christophe Dubois IMX6CCMState *s = (IMX6CCMState *)opaque; 472a66d815cSJean-Christophe Dubois 473a66d815cSJean-Christophe Dubois value = s->ccm[index]; 474a66d815cSJean-Christophe Dubois 4753839aff8SBernhard Beschow trace_imx6_ccm_read(imx6_ccm_reg_name(index), value); 476a66d815cSJean-Christophe Dubois 477a66d815cSJean-Christophe Dubois return (uint64_t)value; 478a66d815cSJean-Christophe Dubois } 479a66d815cSJean-Christophe Dubois 480a66d815cSJean-Christophe Dubois static void imx6_ccm_write(void *opaque, hwaddr offset, uint64_t value, 481a66d815cSJean-Christophe Dubois unsigned size) 482a66d815cSJean-Christophe Dubois { 483a66d815cSJean-Christophe Dubois uint32_t index = offset >> 2; 484a66d815cSJean-Christophe Dubois IMX6CCMState *s = (IMX6CCMState *)opaque; 485a66d815cSJean-Christophe Dubois 4863839aff8SBernhard Beschow trace_imx6_ccm_write(imx6_ccm_reg_name(index), (uint32_t)value); 487a66d815cSJean-Christophe Dubois 488a66d815cSJean-Christophe Dubois /* 489a66d815cSJean-Christophe Dubois * We will do a better implementation later. In particular some bits 490a66d815cSJean-Christophe Dubois * cannot be written to. 491a66d815cSJean-Christophe Dubois */ 492a66d815cSJean-Christophe Dubois s->ccm[index] = (uint32_t)value; 493a66d815cSJean-Christophe Dubois } 494a66d815cSJean-Christophe Dubois 495a66d815cSJean-Christophe Dubois static uint64_t imx6_analog_read(void *opaque, hwaddr offset, unsigned size) 496a66d815cSJean-Christophe Dubois { 497a66d815cSJean-Christophe Dubois uint32_t value; 498a66d815cSJean-Christophe Dubois uint32_t index = offset >> 2; 499a66d815cSJean-Christophe Dubois IMX6CCMState *s = (IMX6CCMState *)opaque; 500a66d815cSJean-Christophe Dubois 501a66d815cSJean-Christophe Dubois switch (index) { 502a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 503a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 504a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 505a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 506a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 507a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 508a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_SET: 509a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 510a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 511a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 512a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 513a66d815cSJean-Christophe Dubois case PMU_MISC1_SET: 514a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 515a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_SET: 516a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_SET: 517a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_MISC_SET: 518a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_SET: 519a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_SET: 520a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_MISC_SET: 521a66d815cSJean-Christophe Dubois /* 522a66d815cSJean-Christophe Dubois * All REG_NAME_SET register access are in fact targeting the 523a66d815cSJean-Christophe Dubois * the REG_NAME register. 524a66d815cSJean-Christophe Dubois */ 525a66d815cSJean-Christophe Dubois value = s->analog[index - 1]; 526a66d815cSJean-Christophe Dubois break; 527a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 528a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 529a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 530a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 531a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 532a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 533a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_CLR: 534a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 535a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 536a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 537a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 538a66d815cSJean-Christophe Dubois case PMU_MISC1_CLR: 539a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 540a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_CLR: 541a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_CLR: 542a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_MISC_CLR: 543a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_CLR: 544a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_CLR: 545a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_MISC_CLR: 546a66d815cSJean-Christophe Dubois /* 547a66d815cSJean-Christophe Dubois * All REG_NAME_CLR register access are in fact targeting the 548a66d815cSJean-Christophe Dubois * the REG_NAME register. 549a66d815cSJean-Christophe Dubois */ 550a66d815cSJean-Christophe Dubois value = s->analog[index - 2]; 551a66d815cSJean-Christophe Dubois break; 552a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 553a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 554a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 555a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 556a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 557a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 558a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_TOG: 559a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 560a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 561a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 562a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 563a66d815cSJean-Christophe Dubois case PMU_MISC1_TOG: 564a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 565a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_TOG: 566a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_TOG: 567a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_MISC_TOG: 568a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_TOG: 569a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_TOG: 570a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_MISC_TOG: 571a66d815cSJean-Christophe Dubois /* 572a66d815cSJean-Christophe Dubois * All REG_NAME_TOG register access are in fact targeting the 573a66d815cSJean-Christophe Dubois * the REG_NAME register. 574a66d815cSJean-Christophe Dubois */ 575a66d815cSJean-Christophe Dubois value = s->analog[index - 3]; 576a66d815cSJean-Christophe Dubois break; 577a66d815cSJean-Christophe Dubois default: 578a66d815cSJean-Christophe Dubois value = s->analog[index]; 579a66d815cSJean-Christophe Dubois break; 580a66d815cSJean-Christophe Dubois } 581a66d815cSJean-Christophe Dubois 5823839aff8SBernhard Beschow trace_imx6_analog_read(imx6_analog_reg_name(index), value); 583a66d815cSJean-Christophe Dubois 584a66d815cSJean-Christophe Dubois return (uint64_t)value; 585a66d815cSJean-Christophe Dubois } 586a66d815cSJean-Christophe Dubois 587a66d815cSJean-Christophe Dubois static void imx6_analog_write(void *opaque, hwaddr offset, uint64_t value, 588a66d815cSJean-Christophe Dubois unsigned size) 589a66d815cSJean-Christophe Dubois { 590a66d815cSJean-Christophe Dubois uint32_t index = offset >> 2; 591a66d815cSJean-Christophe Dubois IMX6CCMState *s = (IMX6CCMState *)opaque; 592a66d815cSJean-Christophe Dubois 5933839aff8SBernhard Beschow trace_imx6_analog_write(imx6_analog_reg_name(index), (uint32_t)value); 594a66d815cSJean-Christophe Dubois 595a66d815cSJean-Christophe Dubois switch (index) { 596a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_SET: 597a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_SET: 598a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_SET: 599a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_SET: 600a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_SET: 601a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_SET: 602a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_SET: 603a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_SET: 604a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_SET: 605a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_SET: 606a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_SET: 607a66d815cSJean-Christophe Dubois case PMU_MISC1_SET: 608a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_SET: 609a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_SET: 610a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_SET: 611a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_MISC_SET: 612a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_SET: 613a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_SET: 614a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_MISC_SET: 615a66d815cSJean-Christophe Dubois /* 616a66d815cSJean-Christophe Dubois * All REG_NAME_SET register access are in fact targeting the 617a66d815cSJean-Christophe Dubois * the REG_NAME register. So we change the value of the 618a66d815cSJean-Christophe Dubois * REG_NAME register, setting bits passed in the value. 619a66d815cSJean-Christophe Dubois */ 620a66d815cSJean-Christophe Dubois s->analog[index - 1] |= value; 621a66d815cSJean-Christophe Dubois break; 622a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_CLR: 623a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_CLR: 624a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_CLR: 625a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_CLR: 626a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_CLR: 627a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_CLR: 628a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_CLR: 629a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_CLR: 630a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_CLR: 631a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_CLR: 632a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_CLR: 633a66d815cSJean-Christophe Dubois case PMU_MISC1_CLR: 634a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_CLR: 635a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_CLR: 636a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_CLR: 637a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_MISC_CLR: 638a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_CLR: 639a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_CLR: 640a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_MISC_CLR: 641a66d815cSJean-Christophe Dubois /* 642a66d815cSJean-Christophe Dubois * All REG_NAME_CLR register access are in fact targeting the 643a66d815cSJean-Christophe Dubois * the REG_NAME register. So we change the value of the 644a66d815cSJean-Christophe Dubois * REG_NAME register, unsetting bits passed in the value. 645a66d815cSJean-Christophe Dubois */ 646a66d815cSJean-Christophe Dubois s->analog[index - 2] &= ~value; 647a66d815cSJean-Christophe Dubois break; 648a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ARM_TOG: 649a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB1_TOG: 650a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_USB2_TOG: 651a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_SYS_TOG: 652a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_AUDIO_TOG: 653a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_VIDEO_TOG: 654a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_MLB_TOG: 655a66d815cSJean-Christophe Dubois case CCM_ANALOG_PLL_ENET_TOG: 656a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_480_TOG: 657a66d815cSJean-Christophe Dubois case CCM_ANALOG_PFD_528_TOG: 658a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC0_TOG: 659a66d815cSJean-Christophe Dubois case PMU_MISC1_TOG: 660a66d815cSJean-Christophe Dubois case CCM_ANALOG_MISC2_TOG: 661a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_VBUS_DETECT_TOG: 662a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_CHRG_DETECT_TOG: 663a66d815cSJean-Christophe Dubois case USB_ANALOG_USB1_MISC_TOG: 664a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_VBUS_DETECT_TOG: 665a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_CHRG_DETECT_TOG: 666a66d815cSJean-Christophe Dubois case USB_ANALOG_USB2_MISC_TOG: 667a66d815cSJean-Christophe Dubois /* 668a66d815cSJean-Christophe Dubois * All REG_NAME_TOG register access are in fact targeting the 669a66d815cSJean-Christophe Dubois * the REG_NAME register. So we change the value of the 670a66d815cSJean-Christophe Dubois * REG_NAME register, toggling bits passed in the value. 671a66d815cSJean-Christophe Dubois */ 672a66d815cSJean-Christophe Dubois s->analog[index - 3] ^= value; 673a66d815cSJean-Christophe Dubois break; 674a66d815cSJean-Christophe Dubois default: 675a66d815cSJean-Christophe Dubois /* 676a66d815cSJean-Christophe Dubois * We will do a better implementation later. In particular some bits 677a66d815cSJean-Christophe Dubois * cannot be written to. 678a66d815cSJean-Christophe Dubois */ 679a66d815cSJean-Christophe Dubois s->analog[index] = value; 680a66d815cSJean-Christophe Dubois break; 681a66d815cSJean-Christophe Dubois } 682a66d815cSJean-Christophe Dubois } 683a66d815cSJean-Christophe Dubois 684a66d815cSJean-Christophe Dubois static const struct MemoryRegionOps imx6_ccm_ops = { 685a66d815cSJean-Christophe Dubois .read = imx6_ccm_read, 686a66d815cSJean-Christophe Dubois .write = imx6_ccm_write, 687a66d815cSJean-Christophe Dubois .endianness = DEVICE_NATIVE_ENDIAN, 688a66d815cSJean-Christophe Dubois .valid = { 689a66d815cSJean-Christophe Dubois /* 690a66d815cSJean-Christophe Dubois * Our device would not work correctly if the guest was doing 691a66d815cSJean-Christophe Dubois * unaligned access. This might not be a limitation on the real 692a66d815cSJean-Christophe Dubois * device but in practice there is no reason for a guest to access 693a66d815cSJean-Christophe Dubois * this device unaligned. 694a66d815cSJean-Christophe Dubois */ 695a66d815cSJean-Christophe Dubois .min_access_size = 4, 696a66d815cSJean-Christophe Dubois .max_access_size = 4, 697a66d815cSJean-Christophe Dubois .unaligned = false, 698a66d815cSJean-Christophe Dubois }, 699a66d815cSJean-Christophe Dubois }; 700a66d815cSJean-Christophe Dubois 701a66d815cSJean-Christophe Dubois static const struct MemoryRegionOps imx6_analog_ops = { 702a66d815cSJean-Christophe Dubois .read = imx6_analog_read, 703a66d815cSJean-Christophe Dubois .write = imx6_analog_write, 704a66d815cSJean-Christophe Dubois .endianness = DEVICE_NATIVE_ENDIAN, 705a66d815cSJean-Christophe Dubois .valid = { 706a66d815cSJean-Christophe Dubois /* 707a66d815cSJean-Christophe Dubois * Our device would not work correctly if the guest was doing 708a66d815cSJean-Christophe Dubois * unaligned access. This might not be a limitation on the real 709a66d815cSJean-Christophe Dubois * device but in practice there is no reason for a guest to access 710a66d815cSJean-Christophe Dubois * this device unaligned. 711a66d815cSJean-Christophe Dubois */ 712a66d815cSJean-Christophe Dubois .min_access_size = 4, 713a66d815cSJean-Christophe Dubois .max_access_size = 4, 714a66d815cSJean-Christophe Dubois .unaligned = false, 715a66d815cSJean-Christophe Dubois }, 716a66d815cSJean-Christophe Dubois }; 717a66d815cSJean-Christophe Dubois 718a66d815cSJean-Christophe Dubois static void imx6_ccm_init(Object *obj) 719a66d815cSJean-Christophe Dubois { 720a66d815cSJean-Christophe Dubois DeviceState *dev = DEVICE(obj); 721a66d815cSJean-Christophe Dubois SysBusDevice *sd = SYS_BUS_DEVICE(obj); 722a66d815cSJean-Christophe Dubois IMX6CCMState *s = IMX6_CCM(obj); 723a66d815cSJean-Christophe Dubois 724a66d815cSJean-Christophe Dubois /* initialize a container for the all memory range */ 725a66d815cSJean-Christophe Dubois memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6_CCM, 0x5000); 726a66d815cSJean-Christophe Dubois 727a66d815cSJean-Christophe Dubois /* We initialize an IO memory region for the CCM part */ 728a66d815cSJean-Christophe Dubois memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6_ccm_ops, s, 729a66d815cSJean-Christophe Dubois TYPE_IMX6_CCM ".ccm", CCM_MAX * sizeof(uint32_t)); 730a66d815cSJean-Christophe Dubois 731a66d815cSJean-Christophe Dubois /* Add the CCM as a subregion at offset 0 */ 732a66d815cSJean-Christophe Dubois memory_region_add_subregion(&s->container, 0, &s->ioccm); 733a66d815cSJean-Christophe Dubois 734a66d815cSJean-Christophe Dubois /* We initialize an IO memory region for the ANALOG part */ 735a66d815cSJean-Christophe Dubois memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6_analog_ops, s, 736a66d815cSJean-Christophe Dubois TYPE_IMX6_CCM ".analog", 737a66d815cSJean-Christophe Dubois CCM_ANALOG_MAX * sizeof(uint32_t)); 738a66d815cSJean-Christophe Dubois 739a66d815cSJean-Christophe Dubois /* Add the ANALOG as a subregion at offset 0x4000 */ 740a66d815cSJean-Christophe Dubois memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog); 741a66d815cSJean-Christophe Dubois 742a66d815cSJean-Christophe Dubois sysbus_init_mmio(sd, &s->container); 743a66d815cSJean-Christophe Dubois } 744a66d815cSJean-Christophe Dubois 745a66d815cSJean-Christophe Dubois static void imx6_ccm_class_init(ObjectClass *klass, void *data) 746a66d815cSJean-Christophe Dubois { 747a66d815cSJean-Christophe Dubois DeviceClass *dc = DEVICE_CLASS(klass); 748a66d815cSJean-Christophe Dubois IMXCCMClass *ccm = IMX_CCM_CLASS(klass); 749a66d815cSJean-Christophe Dubois 750a66d815cSJean-Christophe Dubois dc->reset = imx6_ccm_reset; 751a66d815cSJean-Christophe Dubois dc->vmsd = &vmstate_imx6_ccm; 752a66d815cSJean-Christophe Dubois dc->desc = "i.MX6 Clock Control Module"; 753a66d815cSJean-Christophe Dubois 754a66d815cSJean-Christophe Dubois ccm->get_clock_frequency = imx6_ccm_get_clock_frequency; 755a66d815cSJean-Christophe Dubois } 756a66d815cSJean-Christophe Dubois 757a66d815cSJean-Christophe Dubois static const TypeInfo imx6_ccm_info = { 758a66d815cSJean-Christophe Dubois .name = TYPE_IMX6_CCM, 759a66d815cSJean-Christophe Dubois .parent = TYPE_IMX_CCM, 760a66d815cSJean-Christophe Dubois .instance_size = sizeof(IMX6CCMState), 761a66d815cSJean-Christophe Dubois .instance_init = imx6_ccm_init, 762a66d815cSJean-Christophe Dubois .class_init = imx6_ccm_class_init, 763a66d815cSJean-Christophe Dubois }; 764a66d815cSJean-Christophe Dubois 765a66d815cSJean-Christophe Dubois static void imx6_ccm_register_types(void) 766a66d815cSJean-Christophe Dubois { 767a66d815cSJean-Christophe Dubois type_register_static(&imx6_ccm_info); 768a66d815cSJean-Christophe Dubois } 769a66d815cSJean-Christophe Dubois 770a66d815cSJean-Christophe Dubois type_init(imx6_ccm_register_types) 771