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