1e9e0ef15SAndrey Smirnov /* 2e9e0ef15SAndrey Smirnov * Copyright (c) 2018, Impinj, Inc. 3e9e0ef15SAndrey Smirnov * 4e9e0ef15SAndrey Smirnov * i.MX7 CCM, PMU and ANALOG IP blocks emulation code 5e9e0ef15SAndrey Smirnov * 6e9e0ef15SAndrey Smirnov * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 7e9e0ef15SAndrey Smirnov * 8e9e0ef15SAndrey Smirnov * This work is licensed under the terms of the GNU GPL, version 2 or later. 9e9e0ef15SAndrey Smirnov * See the COPYING file in the top-level directory. 10e9e0ef15SAndrey Smirnov */ 11e9e0ef15SAndrey Smirnov 12e9e0ef15SAndrey Smirnov #include "qemu/osdep.h" 13e9e0ef15SAndrey Smirnov #include "qemu/log.h" 140b8fa32fSMarkus Armbruster #include "qemu/module.h" 15e9e0ef15SAndrey Smirnov 16e9e0ef15SAndrey Smirnov #include "hw/misc/imx7_ccm.h" 17d6454270SMarkus Armbruster #include "migration/vmstate.h" 18e9e0ef15SAndrey Smirnov 19*111c4c49SJean-Christophe Dubois #include "trace.h" 20*111c4c49SJean-Christophe Dubois 21*111c4c49SJean-Christophe Dubois #define CKIH_FREQ 24000000 /* 24MHz crystal input */ 22*111c4c49SJean-Christophe Dubois 23e9e0ef15SAndrey Smirnov static void imx7_analog_reset(DeviceState *dev) 24e9e0ef15SAndrey Smirnov { 25e9e0ef15SAndrey Smirnov IMX7AnalogState *s = IMX7_ANALOG(dev); 26e9e0ef15SAndrey Smirnov 27e9e0ef15SAndrey Smirnov memset(s->pmu, 0, sizeof(s->pmu)); 28e9e0ef15SAndrey Smirnov memset(s->analog, 0, sizeof(s->analog)); 29e9e0ef15SAndrey Smirnov 30e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_ARM] = 0x00002042; 31e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_DDR] = 0x0060302c; 32e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_DDR_SS] = 0x00000000; 33e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_DDR_NUM] = 0x06aaac4d; 34e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_DDR_DENOM] = 0x100003ec; 35e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_480] = 0x00002000; 36e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_480A] = 0x52605a56; 37e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_480B] = 0x52525216; 38e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_ENET] = 0x00001fc0; 39e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_AUDIO] = 0x0001301b; 40e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_AUDIO_SS] = 0x00000000; 41e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_AUDIO_NUM] = 0x05f5e100; 42e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_AUDIO_DENOM] = 0x2964619c; 43e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_VIDEO] = 0x0008201b; 44e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_VIDEO_SS] = 0x00000000; 45e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_VIDEO_NUM] = 0x0000f699; 46e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_VIDEO_DENOM] = 0x000f4240; 47e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_MISC0] = 0x00000000; 48e9e0ef15SAndrey Smirnov 49e9e0ef15SAndrey Smirnov /* all PLLs need to be locked */ 50e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_ARM] |= ANALOG_PLL_LOCK; 51e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_DDR] |= ANALOG_PLL_LOCK; 52e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_480] |= ANALOG_PLL_LOCK; 53e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_480A] |= ANALOG_PLL_LOCK; 54e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_480B] |= ANALOG_PLL_LOCK; 55e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_ENET] |= ANALOG_PLL_LOCK; 56e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_AUDIO] |= ANALOG_PLL_LOCK; 57e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_VIDEO] |= ANALOG_PLL_LOCK; 58e9e0ef15SAndrey Smirnov s->analog[ANALOG_PLL_MISC0] |= ANALOG_PLL_LOCK; 59e9e0ef15SAndrey Smirnov 60e9e0ef15SAndrey Smirnov /* 61e9e0ef15SAndrey Smirnov * Since I couldn't find any info about this in the reference 62e9e0ef15SAndrey Smirnov * manual the value of this register is based strictly on matching 63e9e0ef15SAndrey Smirnov * what Linux kernel expects it to be. 64e9e0ef15SAndrey Smirnov */ 65e9e0ef15SAndrey Smirnov s->analog[ANALOG_DIGPROG] = 0x720000; 66e9e0ef15SAndrey Smirnov /* 67e9e0ef15SAndrey Smirnov * Set revision to be 1.0 (Arbitrary choice, no particular 68e9e0ef15SAndrey Smirnov * reason). 69e9e0ef15SAndrey Smirnov */ 70e9e0ef15SAndrey Smirnov s->analog[ANALOG_DIGPROG] |= 0x000010; 71e9e0ef15SAndrey Smirnov } 72e9e0ef15SAndrey Smirnov 73e9e0ef15SAndrey Smirnov static void imx7_ccm_reset(DeviceState *dev) 74e9e0ef15SAndrey Smirnov { 75e9e0ef15SAndrey Smirnov IMX7CCMState *s = IMX7_CCM(dev); 76e9e0ef15SAndrey Smirnov 77e9e0ef15SAndrey Smirnov memset(s->ccm, 0, sizeof(s->ccm)); 78e9e0ef15SAndrey Smirnov } 79e9e0ef15SAndrey Smirnov 80e9e0ef15SAndrey Smirnov #define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t)) 81e9e0ef15SAndrey Smirnov #define CCM_BITOP(offset) ((offset) & (hwaddr)0xF) 82e9e0ef15SAndrey Smirnov 83e9e0ef15SAndrey Smirnov enum { 84e9e0ef15SAndrey Smirnov CCM_BITOP_NONE = 0x00, 85e9e0ef15SAndrey Smirnov CCM_BITOP_SET = 0x04, 86e9e0ef15SAndrey Smirnov CCM_BITOP_CLR = 0x08, 87e9e0ef15SAndrey Smirnov CCM_BITOP_TOG = 0x0C, 88e9e0ef15SAndrey Smirnov }; 89e9e0ef15SAndrey Smirnov 90e9e0ef15SAndrey Smirnov static uint64_t imx7_set_clr_tog_read(void *opaque, hwaddr offset, 91e9e0ef15SAndrey Smirnov unsigned size) 92e9e0ef15SAndrey Smirnov { 93e9e0ef15SAndrey Smirnov const uint32_t *mmio = opaque; 94e9e0ef15SAndrey Smirnov 95e9e0ef15SAndrey Smirnov return mmio[CCM_INDEX(offset)]; 96e9e0ef15SAndrey Smirnov } 97e9e0ef15SAndrey Smirnov 98e9e0ef15SAndrey Smirnov static void imx7_set_clr_tog_write(void *opaque, hwaddr offset, 99e9e0ef15SAndrey Smirnov uint64_t value, unsigned size) 100e9e0ef15SAndrey Smirnov { 101e9e0ef15SAndrey Smirnov const uint8_t bitop = CCM_BITOP(offset); 102e9e0ef15SAndrey Smirnov const uint32_t index = CCM_INDEX(offset); 103e9e0ef15SAndrey Smirnov uint32_t *mmio = opaque; 104e9e0ef15SAndrey Smirnov 105e9e0ef15SAndrey Smirnov switch (bitop) { 106e9e0ef15SAndrey Smirnov case CCM_BITOP_NONE: 107e9e0ef15SAndrey Smirnov mmio[index] = value; 108e9e0ef15SAndrey Smirnov break; 109e9e0ef15SAndrey Smirnov case CCM_BITOP_SET: 110e9e0ef15SAndrey Smirnov mmio[index] |= value; 111e9e0ef15SAndrey Smirnov break; 112e9e0ef15SAndrey Smirnov case CCM_BITOP_CLR: 113e9e0ef15SAndrey Smirnov mmio[index] &= ~value; 114e9e0ef15SAndrey Smirnov break; 115e9e0ef15SAndrey Smirnov case CCM_BITOP_TOG: 116e9e0ef15SAndrey Smirnov mmio[index] ^= value; 117e9e0ef15SAndrey Smirnov break; 118e9e0ef15SAndrey Smirnov }; 119e9e0ef15SAndrey Smirnov } 120e9e0ef15SAndrey Smirnov 121e9e0ef15SAndrey Smirnov static const struct MemoryRegionOps imx7_set_clr_tog_ops = { 122e9e0ef15SAndrey Smirnov .read = imx7_set_clr_tog_read, 123e9e0ef15SAndrey Smirnov .write = imx7_set_clr_tog_write, 124e9e0ef15SAndrey Smirnov .endianness = DEVICE_NATIVE_ENDIAN, 125e9e0ef15SAndrey Smirnov .impl = { 126e9e0ef15SAndrey Smirnov /* 127e9e0ef15SAndrey Smirnov * Our device would not work correctly if the guest was doing 128e9e0ef15SAndrey Smirnov * unaligned access. This might not be a limitation on the real 129e9e0ef15SAndrey Smirnov * device but in practice there is no reason for a guest to access 130e9e0ef15SAndrey Smirnov * this device unaligned. 131e9e0ef15SAndrey Smirnov */ 132e9e0ef15SAndrey Smirnov .min_access_size = 4, 133e9e0ef15SAndrey Smirnov .max_access_size = 4, 134e9e0ef15SAndrey Smirnov .unaligned = false, 135e9e0ef15SAndrey Smirnov }, 136e9e0ef15SAndrey Smirnov }; 137e9e0ef15SAndrey Smirnov 138735754aaSPrasad J Pandit static void imx7_digprog_write(void *opaque, hwaddr addr, 139735754aaSPrasad J Pandit uint64_t data, unsigned size) 140735754aaSPrasad J Pandit { 141735754aaSPrasad J Pandit qemu_log_mask(LOG_GUEST_ERROR, 142735754aaSPrasad J Pandit "Guest write to read-only ANALOG_DIGPROG register\n"); 143735754aaSPrasad J Pandit } 144735754aaSPrasad J Pandit 145e9e0ef15SAndrey Smirnov static const struct MemoryRegionOps imx7_digprog_ops = { 146e9e0ef15SAndrey Smirnov .read = imx7_set_clr_tog_read, 147735754aaSPrasad J Pandit .write = imx7_digprog_write, 148e9e0ef15SAndrey Smirnov .endianness = DEVICE_NATIVE_ENDIAN, 149e9e0ef15SAndrey Smirnov .impl = { 150e9e0ef15SAndrey Smirnov .min_access_size = 4, 151e9e0ef15SAndrey Smirnov .max_access_size = 4, 152e9e0ef15SAndrey Smirnov .unaligned = false, 153e9e0ef15SAndrey Smirnov }, 154e9e0ef15SAndrey Smirnov }; 155e9e0ef15SAndrey Smirnov 156e9e0ef15SAndrey Smirnov static void imx7_ccm_init(Object *obj) 157e9e0ef15SAndrey Smirnov { 158e9e0ef15SAndrey Smirnov SysBusDevice *sd = SYS_BUS_DEVICE(obj); 159e9e0ef15SAndrey Smirnov IMX7CCMState *s = IMX7_CCM(obj); 160e9e0ef15SAndrey Smirnov 161e9e0ef15SAndrey Smirnov memory_region_init_io(&s->iomem, 162e9e0ef15SAndrey Smirnov obj, 163e9e0ef15SAndrey Smirnov &imx7_set_clr_tog_ops, 164e9e0ef15SAndrey Smirnov s->ccm, 165e9e0ef15SAndrey Smirnov TYPE_IMX7_CCM ".ccm", 166e9e0ef15SAndrey Smirnov sizeof(s->ccm)); 167e9e0ef15SAndrey Smirnov 168e9e0ef15SAndrey Smirnov sysbus_init_mmio(sd, &s->iomem); 169e9e0ef15SAndrey Smirnov } 170e9e0ef15SAndrey Smirnov 171e9e0ef15SAndrey Smirnov static void imx7_analog_init(Object *obj) 172e9e0ef15SAndrey Smirnov { 173e9e0ef15SAndrey Smirnov SysBusDevice *sd = SYS_BUS_DEVICE(obj); 174e9e0ef15SAndrey Smirnov IMX7AnalogState *s = IMX7_ANALOG(obj); 175e9e0ef15SAndrey Smirnov 176e9e0ef15SAndrey Smirnov memory_region_init(&s->mmio.container, obj, TYPE_IMX7_ANALOG, 177e9e0ef15SAndrey Smirnov 0x10000); 178e9e0ef15SAndrey Smirnov 179e9e0ef15SAndrey Smirnov memory_region_init_io(&s->mmio.analog, 180e9e0ef15SAndrey Smirnov obj, 181e9e0ef15SAndrey Smirnov &imx7_set_clr_tog_ops, 182e9e0ef15SAndrey Smirnov s->analog, 183e9e0ef15SAndrey Smirnov TYPE_IMX7_ANALOG, 184e9e0ef15SAndrey Smirnov sizeof(s->analog)); 185e9e0ef15SAndrey Smirnov 186e9e0ef15SAndrey Smirnov memory_region_add_subregion(&s->mmio.container, 187e9e0ef15SAndrey Smirnov 0x60, &s->mmio.analog); 188e9e0ef15SAndrey Smirnov 189e9e0ef15SAndrey Smirnov memory_region_init_io(&s->mmio.pmu, 190e9e0ef15SAndrey Smirnov obj, 191e9e0ef15SAndrey Smirnov &imx7_set_clr_tog_ops, 192e9e0ef15SAndrey Smirnov s->pmu, 193e9e0ef15SAndrey Smirnov TYPE_IMX7_ANALOG ".pmu", 194e9e0ef15SAndrey Smirnov sizeof(s->pmu)); 195e9e0ef15SAndrey Smirnov 196e9e0ef15SAndrey Smirnov memory_region_add_subregion(&s->mmio.container, 197e9e0ef15SAndrey Smirnov 0x200, &s->mmio.pmu); 198e9e0ef15SAndrey Smirnov 199e9e0ef15SAndrey Smirnov memory_region_init_io(&s->mmio.digprog, 200e9e0ef15SAndrey Smirnov obj, 201e9e0ef15SAndrey Smirnov &imx7_digprog_ops, 202e9e0ef15SAndrey Smirnov &s->analog[ANALOG_DIGPROG], 203e9e0ef15SAndrey Smirnov TYPE_IMX7_ANALOG ".digprog", 204e9e0ef15SAndrey Smirnov sizeof(uint32_t)); 205e9e0ef15SAndrey Smirnov 206e9e0ef15SAndrey Smirnov memory_region_add_subregion_overlap(&s->mmio.container, 207e9e0ef15SAndrey Smirnov 0x800, &s->mmio.digprog, 10); 208e9e0ef15SAndrey Smirnov 209e9e0ef15SAndrey Smirnov 210e9e0ef15SAndrey Smirnov sysbus_init_mmio(sd, &s->mmio.container); 211e9e0ef15SAndrey Smirnov } 212e9e0ef15SAndrey Smirnov 213e9e0ef15SAndrey Smirnov static const VMStateDescription vmstate_imx7_ccm = { 214e9e0ef15SAndrey Smirnov .name = TYPE_IMX7_CCM, 215e9e0ef15SAndrey Smirnov .version_id = 1, 216e9e0ef15SAndrey Smirnov .minimum_version_id = 1, 217e9e0ef15SAndrey Smirnov .fields = (VMStateField[]) { 218e9e0ef15SAndrey Smirnov VMSTATE_UINT32_ARRAY(ccm, IMX7CCMState, CCM_MAX), 219e9e0ef15SAndrey Smirnov VMSTATE_END_OF_LIST() 220e9e0ef15SAndrey Smirnov }, 221e9e0ef15SAndrey Smirnov }; 222e9e0ef15SAndrey Smirnov 223e9e0ef15SAndrey Smirnov static uint32_t imx7_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) 224e9e0ef15SAndrey Smirnov { 225e9e0ef15SAndrey Smirnov /* 226*111c4c49SJean-Christophe Dubois * This function is "consumed" by GPT emulation code. Some clocks 227*111c4c49SJean-Christophe Dubois * have fixed frequencies and we can provide requested frequency 228*111c4c49SJean-Christophe Dubois * easily. However for CCM provided clocks (like IPG) each GPT 229*111c4c49SJean-Christophe Dubois * timer can have its own clock root. 230*111c4c49SJean-Christophe Dubois * This means we need additionnal information when calling this 231*111c4c49SJean-Christophe Dubois * function to know the requester's identity. 232e9e0ef15SAndrey Smirnov */ 233*111c4c49SJean-Christophe Dubois uint32_t freq = 0; 234*111c4c49SJean-Christophe Dubois 235*111c4c49SJean-Christophe Dubois switch (clock) { 236*111c4c49SJean-Christophe Dubois case CLK_NONE: 237*111c4c49SJean-Christophe Dubois break; 238*111c4c49SJean-Christophe Dubois case CLK_32k: 239*111c4c49SJean-Christophe Dubois freq = CKIL_FREQ; 240*111c4c49SJean-Christophe Dubois break; 241*111c4c49SJean-Christophe Dubois case CLK_HIGH: 242*111c4c49SJean-Christophe Dubois freq = CKIH_FREQ; 243*111c4c49SJean-Christophe Dubois break; 244*111c4c49SJean-Christophe Dubois case CLK_IPG: 245*111c4c49SJean-Christophe Dubois case CLK_IPG_HIGH: 246*111c4c49SJean-Christophe Dubois /* 247*111c4c49SJean-Christophe Dubois * For now we don't have a way to figure out the device this 248*111c4c49SJean-Christophe Dubois * function is called for. Until then the IPG derived clocks 249*111c4c49SJean-Christophe Dubois * are left unimplemented. 250*111c4c49SJean-Christophe Dubois */ 251*111c4c49SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Clock %d Not implemented\n", 252*111c4c49SJean-Christophe Dubois TYPE_IMX7_CCM, __func__, clock); 253*111c4c49SJean-Christophe Dubois break; 254*111c4c49SJean-Christophe Dubois default: 255*111c4c49SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", 256*111c4c49SJean-Christophe Dubois TYPE_IMX7_CCM, __func__, clock); 257*111c4c49SJean-Christophe Dubois break; 258*111c4c49SJean-Christophe Dubois } 259*111c4c49SJean-Christophe Dubois 260*111c4c49SJean-Christophe Dubois trace_ccm_clock_freq(clock, freq); 261*111c4c49SJean-Christophe Dubois 262*111c4c49SJean-Christophe Dubois return freq; 263e9e0ef15SAndrey Smirnov } 264e9e0ef15SAndrey Smirnov 265e9e0ef15SAndrey Smirnov static void imx7_ccm_class_init(ObjectClass *klass, void *data) 266e9e0ef15SAndrey Smirnov { 267e9e0ef15SAndrey Smirnov DeviceClass *dc = DEVICE_CLASS(klass); 268e9e0ef15SAndrey Smirnov IMXCCMClass *ccm = IMX_CCM_CLASS(klass); 269e9e0ef15SAndrey Smirnov 270e9e0ef15SAndrey Smirnov dc->reset = imx7_ccm_reset; 271e9e0ef15SAndrey Smirnov dc->vmsd = &vmstate_imx7_ccm; 272e9e0ef15SAndrey Smirnov dc->desc = "i.MX7 Clock Control Module"; 273e9e0ef15SAndrey Smirnov 274e9e0ef15SAndrey Smirnov ccm->get_clock_frequency = imx7_ccm_get_clock_frequency; 275e9e0ef15SAndrey Smirnov } 276e9e0ef15SAndrey Smirnov 277e9e0ef15SAndrey Smirnov static const TypeInfo imx7_ccm_info = { 278e9e0ef15SAndrey Smirnov .name = TYPE_IMX7_CCM, 279e9e0ef15SAndrey Smirnov .parent = TYPE_IMX_CCM, 280e9e0ef15SAndrey Smirnov .instance_size = sizeof(IMX7CCMState), 281e9e0ef15SAndrey Smirnov .instance_init = imx7_ccm_init, 282e9e0ef15SAndrey Smirnov .class_init = imx7_ccm_class_init, 283e9e0ef15SAndrey Smirnov }; 284e9e0ef15SAndrey Smirnov 285e9e0ef15SAndrey Smirnov static const VMStateDescription vmstate_imx7_analog = { 286e9e0ef15SAndrey Smirnov .name = TYPE_IMX7_ANALOG, 287e9e0ef15SAndrey Smirnov .version_id = 1, 288e9e0ef15SAndrey Smirnov .minimum_version_id = 1, 289e9e0ef15SAndrey Smirnov .fields = (VMStateField[]) { 290e9e0ef15SAndrey Smirnov VMSTATE_UINT32_ARRAY(analog, IMX7AnalogState, ANALOG_MAX), 291e9e0ef15SAndrey Smirnov VMSTATE_UINT32_ARRAY(pmu, IMX7AnalogState, PMU_MAX), 292e9e0ef15SAndrey Smirnov VMSTATE_END_OF_LIST() 293e9e0ef15SAndrey Smirnov }, 294e9e0ef15SAndrey Smirnov }; 295e9e0ef15SAndrey Smirnov 296e9e0ef15SAndrey Smirnov static void imx7_analog_class_init(ObjectClass *klass, void *data) 297e9e0ef15SAndrey Smirnov { 298e9e0ef15SAndrey Smirnov DeviceClass *dc = DEVICE_CLASS(klass); 299e9e0ef15SAndrey Smirnov 300e9e0ef15SAndrey Smirnov dc->reset = imx7_analog_reset; 301e9e0ef15SAndrey Smirnov dc->vmsd = &vmstate_imx7_analog; 302e9e0ef15SAndrey Smirnov dc->desc = "i.MX7 Analog Module"; 303e9e0ef15SAndrey Smirnov } 304e9e0ef15SAndrey Smirnov 305e9e0ef15SAndrey Smirnov static const TypeInfo imx7_analog_info = { 306e9e0ef15SAndrey Smirnov .name = TYPE_IMX7_ANALOG, 307e9e0ef15SAndrey Smirnov .parent = TYPE_SYS_BUS_DEVICE, 308e9e0ef15SAndrey Smirnov .instance_size = sizeof(IMX7AnalogState), 309e9e0ef15SAndrey Smirnov .instance_init = imx7_analog_init, 310e9e0ef15SAndrey Smirnov .class_init = imx7_analog_class_init, 311e9e0ef15SAndrey Smirnov }; 312e9e0ef15SAndrey Smirnov 313e9e0ef15SAndrey Smirnov static void imx7_ccm_register_type(void) 314e9e0ef15SAndrey Smirnov { 315e9e0ef15SAndrey Smirnov type_register_static(&imx7_ccm_info); 316e9e0ef15SAndrey Smirnov type_register_static(&imx7_analog_info); 317e9e0ef15SAndrey Smirnov } 318e9e0ef15SAndrey Smirnov type_init(imx7_ccm_register_type) 319