1*94e77879SHao Wu /* 2*94e77879SHao Wu * Nuvoton NPCM7xx SMBus Module. 3*94e77879SHao Wu * 4*94e77879SHao Wu * Copyright 2020 Google LLC 5*94e77879SHao Wu * 6*94e77879SHao Wu * This program is free software; you can redistribute it and/or modify it 7*94e77879SHao Wu * under the terms of the GNU General Public License as published by the 8*94e77879SHao Wu * Free Software Foundation; either version 2 of the License, or 9*94e77879SHao Wu * (at your option) any later version. 10*94e77879SHao Wu * 11*94e77879SHao Wu * This program is distributed in the hope that it will be useful, but WITHOUT 12*94e77879SHao Wu * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13*94e77879SHao Wu * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14*94e77879SHao Wu * for more details. 15*94e77879SHao Wu */ 16*94e77879SHao Wu 17*94e77879SHao Wu #include "qemu/osdep.h" 18*94e77879SHao Wu 19*94e77879SHao Wu #include "hw/i2c/npcm7xx_smbus.h" 20*94e77879SHao Wu #include "migration/vmstate.h" 21*94e77879SHao Wu #include "qemu/bitops.h" 22*94e77879SHao Wu #include "qemu/guest-random.h" 23*94e77879SHao Wu #include "qemu/log.h" 24*94e77879SHao Wu #include "qemu/module.h" 25*94e77879SHao Wu #include "qemu/units.h" 26*94e77879SHao Wu 27*94e77879SHao Wu #include "trace.h" 28*94e77879SHao Wu 29*94e77879SHao Wu enum NPCM7xxSMBusCommonRegister { 30*94e77879SHao Wu NPCM7XX_SMB_SDA = 0x0, 31*94e77879SHao Wu NPCM7XX_SMB_ST = 0x2, 32*94e77879SHao Wu NPCM7XX_SMB_CST = 0x4, 33*94e77879SHao Wu NPCM7XX_SMB_CTL1 = 0x6, 34*94e77879SHao Wu NPCM7XX_SMB_ADDR1 = 0x8, 35*94e77879SHao Wu NPCM7XX_SMB_CTL2 = 0xa, 36*94e77879SHao Wu NPCM7XX_SMB_ADDR2 = 0xc, 37*94e77879SHao Wu NPCM7XX_SMB_CTL3 = 0xe, 38*94e77879SHao Wu NPCM7XX_SMB_CST2 = 0x18, 39*94e77879SHao Wu NPCM7XX_SMB_CST3 = 0x19, 40*94e77879SHao Wu NPCM7XX_SMB_VER = 0x1f, 41*94e77879SHao Wu }; 42*94e77879SHao Wu 43*94e77879SHao Wu enum NPCM7xxSMBusBank0Register { 44*94e77879SHao Wu NPCM7XX_SMB_ADDR3 = 0x10, 45*94e77879SHao Wu NPCM7XX_SMB_ADDR7 = 0x11, 46*94e77879SHao Wu NPCM7XX_SMB_ADDR4 = 0x12, 47*94e77879SHao Wu NPCM7XX_SMB_ADDR8 = 0x13, 48*94e77879SHao Wu NPCM7XX_SMB_ADDR5 = 0x14, 49*94e77879SHao Wu NPCM7XX_SMB_ADDR9 = 0x15, 50*94e77879SHao Wu NPCM7XX_SMB_ADDR6 = 0x16, 51*94e77879SHao Wu NPCM7XX_SMB_ADDR10 = 0x17, 52*94e77879SHao Wu NPCM7XX_SMB_CTL4 = 0x1a, 53*94e77879SHao Wu NPCM7XX_SMB_CTL5 = 0x1b, 54*94e77879SHao Wu NPCM7XX_SMB_SCLLT = 0x1c, 55*94e77879SHao Wu NPCM7XX_SMB_FIF_CTL = 0x1d, 56*94e77879SHao Wu NPCM7XX_SMB_SCLHT = 0x1e, 57*94e77879SHao Wu }; 58*94e77879SHao Wu 59*94e77879SHao Wu enum NPCM7xxSMBusBank1Register { 60*94e77879SHao Wu NPCM7XX_SMB_FIF_CTS = 0x10, 61*94e77879SHao Wu NPCM7XX_SMB_FAIR_PER = 0x11, 62*94e77879SHao Wu NPCM7XX_SMB_TXF_CTL = 0x12, 63*94e77879SHao Wu NPCM7XX_SMB_T_OUT = 0x14, 64*94e77879SHao Wu NPCM7XX_SMB_TXF_STS = 0x1a, 65*94e77879SHao Wu NPCM7XX_SMB_RXF_STS = 0x1c, 66*94e77879SHao Wu NPCM7XX_SMB_RXF_CTL = 0x1e, 67*94e77879SHao Wu }; 68*94e77879SHao Wu 69*94e77879SHao Wu /* ST fields */ 70*94e77879SHao Wu #define NPCM7XX_SMBST_STP BIT(7) 71*94e77879SHao Wu #define NPCM7XX_SMBST_SDAST BIT(6) 72*94e77879SHao Wu #define NPCM7XX_SMBST_BER BIT(5) 73*94e77879SHao Wu #define NPCM7XX_SMBST_NEGACK BIT(4) 74*94e77879SHao Wu #define NPCM7XX_SMBST_STASTR BIT(3) 75*94e77879SHao Wu #define NPCM7XX_SMBST_NMATCH BIT(2) 76*94e77879SHao Wu #define NPCM7XX_SMBST_MODE BIT(1) 77*94e77879SHao Wu #define NPCM7XX_SMBST_XMIT BIT(0) 78*94e77879SHao Wu 79*94e77879SHao Wu /* CST fields */ 80*94e77879SHao Wu #define NPCM7XX_SMBCST_ARPMATCH BIT(7) 81*94e77879SHao Wu #define NPCM7XX_SMBCST_MATCHAF BIT(6) 82*94e77879SHao Wu #define NPCM7XX_SMBCST_TGSCL BIT(5) 83*94e77879SHao Wu #define NPCM7XX_SMBCST_TSDA BIT(4) 84*94e77879SHao Wu #define NPCM7XX_SMBCST_GCMATCH BIT(3) 85*94e77879SHao Wu #define NPCM7XX_SMBCST_MATCH BIT(2) 86*94e77879SHao Wu #define NPCM7XX_SMBCST_BB BIT(1) 87*94e77879SHao Wu #define NPCM7XX_SMBCST_BUSY BIT(0) 88*94e77879SHao Wu 89*94e77879SHao Wu /* CST2 fields */ 90*94e77879SHao Wu #define NPCM7XX_SMBCST2_INTSTS BIT(7) 91*94e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH7F BIT(6) 92*94e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH6F BIT(5) 93*94e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH5F BIT(4) 94*94e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH4F BIT(3) 95*94e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH3F BIT(2) 96*94e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH2F BIT(1) 97*94e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH1F BIT(0) 98*94e77879SHao Wu 99*94e77879SHao Wu /* CST3 fields */ 100*94e77879SHao Wu #define NPCM7XX_SMBCST3_EO_BUSY BIT(7) 101*94e77879SHao Wu #define NPCM7XX_SMBCST3_MATCH10F BIT(2) 102*94e77879SHao Wu #define NPCM7XX_SMBCST3_MATCH9F BIT(1) 103*94e77879SHao Wu #define NPCM7XX_SMBCST3_MATCH8F BIT(0) 104*94e77879SHao Wu 105*94e77879SHao Wu /* CTL1 fields */ 106*94e77879SHao Wu #define NPCM7XX_SMBCTL1_STASTRE BIT(7) 107*94e77879SHao Wu #define NPCM7XX_SMBCTL1_NMINTE BIT(6) 108*94e77879SHao Wu #define NPCM7XX_SMBCTL1_GCMEN BIT(5) 109*94e77879SHao Wu #define NPCM7XX_SMBCTL1_ACK BIT(4) 110*94e77879SHao Wu #define NPCM7XX_SMBCTL1_EOBINTE BIT(3) 111*94e77879SHao Wu #define NPCM7XX_SMBCTL1_INTEN BIT(2) 112*94e77879SHao Wu #define NPCM7XX_SMBCTL1_STOP BIT(1) 113*94e77879SHao Wu #define NPCM7XX_SMBCTL1_START BIT(0) 114*94e77879SHao Wu 115*94e77879SHao Wu /* CTL2 fields */ 116*94e77879SHao Wu #define NPCM7XX_SMBCTL2_SCLFRQ(rv) extract8((rv), 1, 6) 117*94e77879SHao Wu #define NPCM7XX_SMBCTL2_ENABLE BIT(0) 118*94e77879SHao Wu 119*94e77879SHao Wu /* CTL3 fields */ 120*94e77879SHao Wu #define NPCM7XX_SMBCTL3_SCL_LVL BIT(7) 121*94e77879SHao Wu #define NPCM7XX_SMBCTL3_SDA_LVL BIT(6) 122*94e77879SHao Wu #define NPCM7XX_SMBCTL3_BNK_SEL BIT(5) 123*94e77879SHao Wu #define NPCM7XX_SMBCTL3_400K_MODE BIT(4) 124*94e77879SHao Wu #define NPCM7XX_SMBCTL3_IDL_START BIT(3) 125*94e77879SHao Wu #define NPCM7XX_SMBCTL3_ARPMEN BIT(2) 126*94e77879SHao Wu #define NPCM7XX_SMBCTL3_SCLFRQ(rv) extract8((rv), 0, 2) 127*94e77879SHao Wu 128*94e77879SHao Wu /* ADDR fields */ 129*94e77879SHao Wu #define NPCM7XX_ADDR_EN BIT(7) 130*94e77879SHao Wu #define NPCM7XX_ADDR_A(rv) extract8((rv), 0, 6) 131*94e77879SHao Wu 132*94e77879SHao Wu #define KEEP_OLD_BIT(o, n, b) (((n) & (~(b))) | ((o) & (b))) 133*94e77879SHao Wu #define WRITE_ONE_CLEAR(o, n, b) ((n) & (b) ? (o) & (~(b)) : (o)) 134*94e77879SHao Wu 135*94e77879SHao Wu #define NPCM7XX_SMBUS_ENABLED(s) ((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE) 136*94e77879SHao Wu 137*94e77879SHao Wu /* VERSION fields values, read-only. */ 138*94e77879SHao Wu #define NPCM7XX_SMBUS_VERSION_NUMBER 1 139*94e77879SHao Wu #define NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED 0 140*94e77879SHao Wu 141*94e77879SHao Wu /* Reset values */ 142*94e77879SHao Wu #define NPCM7XX_SMB_ST_INIT_VAL 0x00 143*94e77879SHao Wu #define NPCM7XX_SMB_CST_INIT_VAL 0x10 144*94e77879SHao Wu #define NPCM7XX_SMB_CST2_INIT_VAL 0x00 145*94e77879SHao Wu #define NPCM7XX_SMB_CST3_INIT_VAL 0x00 146*94e77879SHao Wu #define NPCM7XX_SMB_CTL1_INIT_VAL 0x00 147*94e77879SHao Wu #define NPCM7XX_SMB_CTL2_INIT_VAL 0x00 148*94e77879SHao Wu #define NPCM7XX_SMB_CTL3_INIT_VAL 0xc0 149*94e77879SHao Wu #define NPCM7XX_SMB_CTL4_INIT_VAL 0x07 150*94e77879SHao Wu #define NPCM7XX_SMB_CTL5_INIT_VAL 0x00 151*94e77879SHao Wu #define NPCM7XX_SMB_ADDR_INIT_VAL 0x00 152*94e77879SHao Wu #define NPCM7XX_SMB_SCLLT_INIT_VAL 0x00 153*94e77879SHao Wu #define NPCM7XX_SMB_SCLHT_INIT_VAL 0x00 154*94e77879SHao Wu 155*94e77879SHao Wu static uint8_t npcm7xx_smbus_get_version(void) 156*94e77879SHao Wu { 157*94e77879SHao Wu return NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED << 7 | 158*94e77879SHao Wu NPCM7XX_SMBUS_VERSION_NUMBER; 159*94e77879SHao Wu } 160*94e77879SHao Wu 161*94e77879SHao Wu static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s) 162*94e77879SHao Wu { 163*94e77879SHao Wu int level; 164*94e77879SHao Wu 165*94e77879SHao Wu if (s->ctl1 & NPCM7XX_SMBCTL1_INTEN) { 166*94e77879SHao Wu level = !!((s->ctl1 & NPCM7XX_SMBCTL1_NMINTE && 167*94e77879SHao Wu s->st & NPCM7XX_SMBST_NMATCH) || 168*94e77879SHao Wu (s->st & NPCM7XX_SMBST_BER) || 169*94e77879SHao Wu (s->st & NPCM7XX_SMBST_NEGACK) || 170*94e77879SHao Wu (s->st & NPCM7XX_SMBST_SDAST) || 171*94e77879SHao Wu (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE && 172*94e77879SHao Wu s->st & NPCM7XX_SMBST_SDAST) || 173*94e77879SHao Wu (s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE && 174*94e77879SHao Wu s->cst3 & NPCM7XX_SMBCST3_EO_BUSY)); 175*94e77879SHao Wu 176*94e77879SHao Wu if (level) { 177*94e77879SHao Wu s->cst2 |= NPCM7XX_SMBCST2_INTSTS; 178*94e77879SHao Wu } else { 179*94e77879SHao Wu s->cst2 &= ~NPCM7XX_SMBCST2_INTSTS; 180*94e77879SHao Wu } 181*94e77879SHao Wu qemu_set_irq(s->irq, level); 182*94e77879SHao Wu } 183*94e77879SHao Wu } 184*94e77879SHao Wu 185*94e77879SHao Wu static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s) 186*94e77879SHao Wu { 187*94e77879SHao Wu s->st &= ~NPCM7XX_SMBST_SDAST; 188*94e77879SHao Wu s->st |= NPCM7XX_SMBST_NEGACK; 189*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_NEGACK; 190*94e77879SHao Wu } 191*94e77879SHao Wu 192*94e77879SHao Wu static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value) 193*94e77879SHao Wu { 194*94e77879SHao Wu int rv = i2c_send(s->bus, value); 195*94e77879SHao Wu 196*94e77879SHao Wu if (rv) { 197*94e77879SHao Wu npcm7xx_smbus_nack(s); 198*94e77879SHao Wu } else { 199*94e77879SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 200*94e77879SHao Wu } 201*94e77879SHao Wu trace_npcm7xx_smbus_send_byte((DEVICE(s)->canonical_path), value, !rv); 202*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 203*94e77879SHao Wu } 204*94e77879SHao Wu 205*94e77879SHao Wu static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s) 206*94e77879SHao Wu { 207*94e77879SHao Wu s->sda = i2c_recv(s->bus); 208*94e77879SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 209*94e77879SHao Wu if (s->st & NPCM7XX_SMBCTL1_ACK) { 210*94e77879SHao Wu trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); 211*94e77879SHao Wu i2c_nack(s->bus); 212*94e77879SHao Wu s->st &= NPCM7XX_SMBCTL1_ACK; 213*94e77879SHao Wu } 214*94e77879SHao Wu trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda); 215*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 216*94e77879SHao Wu } 217*94e77879SHao Wu 218*94e77879SHao Wu static void npcm7xx_smbus_start(NPCM7xxSMBusState *s) 219*94e77879SHao Wu { 220*94e77879SHao Wu /* 221*94e77879SHao Wu * We can start the bus if one of these is true: 222*94e77879SHao Wu * 1. The bus is idle (so we can request it) 223*94e77879SHao Wu * 2. We are the occupier (it's a repeated start condition.) 224*94e77879SHao Wu */ 225*94e77879SHao Wu int available = !i2c_bus_busy(s->bus) || 226*94e77879SHao Wu s->status != NPCM7XX_SMBUS_STATUS_IDLE; 227*94e77879SHao Wu 228*94e77879SHao Wu if (available) { 229*94e77879SHao Wu s->st |= NPCM7XX_SMBST_MODE | NPCM7XX_SMBST_XMIT | NPCM7XX_SMBST_SDAST; 230*94e77879SHao Wu s->cst |= NPCM7XX_SMBCST_BUSY; 231*94e77879SHao Wu } else { 232*94e77879SHao Wu s->st &= ~NPCM7XX_SMBST_MODE; 233*94e77879SHao Wu s->cst &= ~NPCM7XX_SMBCST_BUSY; 234*94e77879SHao Wu s->st |= NPCM7XX_SMBST_BER; 235*94e77879SHao Wu } 236*94e77879SHao Wu 237*94e77879SHao Wu trace_npcm7xx_smbus_start(DEVICE(s)->canonical_path, available); 238*94e77879SHao Wu s->cst |= NPCM7XX_SMBCST_BB; 239*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_IDLE; 240*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 241*94e77879SHao Wu } 242*94e77879SHao Wu 243*94e77879SHao Wu static void npcm7xx_smbus_send_address(NPCM7xxSMBusState *s, uint8_t value) 244*94e77879SHao Wu { 245*94e77879SHao Wu int recv; 246*94e77879SHao Wu int rv; 247*94e77879SHao Wu 248*94e77879SHao Wu recv = value & BIT(0); 249*94e77879SHao Wu rv = i2c_start_transfer(s->bus, value >> 1, recv); 250*94e77879SHao Wu trace_npcm7xx_smbus_send_address(DEVICE(s)->canonical_path, 251*94e77879SHao Wu value >> 1, recv, !rv); 252*94e77879SHao Wu if (rv) { 253*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 254*94e77879SHao Wu "%s: requesting i2c bus for 0x%02x failed: %d\n", 255*94e77879SHao Wu DEVICE(s)->canonical_path, value, rv); 256*94e77879SHao Wu /* Failed to start transfer. NACK to reject.*/ 257*94e77879SHao Wu if (recv) { 258*94e77879SHao Wu s->st &= ~NPCM7XX_SMBST_XMIT; 259*94e77879SHao Wu } else { 260*94e77879SHao Wu s->st |= NPCM7XX_SMBST_XMIT; 261*94e77879SHao Wu } 262*94e77879SHao Wu npcm7xx_smbus_nack(s); 263*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 264*94e77879SHao Wu return; 265*94e77879SHao Wu } 266*94e77879SHao Wu 267*94e77879SHao Wu s->st &= ~NPCM7XX_SMBST_NEGACK; 268*94e77879SHao Wu if (recv) { 269*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_RECEIVING; 270*94e77879SHao Wu s->st &= ~NPCM7XX_SMBST_XMIT; 271*94e77879SHao Wu } else { 272*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_SENDING; 273*94e77879SHao Wu s->st |= NPCM7XX_SMBST_XMIT; 274*94e77879SHao Wu } 275*94e77879SHao Wu 276*94e77879SHao Wu if (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE) { 277*94e77879SHao Wu s->st |= NPCM7XX_SMBST_STASTR; 278*94e77879SHao Wu if (!recv) { 279*94e77879SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 280*94e77879SHao Wu } 281*94e77879SHao Wu } else if (recv) { 282*94e77879SHao Wu npcm7xx_smbus_recv_byte(s); 283*94e77879SHao Wu } 284*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 285*94e77879SHao Wu } 286*94e77879SHao Wu 287*94e77879SHao Wu static void npcm7xx_smbus_execute_stop(NPCM7xxSMBusState *s) 288*94e77879SHao Wu { 289*94e77879SHao Wu i2c_end_transfer(s->bus); 290*94e77879SHao Wu s->st = 0; 291*94e77879SHao Wu s->cst = 0; 292*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_IDLE; 293*94e77879SHao Wu s->cst3 |= NPCM7XX_SMBCST3_EO_BUSY; 294*94e77879SHao Wu trace_npcm7xx_smbus_stop(DEVICE(s)->canonical_path); 295*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 296*94e77879SHao Wu } 297*94e77879SHao Wu 298*94e77879SHao Wu 299*94e77879SHao Wu static void npcm7xx_smbus_stop(NPCM7xxSMBusState *s) 300*94e77879SHao Wu { 301*94e77879SHao Wu if (s->st & NPCM7XX_SMBST_MODE) { 302*94e77879SHao Wu switch (s->status) { 303*94e77879SHao Wu case NPCM7XX_SMBUS_STATUS_RECEIVING: 304*94e77879SHao Wu case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE: 305*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE; 306*94e77879SHao Wu break; 307*94e77879SHao Wu 308*94e77879SHao Wu case NPCM7XX_SMBUS_STATUS_NEGACK: 309*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK; 310*94e77879SHao Wu break; 311*94e77879SHao Wu 312*94e77879SHao Wu default: 313*94e77879SHao Wu npcm7xx_smbus_execute_stop(s); 314*94e77879SHao Wu break; 315*94e77879SHao Wu } 316*94e77879SHao Wu } 317*94e77879SHao Wu } 318*94e77879SHao Wu 319*94e77879SHao Wu static uint8_t npcm7xx_smbus_read_sda(NPCM7xxSMBusState *s) 320*94e77879SHao Wu { 321*94e77879SHao Wu uint8_t value = s->sda; 322*94e77879SHao Wu 323*94e77879SHao Wu switch (s->status) { 324*94e77879SHao Wu case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE: 325*94e77879SHao Wu npcm7xx_smbus_execute_stop(s); 326*94e77879SHao Wu break; 327*94e77879SHao Wu 328*94e77879SHao Wu case NPCM7XX_SMBUS_STATUS_RECEIVING: 329*94e77879SHao Wu npcm7xx_smbus_recv_byte(s); 330*94e77879SHao Wu break; 331*94e77879SHao Wu 332*94e77879SHao Wu default: 333*94e77879SHao Wu /* Do nothing */ 334*94e77879SHao Wu break; 335*94e77879SHao Wu } 336*94e77879SHao Wu 337*94e77879SHao Wu return value; 338*94e77879SHao Wu } 339*94e77879SHao Wu 340*94e77879SHao Wu static void npcm7xx_smbus_write_sda(NPCM7xxSMBusState *s, uint8_t value) 341*94e77879SHao Wu { 342*94e77879SHao Wu s->sda = value; 343*94e77879SHao Wu if (s->st & NPCM7XX_SMBST_MODE) { 344*94e77879SHao Wu switch (s->status) { 345*94e77879SHao Wu case NPCM7XX_SMBUS_STATUS_IDLE: 346*94e77879SHao Wu npcm7xx_smbus_send_address(s, value); 347*94e77879SHao Wu break; 348*94e77879SHao Wu case NPCM7XX_SMBUS_STATUS_SENDING: 349*94e77879SHao Wu npcm7xx_smbus_send_byte(s, value); 350*94e77879SHao Wu break; 351*94e77879SHao Wu default: 352*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 353*94e77879SHao Wu "%s: write to SDA in invalid status %d: %u\n", 354*94e77879SHao Wu DEVICE(s)->canonical_path, s->status, value); 355*94e77879SHao Wu break; 356*94e77879SHao Wu } 357*94e77879SHao Wu } 358*94e77879SHao Wu } 359*94e77879SHao Wu 360*94e77879SHao Wu static void npcm7xx_smbus_write_st(NPCM7xxSMBusState *s, uint8_t value) 361*94e77879SHao Wu { 362*94e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STP); 363*94e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_BER); 364*94e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STASTR); 365*94e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_NMATCH); 366*94e77879SHao Wu 367*94e77879SHao Wu if (value & NPCM7XX_SMBST_NEGACK) { 368*94e77879SHao Wu s->st &= ~NPCM7XX_SMBST_NEGACK; 369*94e77879SHao Wu if (s->status == NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK) { 370*94e77879SHao Wu npcm7xx_smbus_execute_stop(s); 371*94e77879SHao Wu } 372*94e77879SHao Wu } 373*94e77879SHao Wu 374*94e77879SHao Wu if (value & NPCM7XX_SMBST_STASTR && 375*94e77879SHao Wu s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { 376*94e77879SHao Wu npcm7xx_smbus_recv_byte(s); 377*94e77879SHao Wu } 378*94e77879SHao Wu 379*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 380*94e77879SHao Wu } 381*94e77879SHao Wu 382*94e77879SHao Wu static void npcm7xx_smbus_write_cst(NPCM7xxSMBusState *s, uint8_t value) 383*94e77879SHao Wu { 384*94e77879SHao Wu uint8_t new_value = s->cst; 385*94e77879SHao Wu 386*94e77879SHao Wu s->cst = WRITE_ONE_CLEAR(new_value, value, NPCM7XX_SMBCST_BB); 387*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 388*94e77879SHao Wu } 389*94e77879SHao Wu 390*94e77879SHao Wu static void npcm7xx_smbus_write_cst3(NPCM7xxSMBusState *s, uint8_t value) 391*94e77879SHao Wu { 392*94e77879SHao Wu s->cst3 = WRITE_ONE_CLEAR(s->cst3, value, NPCM7XX_SMBCST3_EO_BUSY); 393*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 394*94e77879SHao Wu } 395*94e77879SHao Wu 396*94e77879SHao Wu static void npcm7xx_smbus_write_ctl1(NPCM7xxSMBusState *s, uint8_t value) 397*94e77879SHao Wu { 398*94e77879SHao Wu s->ctl1 = KEEP_OLD_BIT(s->ctl1, value, 399*94e77879SHao Wu NPCM7XX_SMBCTL1_START | NPCM7XX_SMBCTL1_STOP | NPCM7XX_SMBCTL1_ACK); 400*94e77879SHao Wu 401*94e77879SHao Wu if (value & NPCM7XX_SMBCTL1_START) { 402*94e77879SHao Wu npcm7xx_smbus_start(s); 403*94e77879SHao Wu } 404*94e77879SHao Wu 405*94e77879SHao Wu if (value & NPCM7XX_SMBCTL1_STOP) { 406*94e77879SHao Wu npcm7xx_smbus_stop(s); 407*94e77879SHao Wu } 408*94e77879SHao Wu 409*94e77879SHao Wu npcm7xx_smbus_update_irq(s); 410*94e77879SHao Wu } 411*94e77879SHao Wu 412*94e77879SHao Wu static void npcm7xx_smbus_write_ctl2(NPCM7xxSMBusState *s, uint8_t value) 413*94e77879SHao Wu { 414*94e77879SHao Wu s->ctl2 = value; 415*94e77879SHao Wu 416*94e77879SHao Wu if (!NPCM7XX_SMBUS_ENABLED(s)) { 417*94e77879SHao Wu /* Disable this SMBus module. */ 418*94e77879SHao Wu s->ctl1 = 0; 419*94e77879SHao Wu s->st = 0; 420*94e77879SHao Wu s->cst3 = s->cst3 & (~NPCM7XX_SMBCST3_EO_BUSY); 421*94e77879SHao Wu s->cst = 0; 422*94e77879SHao Wu } 423*94e77879SHao Wu } 424*94e77879SHao Wu 425*94e77879SHao Wu static void npcm7xx_smbus_write_ctl3(NPCM7xxSMBusState *s, uint8_t value) 426*94e77879SHao Wu { 427*94e77879SHao Wu uint8_t old_ctl3 = s->ctl3; 428*94e77879SHao Wu 429*94e77879SHao Wu /* Write to SDA and SCL bits are ignored. */ 430*94e77879SHao Wu s->ctl3 = KEEP_OLD_BIT(old_ctl3, value, 431*94e77879SHao Wu NPCM7XX_SMBCTL3_SCL_LVL | NPCM7XX_SMBCTL3_SDA_LVL); 432*94e77879SHao Wu } 433*94e77879SHao Wu 434*94e77879SHao Wu static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size) 435*94e77879SHao Wu { 436*94e77879SHao Wu NPCM7xxSMBusState *s = opaque; 437*94e77879SHao Wu uint64_t value = 0; 438*94e77879SHao Wu uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL; 439*94e77879SHao Wu 440*94e77879SHao Wu /* The order of the registers are their order in memory. */ 441*94e77879SHao Wu switch (offset) { 442*94e77879SHao Wu case NPCM7XX_SMB_SDA: 443*94e77879SHao Wu value = npcm7xx_smbus_read_sda(s); 444*94e77879SHao Wu break; 445*94e77879SHao Wu 446*94e77879SHao Wu case NPCM7XX_SMB_ST: 447*94e77879SHao Wu value = s->st; 448*94e77879SHao Wu break; 449*94e77879SHao Wu 450*94e77879SHao Wu case NPCM7XX_SMB_CST: 451*94e77879SHao Wu value = s->cst; 452*94e77879SHao Wu break; 453*94e77879SHao Wu 454*94e77879SHao Wu case NPCM7XX_SMB_CTL1: 455*94e77879SHao Wu value = s->ctl1; 456*94e77879SHao Wu break; 457*94e77879SHao Wu 458*94e77879SHao Wu case NPCM7XX_SMB_ADDR1: 459*94e77879SHao Wu value = s->addr[0]; 460*94e77879SHao Wu break; 461*94e77879SHao Wu 462*94e77879SHao Wu case NPCM7XX_SMB_CTL2: 463*94e77879SHao Wu value = s->ctl2; 464*94e77879SHao Wu break; 465*94e77879SHao Wu 466*94e77879SHao Wu case NPCM7XX_SMB_ADDR2: 467*94e77879SHao Wu value = s->addr[1]; 468*94e77879SHao Wu break; 469*94e77879SHao Wu 470*94e77879SHao Wu case NPCM7XX_SMB_CTL3: 471*94e77879SHao Wu value = s->ctl3; 472*94e77879SHao Wu break; 473*94e77879SHao Wu 474*94e77879SHao Wu case NPCM7XX_SMB_CST2: 475*94e77879SHao Wu value = s->cst2; 476*94e77879SHao Wu break; 477*94e77879SHao Wu 478*94e77879SHao Wu case NPCM7XX_SMB_CST3: 479*94e77879SHao Wu value = s->cst3; 480*94e77879SHao Wu break; 481*94e77879SHao Wu 482*94e77879SHao Wu case NPCM7XX_SMB_VER: 483*94e77879SHao Wu value = npcm7xx_smbus_get_version(); 484*94e77879SHao Wu break; 485*94e77879SHao Wu 486*94e77879SHao Wu /* This register is either invalid or banked at this point. */ 487*94e77879SHao Wu default: 488*94e77879SHao Wu if (bank) { 489*94e77879SHao Wu /* Bank 1 */ 490*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 491*94e77879SHao Wu "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", 492*94e77879SHao Wu DEVICE(s)->canonical_path, offset); 493*94e77879SHao Wu } else { 494*94e77879SHao Wu /* Bank 0 */ 495*94e77879SHao Wu switch (offset) { 496*94e77879SHao Wu case NPCM7XX_SMB_ADDR3: 497*94e77879SHao Wu value = s->addr[2]; 498*94e77879SHao Wu break; 499*94e77879SHao Wu 500*94e77879SHao Wu case NPCM7XX_SMB_ADDR7: 501*94e77879SHao Wu value = s->addr[6]; 502*94e77879SHao Wu break; 503*94e77879SHao Wu 504*94e77879SHao Wu case NPCM7XX_SMB_ADDR4: 505*94e77879SHao Wu value = s->addr[3]; 506*94e77879SHao Wu break; 507*94e77879SHao Wu 508*94e77879SHao Wu case NPCM7XX_SMB_ADDR8: 509*94e77879SHao Wu value = s->addr[7]; 510*94e77879SHao Wu break; 511*94e77879SHao Wu 512*94e77879SHao Wu case NPCM7XX_SMB_ADDR5: 513*94e77879SHao Wu value = s->addr[4]; 514*94e77879SHao Wu break; 515*94e77879SHao Wu 516*94e77879SHao Wu case NPCM7XX_SMB_ADDR9: 517*94e77879SHao Wu value = s->addr[8]; 518*94e77879SHao Wu break; 519*94e77879SHao Wu 520*94e77879SHao Wu case NPCM7XX_SMB_ADDR6: 521*94e77879SHao Wu value = s->addr[5]; 522*94e77879SHao Wu break; 523*94e77879SHao Wu 524*94e77879SHao Wu case NPCM7XX_SMB_ADDR10: 525*94e77879SHao Wu value = s->addr[9]; 526*94e77879SHao Wu break; 527*94e77879SHao Wu 528*94e77879SHao Wu case NPCM7XX_SMB_CTL4: 529*94e77879SHao Wu value = s->ctl4; 530*94e77879SHao Wu break; 531*94e77879SHao Wu 532*94e77879SHao Wu case NPCM7XX_SMB_CTL5: 533*94e77879SHao Wu value = s->ctl5; 534*94e77879SHao Wu break; 535*94e77879SHao Wu 536*94e77879SHao Wu case NPCM7XX_SMB_SCLLT: 537*94e77879SHao Wu value = s->scllt; 538*94e77879SHao Wu break; 539*94e77879SHao Wu 540*94e77879SHao Wu case NPCM7XX_SMB_SCLHT: 541*94e77879SHao Wu value = s->sclht; 542*94e77879SHao Wu break; 543*94e77879SHao Wu 544*94e77879SHao Wu default: 545*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 546*94e77879SHao Wu "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", 547*94e77879SHao Wu DEVICE(s)->canonical_path, offset); 548*94e77879SHao Wu break; 549*94e77879SHao Wu } 550*94e77879SHao Wu } 551*94e77879SHao Wu break; 552*94e77879SHao Wu } 553*94e77879SHao Wu 554*94e77879SHao Wu trace_npcm7xx_smbus_read(DEVICE(s)->canonical_path, offset, value, size); 555*94e77879SHao Wu 556*94e77879SHao Wu return value; 557*94e77879SHao Wu } 558*94e77879SHao Wu 559*94e77879SHao Wu static void npcm7xx_smbus_write(void *opaque, hwaddr offset, uint64_t value, 560*94e77879SHao Wu unsigned size) 561*94e77879SHao Wu { 562*94e77879SHao Wu NPCM7xxSMBusState *s = opaque; 563*94e77879SHao Wu uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL; 564*94e77879SHao Wu 565*94e77879SHao Wu trace_npcm7xx_smbus_write(DEVICE(s)->canonical_path, offset, value, size); 566*94e77879SHao Wu 567*94e77879SHao Wu /* The order of the registers are their order in memory. */ 568*94e77879SHao Wu switch (offset) { 569*94e77879SHao Wu case NPCM7XX_SMB_SDA: 570*94e77879SHao Wu npcm7xx_smbus_write_sda(s, value); 571*94e77879SHao Wu break; 572*94e77879SHao Wu 573*94e77879SHao Wu case NPCM7XX_SMB_ST: 574*94e77879SHao Wu npcm7xx_smbus_write_st(s, value); 575*94e77879SHao Wu break; 576*94e77879SHao Wu 577*94e77879SHao Wu case NPCM7XX_SMB_CST: 578*94e77879SHao Wu npcm7xx_smbus_write_cst(s, value); 579*94e77879SHao Wu break; 580*94e77879SHao Wu 581*94e77879SHao Wu case NPCM7XX_SMB_CTL1: 582*94e77879SHao Wu npcm7xx_smbus_write_ctl1(s, value); 583*94e77879SHao Wu break; 584*94e77879SHao Wu 585*94e77879SHao Wu case NPCM7XX_SMB_ADDR1: 586*94e77879SHao Wu s->addr[0] = value; 587*94e77879SHao Wu break; 588*94e77879SHao Wu 589*94e77879SHao Wu case NPCM7XX_SMB_CTL2: 590*94e77879SHao Wu npcm7xx_smbus_write_ctl2(s, value); 591*94e77879SHao Wu break; 592*94e77879SHao Wu 593*94e77879SHao Wu case NPCM7XX_SMB_ADDR2: 594*94e77879SHao Wu s->addr[1] = value; 595*94e77879SHao Wu break; 596*94e77879SHao Wu 597*94e77879SHao Wu case NPCM7XX_SMB_CTL3: 598*94e77879SHao Wu npcm7xx_smbus_write_ctl3(s, value); 599*94e77879SHao Wu break; 600*94e77879SHao Wu 601*94e77879SHao Wu case NPCM7XX_SMB_CST2: 602*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 603*94e77879SHao Wu "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n", 604*94e77879SHao Wu DEVICE(s)->canonical_path, offset); 605*94e77879SHao Wu break; 606*94e77879SHao Wu 607*94e77879SHao Wu case NPCM7XX_SMB_CST3: 608*94e77879SHao Wu npcm7xx_smbus_write_cst3(s, value); 609*94e77879SHao Wu break; 610*94e77879SHao Wu 611*94e77879SHao Wu case NPCM7XX_SMB_VER: 612*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 613*94e77879SHao Wu "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n", 614*94e77879SHao Wu DEVICE(s)->canonical_path, offset); 615*94e77879SHao Wu break; 616*94e77879SHao Wu 617*94e77879SHao Wu /* This register is either invalid or banked at this point. */ 618*94e77879SHao Wu default: 619*94e77879SHao Wu if (bank) { 620*94e77879SHao Wu /* Bank 1 */ 621*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 622*94e77879SHao Wu "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", 623*94e77879SHao Wu DEVICE(s)->canonical_path, offset); 624*94e77879SHao Wu } else { 625*94e77879SHao Wu /* Bank 0 */ 626*94e77879SHao Wu switch (offset) { 627*94e77879SHao Wu case NPCM7XX_SMB_ADDR3: 628*94e77879SHao Wu s->addr[2] = value; 629*94e77879SHao Wu break; 630*94e77879SHao Wu 631*94e77879SHao Wu case NPCM7XX_SMB_ADDR7: 632*94e77879SHao Wu s->addr[6] = value; 633*94e77879SHao Wu break; 634*94e77879SHao Wu 635*94e77879SHao Wu case NPCM7XX_SMB_ADDR4: 636*94e77879SHao Wu s->addr[3] = value; 637*94e77879SHao Wu break; 638*94e77879SHao Wu 639*94e77879SHao Wu case NPCM7XX_SMB_ADDR8: 640*94e77879SHao Wu s->addr[7] = value; 641*94e77879SHao Wu break; 642*94e77879SHao Wu 643*94e77879SHao Wu case NPCM7XX_SMB_ADDR5: 644*94e77879SHao Wu s->addr[4] = value; 645*94e77879SHao Wu break; 646*94e77879SHao Wu 647*94e77879SHao Wu case NPCM7XX_SMB_ADDR9: 648*94e77879SHao Wu s->addr[8] = value; 649*94e77879SHao Wu break; 650*94e77879SHao Wu 651*94e77879SHao Wu case NPCM7XX_SMB_ADDR6: 652*94e77879SHao Wu s->addr[5] = value; 653*94e77879SHao Wu break; 654*94e77879SHao Wu 655*94e77879SHao Wu case NPCM7XX_SMB_ADDR10: 656*94e77879SHao Wu s->addr[9] = value; 657*94e77879SHao Wu break; 658*94e77879SHao Wu 659*94e77879SHao Wu case NPCM7XX_SMB_CTL4: 660*94e77879SHao Wu s->ctl4 = value; 661*94e77879SHao Wu break; 662*94e77879SHao Wu 663*94e77879SHao Wu case NPCM7XX_SMB_CTL5: 664*94e77879SHao Wu s->ctl5 = value; 665*94e77879SHao Wu break; 666*94e77879SHao Wu 667*94e77879SHao Wu case NPCM7XX_SMB_SCLLT: 668*94e77879SHao Wu s->scllt = value; 669*94e77879SHao Wu break; 670*94e77879SHao Wu 671*94e77879SHao Wu case NPCM7XX_SMB_SCLHT: 672*94e77879SHao Wu s->sclht = value; 673*94e77879SHao Wu break; 674*94e77879SHao Wu 675*94e77879SHao Wu default: 676*94e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 677*94e77879SHao Wu "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", 678*94e77879SHao Wu DEVICE(s)->canonical_path, offset); 679*94e77879SHao Wu break; 680*94e77879SHao Wu } 681*94e77879SHao Wu } 682*94e77879SHao Wu break; 683*94e77879SHao Wu } 684*94e77879SHao Wu } 685*94e77879SHao Wu 686*94e77879SHao Wu static const MemoryRegionOps npcm7xx_smbus_ops = { 687*94e77879SHao Wu .read = npcm7xx_smbus_read, 688*94e77879SHao Wu .write = npcm7xx_smbus_write, 689*94e77879SHao Wu .endianness = DEVICE_LITTLE_ENDIAN, 690*94e77879SHao Wu .valid = { 691*94e77879SHao Wu .min_access_size = 1, 692*94e77879SHao Wu .max_access_size = 1, 693*94e77879SHao Wu .unaligned = false, 694*94e77879SHao Wu }, 695*94e77879SHao Wu }; 696*94e77879SHao Wu 697*94e77879SHao Wu static void npcm7xx_smbus_enter_reset(Object *obj, ResetType type) 698*94e77879SHao Wu { 699*94e77879SHao Wu NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj); 700*94e77879SHao Wu 701*94e77879SHao Wu s->st = NPCM7XX_SMB_ST_INIT_VAL; 702*94e77879SHao Wu s->cst = NPCM7XX_SMB_CST_INIT_VAL; 703*94e77879SHao Wu s->cst2 = NPCM7XX_SMB_CST2_INIT_VAL; 704*94e77879SHao Wu s->cst3 = NPCM7XX_SMB_CST3_INIT_VAL; 705*94e77879SHao Wu s->ctl1 = NPCM7XX_SMB_CTL1_INIT_VAL; 706*94e77879SHao Wu s->ctl2 = NPCM7XX_SMB_CTL2_INIT_VAL; 707*94e77879SHao Wu s->ctl3 = NPCM7XX_SMB_CTL3_INIT_VAL; 708*94e77879SHao Wu s->ctl4 = NPCM7XX_SMB_CTL4_INIT_VAL; 709*94e77879SHao Wu s->ctl5 = NPCM7XX_SMB_CTL5_INIT_VAL; 710*94e77879SHao Wu 711*94e77879SHao Wu for (int i = 0; i < NPCM7XX_SMBUS_NR_ADDRS; ++i) { 712*94e77879SHao Wu s->addr[i] = NPCM7XX_SMB_ADDR_INIT_VAL; 713*94e77879SHao Wu } 714*94e77879SHao Wu s->scllt = NPCM7XX_SMB_SCLLT_INIT_VAL; 715*94e77879SHao Wu s->sclht = NPCM7XX_SMB_SCLHT_INIT_VAL; 716*94e77879SHao Wu 717*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_IDLE; 718*94e77879SHao Wu } 719*94e77879SHao Wu 720*94e77879SHao Wu static void npcm7xx_smbus_hold_reset(Object *obj) 721*94e77879SHao Wu { 722*94e77879SHao Wu NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj); 723*94e77879SHao Wu 724*94e77879SHao Wu qemu_irq_lower(s->irq); 725*94e77879SHao Wu } 726*94e77879SHao Wu 727*94e77879SHao Wu static void npcm7xx_smbus_init(Object *obj) 728*94e77879SHao Wu { 729*94e77879SHao Wu NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj); 730*94e77879SHao Wu SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 731*94e77879SHao Wu 732*94e77879SHao Wu sysbus_init_irq(sbd, &s->irq); 733*94e77879SHao Wu memory_region_init_io(&s->iomem, obj, &npcm7xx_smbus_ops, s, 734*94e77879SHao Wu "regs", 4 * KiB); 735*94e77879SHao Wu sysbus_init_mmio(sbd, &s->iomem); 736*94e77879SHao Wu 737*94e77879SHao Wu s->bus = i2c_init_bus(DEVICE(s), "i2c-bus"); 738*94e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_IDLE; 739*94e77879SHao Wu } 740*94e77879SHao Wu 741*94e77879SHao Wu static const VMStateDescription vmstate_npcm7xx_smbus = { 742*94e77879SHao Wu .name = "npcm7xx-smbus", 743*94e77879SHao Wu .version_id = 0, 744*94e77879SHao Wu .minimum_version_id = 0, 745*94e77879SHao Wu .fields = (VMStateField[]) { 746*94e77879SHao Wu VMSTATE_UINT8(sda, NPCM7xxSMBusState), 747*94e77879SHao Wu VMSTATE_UINT8(st, NPCM7xxSMBusState), 748*94e77879SHao Wu VMSTATE_UINT8(cst, NPCM7xxSMBusState), 749*94e77879SHao Wu VMSTATE_UINT8(cst2, NPCM7xxSMBusState), 750*94e77879SHao Wu VMSTATE_UINT8(cst3, NPCM7xxSMBusState), 751*94e77879SHao Wu VMSTATE_UINT8(ctl1, NPCM7xxSMBusState), 752*94e77879SHao Wu VMSTATE_UINT8(ctl2, NPCM7xxSMBusState), 753*94e77879SHao Wu VMSTATE_UINT8(ctl3, NPCM7xxSMBusState), 754*94e77879SHao Wu VMSTATE_UINT8(ctl4, NPCM7xxSMBusState), 755*94e77879SHao Wu VMSTATE_UINT8(ctl5, NPCM7xxSMBusState), 756*94e77879SHao Wu VMSTATE_UINT8_ARRAY(addr, NPCM7xxSMBusState, NPCM7XX_SMBUS_NR_ADDRS), 757*94e77879SHao Wu VMSTATE_UINT8(scllt, NPCM7xxSMBusState), 758*94e77879SHao Wu VMSTATE_UINT8(sclht, NPCM7xxSMBusState), 759*94e77879SHao Wu VMSTATE_END_OF_LIST(), 760*94e77879SHao Wu }, 761*94e77879SHao Wu }; 762*94e77879SHao Wu 763*94e77879SHao Wu static void npcm7xx_smbus_class_init(ObjectClass *klass, void *data) 764*94e77879SHao Wu { 765*94e77879SHao Wu ResettableClass *rc = RESETTABLE_CLASS(klass); 766*94e77879SHao Wu DeviceClass *dc = DEVICE_CLASS(klass); 767*94e77879SHao Wu 768*94e77879SHao Wu dc->desc = "NPCM7xx System Management Bus"; 769*94e77879SHao Wu dc->vmsd = &vmstate_npcm7xx_smbus; 770*94e77879SHao Wu rc->phases.enter = npcm7xx_smbus_enter_reset; 771*94e77879SHao Wu rc->phases.hold = npcm7xx_smbus_hold_reset; 772*94e77879SHao Wu } 773*94e77879SHao Wu 774*94e77879SHao Wu static const TypeInfo npcm7xx_smbus_types[] = { 775*94e77879SHao Wu { 776*94e77879SHao Wu .name = TYPE_NPCM7XX_SMBUS, 777*94e77879SHao Wu .parent = TYPE_SYS_BUS_DEVICE, 778*94e77879SHao Wu .instance_size = sizeof(NPCM7xxSMBusState), 779*94e77879SHao Wu .class_init = npcm7xx_smbus_class_init, 780*94e77879SHao Wu .instance_init = npcm7xx_smbus_init, 781*94e77879SHao Wu }, 782*94e77879SHao Wu }; 783*94e77879SHao Wu DEFINE_TYPES(npcm7xx_smbus_types); 784