1*d6b55a0fSArnaud Minier /* 2*d6b55a0fSArnaud Minier * STM32L4X5 RCC (Reset and clock control) 3*d6b55a0fSArnaud Minier * 4*d6b55a0fSArnaud Minier * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr> 5*d6b55a0fSArnaud Minier * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr> 6*d6b55a0fSArnaud Minier * 7*d6b55a0fSArnaud Minier * SPDX-License-Identifier: GPL-2.0-or-later 8*d6b55a0fSArnaud Minier * 9*d6b55a0fSArnaud Minier * This work is licensed under the terms of the GNU GPL, version 2 or later. 10*d6b55a0fSArnaud Minier * See the COPYING file in the top-level directory. 11*d6b55a0fSArnaud Minier * 12*d6b55a0fSArnaud Minier * The reference used is the STMicroElectronics RM0351 Reference manual 13*d6b55a0fSArnaud Minier * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs. 14*d6b55a0fSArnaud Minier * 15*d6b55a0fSArnaud Minier * Inspired by the BCM2835 CPRMAN clock manager implementation by Luc Michel. 16*d6b55a0fSArnaud Minier */ 17*d6b55a0fSArnaud Minier 18*d6b55a0fSArnaud Minier #include "qemu/osdep.h" 19*d6b55a0fSArnaud Minier #include "qemu/log.h" 20*d6b55a0fSArnaud Minier #include "qemu/module.h" 21*d6b55a0fSArnaud Minier #include "qemu/timer.h" 22*d6b55a0fSArnaud Minier #include "qapi/error.h" 23*d6b55a0fSArnaud Minier #include "migration/vmstate.h" 24*d6b55a0fSArnaud Minier #include "hw/misc/stm32l4x5_rcc.h" 25*d6b55a0fSArnaud Minier #include "hw/misc/stm32l4x5_rcc_internals.h" 26*d6b55a0fSArnaud Minier #include "hw/clock.h" 27*d6b55a0fSArnaud Minier #include "hw/irq.h" 28*d6b55a0fSArnaud Minier #include "hw/qdev-clock.h" 29*d6b55a0fSArnaud Minier #include "hw/qdev-properties.h" 30*d6b55a0fSArnaud Minier #include "hw/qdev-properties-system.h" 31*d6b55a0fSArnaud Minier #include "trace.h" 32*d6b55a0fSArnaud Minier 33*d6b55a0fSArnaud Minier #define HSE_DEFAULT_FRQ 48000000ULL 34*d6b55a0fSArnaud Minier #define HSI_FRQ 16000000ULL 35*d6b55a0fSArnaud Minier #define MSI_DEFAULT_FRQ 4000000ULL 36*d6b55a0fSArnaud Minier #define LSE_FRQ 32768ULL 37*d6b55a0fSArnaud Minier #define LSI_FRQ 32000ULL 38*d6b55a0fSArnaud Minier 39*d6b55a0fSArnaud Minier static void rcc_update_irq(Stm32l4x5RccState *s) 40*d6b55a0fSArnaud Minier { 41*d6b55a0fSArnaud Minier if (s->cifr & CIFR_IRQ_MASK) { 42*d6b55a0fSArnaud Minier qemu_irq_raise(s->irq); 43*d6b55a0fSArnaud Minier } else { 44*d6b55a0fSArnaud Minier qemu_irq_lower(s->irq); 45*d6b55a0fSArnaud Minier } 46*d6b55a0fSArnaud Minier } 47*d6b55a0fSArnaud Minier 48*d6b55a0fSArnaud Minier static void stm32l4x5_rcc_reset_hold(Object *obj) 49*d6b55a0fSArnaud Minier { 50*d6b55a0fSArnaud Minier Stm32l4x5RccState *s = STM32L4X5_RCC(obj); 51*d6b55a0fSArnaud Minier s->cr = 0x00000063; 52*d6b55a0fSArnaud Minier /* 53*d6b55a0fSArnaud Minier * Factory-programmed calibration data 54*d6b55a0fSArnaud Minier * From the reference manual: 0x10XX 00XX 55*d6b55a0fSArnaud Minier * Value taken from a real card. 56*d6b55a0fSArnaud Minier */ 57*d6b55a0fSArnaud Minier s->icscr = 0x106E0082; 58*d6b55a0fSArnaud Minier s->cfgr = 0x0; 59*d6b55a0fSArnaud Minier s->pllcfgr = 0x00001000; 60*d6b55a0fSArnaud Minier s->pllsai1cfgr = 0x00001000; 61*d6b55a0fSArnaud Minier s->pllsai2cfgr = 0x00001000; 62*d6b55a0fSArnaud Minier s->cier = 0x0; 63*d6b55a0fSArnaud Minier s->cifr = 0x0; 64*d6b55a0fSArnaud Minier s->ahb1rstr = 0x0; 65*d6b55a0fSArnaud Minier s->ahb2rstr = 0x0; 66*d6b55a0fSArnaud Minier s->ahb3rstr = 0x0; 67*d6b55a0fSArnaud Minier s->apb1rstr1 = 0x0; 68*d6b55a0fSArnaud Minier s->apb1rstr2 = 0x0; 69*d6b55a0fSArnaud Minier s->apb2rstr = 0x0; 70*d6b55a0fSArnaud Minier s->ahb1enr = 0x00000100; 71*d6b55a0fSArnaud Minier s->ahb2enr = 0x0; 72*d6b55a0fSArnaud Minier s->ahb3enr = 0x0; 73*d6b55a0fSArnaud Minier s->apb1enr1 = 0x0; 74*d6b55a0fSArnaud Minier s->apb1enr2 = 0x0; 75*d6b55a0fSArnaud Minier s->apb2enr = 0x0; 76*d6b55a0fSArnaud Minier s->ahb1smenr = 0x00011303; 77*d6b55a0fSArnaud Minier s->ahb2smenr = 0x000532FF; 78*d6b55a0fSArnaud Minier s->ahb3smenr = 0x00000101; 79*d6b55a0fSArnaud Minier s->apb1smenr1 = 0xF2FECA3F; 80*d6b55a0fSArnaud Minier s->apb1smenr2 = 0x00000025; 81*d6b55a0fSArnaud Minier s->apb2smenr = 0x01677C01; 82*d6b55a0fSArnaud Minier s->ccipr = 0x0; 83*d6b55a0fSArnaud Minier s->bdcr = 0x0; 84*d6b55a0fSArnaud Minier s->csr = 0x0C000600; 85*d6b55a0fSArnaud Minier } 86*d6b55a0fSArnaud Minier 87*d6b55a0fSArnaud Minier static uint64_t stm32l4x5_rcc_read(void *opaque, hwaddr addr, 88*d6b55a0fSArnaud Minier unsigned int size) 89*d6b55a0fSArnaud Minier { 90*d6b55a0fSArnaud Minier Stm32l4x5RccState *s = opaque; 91*d6b55a0fSArnaud Minier uint64_t retvalue = 0; 92*d6b55a0fSArnaud Minier 93*d6b55a0fSArnaud Minier switch (addr) { 94*d6b55a0fSArnaud Minier case A_CR: 95*d6b55a0fSArnaud Minier retvalue = s->cr; 96*d6b55a0fSArnaud Minier break; 97*d6b55a0fSArnaud Minier case A_ICSCR: 98*d6b55a0fSArnaud Minier retvalue = s->icscr; 99*d6b55a0fSArnaud Minier break; 100*d6b55a0fSArnaud Minier case A_CFGR: 101*d6b55a0fSArnaud Minier retvalue = s->cfgr; 102*d6b55a0fSArnaud Minier break; 103*d6b55a0fSArnaud Minier case A_PLLCFGR: 104*d6b55a0fSArnaud Minier retvalue = s->pllcfgr; 105*d6b55a0fSArnaud Minier break; 106*d6b55a0fSArnaud Minier case A_PLLSAI1CFGR: 107*d6b55a0fSArnaud Minier retvalue = s->pllsai1cfgr; 108*d6b55a0fSArnaud Minier break; 109*d6b55a0fSArnaud Minier case A_PLLSAI2CFGR: 110*d6b55a0fSArnaud Minier retvalue = s->pllsai2cfgr; 111*d6b55a0fSArnaud Minier break; 112*d6b55a0fSArnaud Minier case A_CIER: 113*d6b55a0fSArnaud Minier retvalue = s->cier; 114*d6b55a0fSArnaud Minier break; 115*d6b55a0fSArnaud Minier case A_CIFR: 116*d6b55a0fSArnaud Minier retvalue = s->cifr; 117*d6b55a0fSArnaud Minier break; 118*d6b55a0fSArnaud Minier case A_CICR: 119*d6b55a0fSArnaud Minier /* CICR is write only, return the reset value = 0 */ 120*d6b55a0fSArnaud Minier break; 121*d6b55a0fSArnaud Minier case A_AHB1RSTR: 122*d6b55a0fSArnaud Minier retvalue = s->ahb1rstr; 123*d6b55a0fSArnaud Minier break; 124*d6b55a0fSArnaud Minier case A_AHB2RSTR: 125*d6b55a0fSArnaud Minier retvalue = s->ahb2rstr; 126*d6b55a0fSArnaud Minier break; 127*d6b55a0fSArnaud Minier case A_AHB3RSTR: 128*d6b55a0fSArnaud Minier retvalue = s->ahb3rstr; 129*d6b55a0fSArnaud Minier break; 130*d6b55a0fSArnaud Minier case A_APB1RSTR1: 131*d6b55a0fSArnaud Minier retvalue = s->apb1rstr1; 132*d6b55a0fSArnaud Minier break; 133*d6b55a0fSArnaud Minier case A_APB1RSTR2: 134*d6b55a0fSArnaud Minier retvalue = s->apb1rstr2; 135*d6b55a0fSArnaud Minier break; 136*d6b55a0fSArnaud Minier case A_APB2RSTR: 137*d6b55a0fSArnaud Minier retvalue = s->apb2rstr; 138*d6b55a0fSArnaud Minier break; 139*d6b55a0fSArnaud Minier case A_AHB1ENR: 140*d6b55a0fSArnaud Minier retvalue = s->ahb1enr; 141*d6b55a0fSArnaud Minier break; 142*d6b55a0fSArnaud Minier case A_AHB2ENR: 143*d6b55a0fSArnaud Minier retvalue = s->ahb2enr; 144*d6b55a0fSArnaud Minier break; 145*d6b55a0fSArnaud Minier case A_AHB3ENR: 146*d6b55a0fSArnaud Minier retvalue = s->ahb3enr; 147*d6b55a0fSArnaud Minier break; 148*d6b55a0fSArnaud Minier case A_APB1ENR1: 149*d6b55a0fSArnaud Minier retvalue = s->apb1enr1; 150*d6b55a0fSArnaud Minier break; 151*d6b55a0fSArnaud Minier case A_APB1ENR2: 152*d6b55a0fSArnaud Minier retvalue = s->apb1enr2; 153*d6b55a0fSArnaud Minier break; 154*d6b55a0fSArnaud Minier case A_APB2ENR: 155*d6b55a0fSArnaud Minier retvalue = s->apb2enr; 156*d6b55a0fSArnaud Minier break; 157*d6b55a0fSArnaud Minier case A_AHB1SMENR: 158*d6b55a0fSArnaud Minier retvalue = s->ahb1smenr; 159*d6b55a0fSArnaud Minier break; 160*d6b55a0fSArnaud Minier case A_AHB2SMENR: 161*d6b55a0fSArnaud Minier retvalue = s->ahb2smenr; 162*d6b55a0fSArnaud Minier break; 163*d6b55a0fSArnaud Minier case A_AHB3SMENR: 164*d6b55a0fSArnaud Minier retvalue = s->ahb3smenr; 165*d6b55a0fSArnaud Minier break; 166*d6b55a0fSArnaud Minier case A_APB1SMENR1: 167*d6b55a0fSArnaud Minier retvalue = s->apb1smenr1; 168*d6b55a0fSArnaud Minier break; 169*d6b55a0fSArnaud Minier case A_APB1SMENR2: 170*d6b55a0fSArnaud Minier retvalue = s->apb1smenr2; 171*d6b55a0fSArnaud Minier break; 172*d6b55a0fSArnaud Minier case A_APB2SMENR: 173*d6b55a0fSArnaud Minier retvalue = s->apb2smenr; 174*d6b55a0fSArnaud Minier break; 175*d6b55a0fSArnaud Minier case A_CCIPR: 176*d6b55a0fSArnaud Minier retvalue = s->ccipr; 177*d6b55a0fSArnaud Minier break; 178*d6b55a0fSArnaud Minier case A_BDCR: 179*d6b55a0fSArnaud Minier retvalue = s->bdcr; 180*d6b55a0fSArnaud Minier break; 181*d6b55a0fSArnaud Minier case A_CSR: 182*d6b55a0fSArnaud Minier retvalue = s->csr; 183*d6b55a0fSArnaud Minier break; 184*d6b55a0fSArnaud Minier default: 185*d6b55a0fSArnaud Minier qemu_log_mask(LOG_GUEST_ERROR, 186*d6b55a0fSArnaud Minier "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); 187*d6b55a0fSArnaud Minier break; 188*d6b55a0fSArnaud Minier } 189*d6b55a0fSArnaud Minier 190*d6b55a0fSArnaud Minier trace_stm32l4x5_rcc_read(addr, retvalue); 191*d6b55a0fSArnaud Minier 192*d6b55a0fSArnaud Minier return retvalue; 193*d6b55a0fSArnaud Minier } 194*d6b55a0fSArnaud Minier 195*d6b55a0fSArnaud Minier static void stm32l4x5_rcc_write(void *opaque, hwaddr addr, 196*d6b55a0fSArnaud Minier uint64_t val64, unsigned int size) 197*d6b55a0fSArnaud Minier { 198*d6b55a0fSArnaud Minier Stm32l4x5RccState *s = opaque; 199*d6b55a0fSArnaud Minier const uint32_t value = val64; 200*d6b55a0fSArnaud Minier 201*d6b55a0fSArnaud Minier trace_stm32l4x5_rcc_write(addr, value); 202*d6b55a0fSArnaud Minier 203*d6b55a0fSArnaud Minier switch (addr) { 204*d6b55a0fSArnaud Minier case A_CR: 205*d6b55a0fSArnaud Minier s->cr = (s->cr & CR_READ_SET_MASK) | 206*d6b55a0fSArnaud Minier (value & (CR_READ_SET_MASK | ~CR_READ_ONLY_MASK)); 207*d6b55a0fSArnaud Minier break; 208*d6b55a0fSArnaud Minier case A_ICSCR: 209*d6b55a0fSArnaud Minier s->icscr = value & ~ICSCR_READ_ONLY_MASK; 210*d6b55a0fSArnaud Minier break; 211*d6b55a0fSArnaud Minier case A_CFGR: 212*d6b55a0fSArnaud Minier s->cfgr = value & ~CFGR_READ_ONLY_MASK; 213*d6b55a0fSArnaud Minier break; 214*d6b55a0fSArnaud Minier case A_PLLCFGR: 215*d6b55a0fSArnaud Minier s->pllcfgr = value; 216*d6b55a0fSArnaud Minier break; 217*d6b55a0fSArnaud Minier case A_PLLSAI1CFGR: 218*d6b55a0fSArnaud Minier s->pllsai1cfgr = value; 219*d6b55a0fSArnaud Minier break; 220*d6b55a0fSArnaud Minier case A_PLLSAI2CFGR: 221*d6b55a0fSArnaud Minier s->pllsai2cfgr = value; 222*d6b55a0fSArnaud Minier break; 223*d6b55a0fSArnaud Minier case A_CIER: 224*d6b55a0fSArnaud Minier s->cier = value; 225*d6b55a0fSArnaud Minier break; 226*d6b55a0fSArnaud Minier case A_CIFR: 227*d6b55a0fSArnaud Minier qemu_log_mask(LOG_GUEST_ERROR, 228*d6b55a0fSArnaud Minier "%s: Write attempt into read-only register (CIFR) 0x%"PRIx32"\n", 229*d6b55a0fSArnaud Minier __func__, value); 230*d6b55a0fSArnaud Minier break; 231*d6b55a0fSArnaud Minier case A_CICR: 232*d6b55a0fSArnaud Minier /* Clear interrupt flags by writing a 1 to the CICR register */ 233*d6b55a0fSArnaud Minier s->cifr &= ~value; 234*d6b55a0fSArnaud Minier rcc_update_irq(s); 235*d6b55a0fSArnaud Minier break; 236*d6b55a0fSArnaud Minier /* Reset behaviors are not implemented */ 237*d6b55a0fSArnaud Minier case A_AHB1RSTR: 238*d6b55a0fSArnaud Minier s->ahb1rstr = value; 239*d6b55a0fSArnaud Minier break; 240*d6b55a0fSArnaud Minier case A_AHB2RSTR: 241*d6b55a0fSArnaud Minier s->ahb2rstr = value; 242*d6b55a0fSArnaud Minier break; 243*d6b55a0fSArnaud Minier case A_AHB3RSTR: 244*d6b55a0fSArnaud Minier s->ahb3rstr = value; 245*d6b55a0fSArnaud Minier break; 246*d6b55a0fSArnaud Minier case A_APB1RSTR1: 247*d6b55a0fSArnaud Minier s->apb1rstr1 = value; 248*d6b55a0fSArnaud Minier break; 249*d6b55a0fSArnaud Minier case A_APB1RSTR2: 250*d6b55a0fSArnaud Minier s->apb1rstr2 = value; 251*d6b55a0fSArnaud Minier break; 252*d6b55a0fSArnaud Minier case A_APB2RSTR: 253*d6b55a0fSArnaud Minier s->apb2rstr = value; 254*d6b55a0fSArnaud Minier break; 255*d6b55a0fSArnaud Minier case A_AHB1ENR: 256*d6b55a0fSArnaud Minier s->ahb1enr = value; 257*d6b55a0fSArnaud Minier break; 258*d6b55a0fSArnaud Minier case A_AHB2ENR: 259*d6b55a0fSArnaud Minier s->ahb2enr = value; 260*d6b55a0fSArnaud Minier break; 261*d6b55a0fSArnaud Minier case A_AHB3ENR: 262*d6b55a0fSArnaud Minier s->ahb3enr = value; 263*d6b55a0fSArnaud Minier break; 264*d6b55a0fSArnaud Minier case A_APB1ENR1: 265*d6b55a0fSArnaud Minier s->apb1enr1 = value; 266*d6b55a0fSArnaud Minier break; 267*d6b55a0fSArnaud Minier case A_APB1ENR2: 268*d6b55a0fSArnaud Minier s->apb1enr2 = value; 269*d6b55a0fSArnaud Minier break; 270*d6b55a0fSArnaud Minier case A_APB2ENR: 271*d6b55a0fSArnaud Minier s->apb2enr = (s->apb2enr & APB2ENR_READ_SET_MASK) | value; 272*d6b55a0fSArnaud Minier break; 273*d6b55a0fSArnaud Minier /* Behaviors for Sleep and Stop modes are not implemented */ 274*d6b55a0fSArnaud Minier case A_AHB1SMENR: 275*d6b55a0fSArnaud Minier s->ahb1smenr = value; 276*d6b55a0fSArnaud Minier break; 277*d6b55a0fSArnaud Minier case A_AHB2SMENR: 278*d6b55a0fSArnaud Minier s->ahb2smenr = value; 279*d6b55a0fSArnaud Minier break; 280*d6b55a0fSArnaud Minier case A_AHB3SMENR: 281*d6b55a0fSArnaud Minier s->ahb3smenr = value; 282*d6b55a0fSArnaud Minier break; 283*d6b55a0fSArnaud Minier case A_APB1SMENR1: 284*d6b55a0fSArnaud Minier s->apb1smenr1 = value; 285*d6b55a0fSArnaud Minier break; 286*d6b55a0fSArnaud Minier case A_APB1SMENR2: 287*d6b55a0fSArnaud Minier s->apb1smenr2 = value; 288*d6b55a0fSArnaud Minier break; 289*d6b55a0fSArnaud Minier case A_APB2SMENR: 290*d6b55a0fSArnaud Minier s->apb2smenr = value; 291*d6b55a0fSArnaud Minier break; 292*d6b55a0fSArnaud Minier case A_CCIPR: 293*d6b55a0fSArnaud Minier s->ccipr = value; 294*d6b55a0fSArnaud Minier break; 295*d6b55a0fSArnaud Minier case A_BDCR: 296*d6b55a0fSArnaud Minier s->bdcr = value & ~BDCR_READ_ONLY_MASK; 297*d6b55a0fSArnaud Minier break; 298*d6b55a0fSArnaud Minier case A_CSR: 299*d6b55a0fSArnaud Minier s->csr = value & ~CSR_READ_ONLY_MASK; 300*d6b55a0fSArnaud Minier break; 301*d6b55a0fSArnaud Minier default: 302*d6b55a0fSArnaud Minier qemu_log_mask(LOG_GUEST_ERROR, 303*d6b55a0fSArnaud Minier "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); 304*d6b55a0fSArnaud Minier } 305*d6b55a0fSArnaud Minier } 306*d6b55a0fSArnaud Minier 307*d6b55a0fSArnaud Minier static const MemoryRegionOps stm32l4x5_rcc_ops = { 308*d6b55a0fSArnaud Minier .read = stm32l4x5_rcc_read, 309*d6b55a0fSArnaud Minier .write = stm32l4x5_rcc_write, 310*d6b55a0fSArnaud Minier .endianness = DEVICE_NATIVE_ENDIAN, 311*d6b55a0fSArnaud Minier .valid = { 312*d6b55a0fSArnaud Minier .max_access_size = 4, 313*d6b55a0fSArnaud Minier .min_access_size = 4, 314*d6b55a0fSArnaud Minier .unaligned = false 315*d6b55a0fSArnaud Minier }, 316*d6b55a0fSArnaud Minier .impl = { 317*d6b55a0fSArnaud Minier .max_access_size = 4, 318*d6b55a0fSArnaud Minier .min_access_size = 4, 319*d6b55a0fSArnaud Minier .unaligned = false 320*d6b55a0fSArnaud Minier }, 321*d6b55a0fSArnaud Minier }; 322*d6b55a0fSArnaud Minier 323*d6b55a0fSArnaud Minier static const ClockPortInitArray stm32l4x5_rcc_clocks = { 324*d6b55a0fSArnaud Minier QDEV_CLOCK_IN(Stm32l4x5RccState, hsi16_rc, NULL, 0), 325*d6b55a0fSArnaud Minier QDEV_CLOCK_IN(Stm32l4x5RccState, msi_rc, NULL, 0), 326*d6b55a0fSArnaud Minier QDEV_CLOCK_IN(Stm32l4x5RccState, hse, NULL, 0), 327*d6b55a0fSArnaud Minier QDEV_CLOCK_IN(Stm32l4x5RccState, lsi_rc, NULL, 0), 328*d6b55a0fSArnaud Minier QDEV_CLOCK_IN(Stm32l4x5RccState, lse_crystal, NULL, 0), 329*d6b55a0fSArnaud Minier QDEV_CLOCK_IN(Stm32l4x5RccState, sai1_extclk, NULL, 0), 330*d6b55a0fSArnaud Minier QDEV_CLOCK_IN(Stm32l4x5RccState, sai2_extclk, NULL, 0), 331*d6b55a0fSArnaud Minier QDEV_CLOCK_END 332*d6b55a0fSArnaud Minier }; 333*d6b55a0fSArnaud Minier 334*d6b55a0fSArnaud Minier 335*d6b55a0fSArnaud Minier static void stm32l4x5_rcc_init(Object *obj) 336*d6b55a0fSArnaud Minier { 337*d6b55a0fSArnaud Minier Stm32l4x5RccState *s = STM32L4X5_RCC(obj); 338*d6b55a0fSArnaud Minier 339*d6b55a0fSArnaud Minier sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); 340*d6b55a0fSArnaud Minier 341*d6b55a0fSArnaud Minier memory_region_init_io(&s->mmio, obj, &stm32l4x5_rcc_ops, s, 342*d6b55a0fSArnaud Minier TYPE_STM32L4X5_RCC, 0x400); 343*d6b55a0fSArnaud Minier sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); 344*d6b55a0fSArnaud Minier 345*d6b55a0fSArnaud Minier qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks); 346*d6b55a0fSArnaud Minier 347*d6b55a0fSArnaud Minier s->gnd = clock_new(obj, "gnd"); 348*d6b55a0fSArnaud Minier } 349*d6b55a0fSArnaud Minier 350*d6b55a0fSArnaud Minier static const VMStateDescription vmstate_stm32l4x5_rcc = { 351*d6b55a0fSArnaud Minier .name = TYPE_STM32L4X5_RCC, 352*d6b55a0fSArnaud Minier .version_id = 1, 353*d6b55a0fSArnaud Minier .minimum_version_id = 1, 354*d6b55a0fSArnaud Minier .fields = (VMStateField[]) { 355*d6b55a0fSArnaud Minier VMSTATE_UINT32(cr, Stm32l4x5RccState), 356*d6b55a0fSArnaud Minier VMSTATE_UINT32(icscr, Stm32l4x5RccState), 357*d6b55a0fSArnaud Minier VMSTATE_UINT32(cfgr, Stm32l4x5RccState), 358*d6b55a0fSArnaud Minier VMSTATE_UINT32(pllcfgr, Stm32l4x5RccState), 359*d6b55a0fSArnaud Minier VMSTATE_UINT32(pllsai1cfgr, Stm32l4x5RccState), 360*d6b55a0fSArnaud Minier VMSTATE_UINT32(pllsai2cfgr, Stm32l4x5RccState), 361*d6b55a0fSArnaud Minier VMSTATE_UINT32(cier, Stm32l4x5RccState), 362*d6b55a0fSArnaud Minier VMSTATE_UINT32(cifr, Stm32l4x5RccState), 363*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb1rstr, Stm32l4x5RccState), 364*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb2rstr, Stm32l4x5RccState), 365*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb3rstr, Stm32l4x5RccState), 366*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb1rstr1, Stm32l4x5RccState), 367*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb1rstr2, Stm32l4x5RccState), 368*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb2rstr, Stm32l4x5RccState), 369*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb1enr, Stm32l4x5RccState), 370*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb2enr, Stm32l4x5RccState), 371*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb3enr, Stm32l4x5RccState), 372*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb1enr1, Stm32l4x5RccState), 373*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb1enr2, Stm32l4x5RccState), 374*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb2enr, Stm32l4x5RccState), 375*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb1smenr, Stm32l4x5RccState), 376*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb2smenr, Stm32l4x5RccState), 377*d6b55a0fSArnaud Minier VMSTATE_UINT32(ahb3smenr, Stm32l4x5RccState), 378*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb1smenr1, Stm32l4x5RccState), 379*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb1smenr2, Stm32l4x5RccState), 380*d6b55a0fSArnaud Minier VMSTATE_UINT32(apb2smenr, Stm32l4x5RccState), 381*d6b55a0fSArnaud Minier VMSTATE_UINT32(ccipr, Stm32l4x5RccState), 382*d6b55a0fSArnaud Minier VMSTATE_UINT32(bdcr, Stm32l4x5RccState), 383*d6b55a0fSArnaud Minier VMSTATE_UINT32(csr, Stm32l4x5RccState), 384*d6b55a0fSArnaud Minier VMSTATE_CLOCK(hsi16_rc, Stm32l4x5RccState), 385*d6b55a0fSArnaud Minier VMSTATE_CLOCK(msi_rc, Stm32l4x5RccState), 386*d6b55a0fSArnaud Minier VMSTATE_CLOCK(hse, Stm32l4x5RccState), 387*d6b55a0fSArnaud Minier VMSTATE_CLOCK(lsi_rc, Stm32l4x5RccState), 388*d6b55a0fSArnaud Minier VMSTATE_CLOCK(lse_crystal, Stm32l4x5RccState), 389*d6b55a0fSArnaud Minier VMSTATE_CLOCK(sai1_extclk, Stm32l4x5RccState), 390*d6b55a0fSArnaud Minier VMSTATE_CLOCK(sai2_extclk, Stm32l4x5RccState), 391*d6b55a0fSArnaud Minier VMSTATE_END_OF_LIST() 392*d6b55a0fSArnaud Minier } 393*d6b55a0fSArnaud Minier }; 394*d6b55a0fSArnaud Minier 395*d6b55a0fSArnaud Minier 396*d6b55a0fSArnaud Minier static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) 397*d6b55a0fSArnaud Minier { 398*d6b55a0fSArnaud Minier Stm32l4x5RccState *s = STM32L4X5_RCC(dev); 399*d6b55a0fSArnaud Minier 400*d6b55a0fSArnaud Minier if (s->hse_frequency < 4000000ULL || 401*d6b55a0fSArnaud Minier s->hse_frequency > 48000000ULL) { 402*d6b55a0fSArnaud Minier error_setg(errp, 403*d6b55a0fSArnaud Minier "HSE frequency is outside of the allowed [4-48]Mhz range: %" PRIx64 "", 404*d6b55a0fSArnaud Minier s->hse_frequency); 405*d6b55a0fSArnaud Minier return; 406*d6b55a0fSArnaud Minier } 407*d6b55a0fSArnaud Minier 408*d6b55a0fSArnaud Minier clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ); 409*d6b55a0fSArnaud Minier clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency); 410*d6b55a0fSArnaud Minier clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency); 411*d6b55a0fSArnaud Minier clock_update(s->gnd, 0); 412*d6b55a0fSArnaud Minier } 413*d6b55a0fSArnaud Minier 414*d6b55a0fSArnaud Minier static Property stm32l4x5_rcc_properties[] = { 415*d6b55a0fSArnaud Minier DEFINE_PROP_UINT64("hse_frequency", Stm32l4x5RccState, 416*d6b55a0fSArnaud Minier hse_frequency, HSE_DEFAULT_FRQ), 417*d6b55a0fSArnaud Minier DEFINE_PROP_UINT64("sai1_extclk_frequency", Stm32l4x5RccState, 418*d6b55a0fSArnaud Minier sai1_extclk_frequency, 0), 419*d6b55a0fSArnaud Minier DEFINE_PROP_UINT64("sai2_extclk_frequency", Stm32l4x5RccState, 420*d6b55a0fSArnaud Minier sai2_extclk_frequency, 0), 421*d6b55a0fSArnaud Minier DEFINE_PROP_END_OF_LIST(), 422*d6b55a0fSArnaud Minier }; 423*d6b55a0fSArnaud Minier 424*d6b55a0fSArnaud Minier static void stm32l4x5_rcc_class_init(ObjectClass *klass, void *data) 425*d6b55a0fSArnaud Minier { 426*d6b55a0fSArnaud Minier DeviceClass *dc = DEVICE_CLASS(klass); 427*d6b55a0fSArnaud Minier ResettableClass *rc = RESETTABLE_CLASS(klass); 428*d6b55a0fSArnaud Minier 429*d6b55a0fSArnaud Minier 430*d6b55a0fSArnaud Minier rc->phases.hold = stm32l4x5_rcc_reset_hold; 431*d6b55a0fSArnaud Minier device_class_set_props(dc, stm32l4x5_rcc_properties); 432*d6b55a0fSArnaud Minier dc->realize = stm32l4x5_rcc_realize; 433*d6b55a0fSArnaud Minier dc->vmsd = &vmstate_stm32l4x5_rcc; 434*d6b55a0fSArnaud Minier } 435*d6b55a0fSArnaud Minier 436*d6b55a0fSArnaud Minier static const TypeInfo stm32l4x5_rcc_types[] = { 437*d6b55a0fSArnaud Minier { 438*d6b55a0fSArnaud Minier .name = TYPE_STM32L4X5_RCC, 439*d6b55a0fSArnaud Minier .parent = TYPE_SYS_BUS_DEVICE, 440*d6b55a0fSArnaud Minier .instance_size = sizeof(Stm32l4x5RccState), 441*d6b55a0fSArnaud Minier .instance_init = stm32l4x5_rcc_init, 442*d6b55a0fSArnaud Minier .class_init = stm32l4x5_rcc_class_init, 443*d6b55a0fSArnaud Minier } 444*d6b55a0fSArnaud Minier }; 445*d6b55a0fSArnaud Minier 446*d6b55a0fSArnaud Minier DEFINE_TYPES(stm32l4x5_rcc_types) 447