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