1*30b2f870SAndrey Smirnov /* 2*30b2f870SAndrey Smirnov * Copyright (c) 2018, Impinj, Inc. 3*30b2f870SAndrey Smirnov * 4*30b2f870SAndrey Smirnov * i.MX7 GPR IP block emulation code 5*30b2f870SAndrey Smirnov * 6*30b2f870SAndrey Smirnov * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 7*30b2f870SAndrey Smirnov * 8*30b2f870SAndrey Smirnov * This work is licensed under the terms of the GNU GPL, version 2 or later. 9*30b2f870SAndrey Smirnov * See the COPYING file in the top-level directory. 10*30b2f870SAndrey Smirnov * 11*30b2f870SAndrey Smirnov * Bare minimum emulation code needed to support being able to shut 12*30b2f870SAndrey Smirnov * down linux guest gracefully. 13*30b2f870SAndrey Smirnov */ 14*30b2f870SAndrey Smirnov 15*30b2f870SAndrey Smirnov #include "qemu/osdep.h" 16*30b2f870SAndrey Smirnov #include "hw/misc/imx7_gpr.h" 17*30b2f870SAndrey Smirnov #include "qemu/log.h" 18*30b2f870SAndrey Smirnov #include "sysemu/sysemu.h" 19*30b2f870SAndrey Smirnov 20*30b2f870SAndrey Smirnov #include "trace.h" 21*30b2f870SAndrey Smirnov 22*30b2f870SAndrey Smirnov enum IMX7GPRRegisters { 23*30b2f870SAndrey Smirnov IOMUXC_GPR0 = 0x00, 24*30b2f870SAndrey Smirnov IOMUXC_GPR1 = 0x04, 25*30b2f870SAndrey Smirnov IOMUXC_GPR2 = 0x08, 26*30b2f870SAndrey Smirnov IOMUXC_GPR3 = 0x0c, 27*30b2f870SAndrey Smirnov IOMUXC_GPR4 = 0x10, 28*30b2f870SAndrey Smirnov IOMUXC_GPR5 = 0x14, 29*30b2f870SAndrey Smirnov IOMUXC_GPR6 = 0x18, 30*30b2f870SAndrey Smirnov IOMUXC_GPR7 = 0x1c, 31*30b2f870SAndrey Smirnov IOMUXC_GPR8 = 0x20, 32*30b2f870SAndrey Smirnov IOMUXC_GPR9 = 0x24, 33*30b2f870SAndrey Smirnov IOMUXC_GPR10 = 0x28, 34*30b2f870SAndrey Smirnov IOMUXC_GPR11 = 0x2c, 35*30b2f870SAndrey Smirnov IOMUXC_GPR12 = 0x30, 36*30b2f870SAndrey Smirnov IOMUXC_GPR13 = 0x34, 37*30b2f870SAndrey Smirnov IOMUXC_GPR14 = 0x38, 38*30b2f870SAndrey Smirnov IOMUXC_GPR15 = 0x3c, 39*30b2f870SAndrey Smirnov IOMUXC_GPR16 = 0x40, 40*30b2f870SAndrey Smirnov IOMUXC_GPR17 = 0x44, 41*30b2f870SAndrey Smirnov IOMUXC_GPR18 = 0x48, 42*30b2f870SAndrey Smirnov IOMUXC_GPR19 = 0x4c, 43*30b2f870SAndrey Smirnov IOMUXC_GPR20 = 0x50, 44*30b2f870SAndrey Smirnov IOMUXC_GPR21 = 0x54, 45*30b2f870SAndrey Smirnov IOMUXC_GPR22 = 0x58, 46*30b2f870SAndrey Smirnov }; 47*30b2f870SAndrey Smirnov 48*30b2f870SAndrey Smirnov #define IMX7D_GPR1_IRQ_MASK BIT(12) 49*30b2f870SAndrey Smirnov #define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK BIT(13) 50*30b2f870SAndrey Smirnov #define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK BIT(14) 51*30b2f870SAndrey Smirnov #define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13) 52*30b2f870SAndrey Smirnov #define IMX7D_GPR1_ENET1_CLK_DIR_MASK BIT(17) 53*30b2f870SAndrey Smirnov #define IMX7D_GPR1_ENET2_CLK_DIR_MASK BIT(18) 54*30b2f870SAndrey Smirnov #define IMX7D_GPR1_ENET_CLK_DIR_MASK (0x3 << 17) 55*30b2f870SAndrey Smirnov 56*30b2f870SAndrey Smirnov #define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI BIT(4) 57*30b2f870SAndrey Smirnov #define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL BIT(5) 58*30b2f870SAndrey Smirnov #define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED BIT(31) 59*30b2f870SAndrey Smirnov 60*30b2f870SAndrey Smirnov 61*30b2f870SAndrey Smirnov static uint64_t imx7_gpr_read(void *opaque, hwaddr offset, unsigned size) 62*30b2f870SAndrey Smirnov { 63*30b2f870SAndrey Smirnov trace_imx7_gpr_read(offset); 64*30b2f870SAndrey Smirnov 65*30b2f870SAndrey Smirnov if (offset == IOMUXC_GPR22) { 66*30b2f870SAndrey Smirnov return IMX7D_GPR22_PCIE_PHY_PLL_LOCKED; 67*30b2f870SAndrey Smirnov } 68*30b2f870SAndrey Smirnov 69*30b2f870SAndrey Smirnov return 0; 70*30b2f870SAndrey Smirnov } 71*30b2f870SAndrey Smirnov 72*30b2f870SAndrey Smirnov static void imx7_gpr_write(void *opaque, hwaddr offset, 73*30b2f870SAndrey Smirnov uint64_t v, unsigned size) 74*30b2f870SAndrey Smirnov { 75*30b2f870SAndrey Smirnov trace_imx7_gpr_write(offset, v); 76*30b2f870SAndrey Smirnov } 77*30b2f870SAndrey Smirnov 78*30b2f870SAndrey Smirnov static const struct MemoryRegionOps imx7_gpr_ops = { 79*30b2f870SAndrey Smirnov .read = imx7_gpr_read, 80*30b2f870SAndrey Smirnov .write = imx7_gpr_write, 81*30b2f870SAndrey Smirnov .endianness = DEVICE_NATIVE_ENDIAN, 82*30b2f870SAndrey Smirnov .impl = { 83*30b2f870SAndrey Smirnov /* 84*30b2f870SAndrey Smirnov * Our device would not work correctly if the guest was doing 85*30b2f870SAndrey Smirnov * unaligned access. This might not be a limitation on the 86*30b2f870SAndrey Smirnov * real device but in practice there is no reason for a guest 87*30b2f870SAndrey Smirnov * to access this device unaligned. 88*30b2f870SAndrey Smirnov */ 89*30b2f870SAndrey Smirnov .min_access_size = 4, 90*30b2f870SAndrey Smirnov .max_access_size = 4, 91*30b2f870SAndrey Smirnov .unaligned = false, 92*30b2f870SAndrey Smirnov }, 93*30b2f870SAndrey Smirnov }; 94*30b2f870SAndrey Smirnov 95*30b2f870SAndrey Smirnov static void imx7_gpr_init(Object *obj) 96*30b2f870SAndrey Smirnov { 97*30b2f870SAndrey Smirnov SysBusDevice *sd = SYS_BUS_DEVICE(obj); 98*30b2f870SAndrey Smirnov IMX7GPRState *s = IMX7_GPR(obj); 99*30b2f870SAndrey Smirnov 100*30b2f870SAndrey Smirnov memory_region_init_io(&s->mmio, obj, &imx7_gpr_ops, s, 101*30b2f870SAndrey Smirnov TYPE_IMX7_GPR, 64 * 1024); 102*30b2f870SAndrey Smirnov sysbus_init_mmio(sd, &s->mmio); 103*30b2f870SAndrey Smirnov } 104*30b2f870SAndrey Smirnov 105*30b2f870SAndrey Smirnov static void imx7_gpr_class_init(ObjectClass *klass, void *data) 106*30b2f870SAndrey Smirnov { 107*30b2f870SAndrey Smirnov DeviceClass *dc = DEVICE_CLASS(klass); 108*30b2f870SAndrey Smirnov 109*30b2f870SAndrey Smirnov dc->desc = "i.MX7 General Purpose Registers Module"; 110*30b2f870SAndrey Smirnov } 111*30b2f870SAndrey Smirnov 112*30b2f870SAndrey Smirnov static const TypeInfo imx7_gpr_info = { 113*30b2f870SAndrey Smirnov .name = TYPE_IMX7_GPR, 114*30b2f870SAndrey Smirnov .parent = TYPE_SYS_BUS_DEVICE, 115*30b2f870SAndrey Smirnov .instance_size = sizeof(IMX7GPRState), 116*30b2f870SAndrey Smirnov .instance_init = imx7_gpr_init, 117*30b2f870SAndrey Smirnov .class_init = imx7_gpr_class_init, 118*30b2f870SAndrey Smirnov }; 119*30b2f870SAndrey Smirnov 120*30b2f870SAndrey Smirnov static void imx7_gpr_register_type(void) 121*30b2f870SAndrey Smirnov { 122*30b2f870SAndrey Smirnov type_register_static(&imx7_gpr_info); 123*30b2f870SAndrey Smirnov } 124*30b2f870SAndrey Smirnov type_init(imx7_gpr_register_type) 125