194e77879SHao Wu /* 294e77879SHao Wu * Nuvoton NPCM7xx SMBus Module. 394e77879SHao Wu * 494e77879SHao Wu * Copyright 2020 Google LLC 594e77879SHao Wu * 694e77879SHao Wu * This program is free software; you can redistribute it and/or modify it 794e77879SHao Wu * under the terms of the GNU General Public License as published by the 894e77879SHao Wu * Free Software Foundation; either version 2 of the License, or 994e77879SHao Wu * (at your option) any later version. 1094e77879SHao Wu * 1194e77879SHao Wu * This program is distributed in the hope that it will be useful, but WITHOUT 1294e77879SHao Wu * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1394e77879SHao Wu * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1494e77879SHao Wu * for more details. 1594e77879SHao Wu */ 1694e77879SHao Wu 1794e77879SHao Wu #include "qemu/osdep.h" 1894e77879SHao Wu 1994e77879SHao Wu #include "hw/i2c/npcm7xx_smbus.h" 2094e77879SHao Wu #include "migration/vmstate.h" 2194e77879SHao Wu #include "qemu/bitops.h" 2294e77879SHao Wu #include "qemu/guest-random.h" 2394e77879SHao Wu #include "qemu/log.h" 2494e77879SHao Wu #include "qemu/module.h" 2594e77879SHao Wu #include "qemu/units.h" 2694e77879SHao Wu 2794e77879SHao Wu #include "trace.h" 2894e77879SHao Wu 2994e77879SHao Wu enum NPCM7xxSMBusCommonRegister { 3094e77879SHao Wu NPCM7XX_SMB_SDA = 0x0, 3194e77879SHao Wu NPCM7XX_SMB_ST = 0x2, 3294e77879SHao Wu NPCM7XX_SMB_CST = 0x4, 3394e77879SHao Wu NPCM7XX_SMB_CTL1 = 0x6, 3494e77879SHao Wu NPCM7XX_SMB_ADDR1 = 0x8, 3594e77879SHao Wu NPCM7XX_SMB_CTL2 = 0xa, 3694e77879SHao Wu NPCM7XX_SMB_ADDR2 = 0xc, 3794e77879SHao Wu NPCM7XX_SMB_CTL3 = 0xe, 3894e77879SHao Wu NPCM7XX_SMB_CST2 = 0x18, 3994e77879SHao Wu NPCM7XX_SMB_CST3 = 0x19, 4094e77879SHao Wu NPCM7XX_SMB_VER = 0x1f, 4194e77879SHao Wu }; 4294e77879SHao Wu 4394e77879SHao Wu enum NPCM7xxSMBusBank0Register { 4494e77879SHao Wu NPCM7XX_SMB_ADDR3 = 0x10, 4594e77879SHao Wu NPCM7XX_SMB_ADDR7 = 0x11, 4694e77879SHao Wu NPCM7XX_SMB_ADDR4 = 0x12, 4794e77879SHao Wu NPCM7XX_SMB_ADDR8 = 0x13, 4894e77879SHao Wu NPCM7XX_SMB_ADDR5 = 0x14, 4994e77879SHao Wu NPCM7XX_SMB_ADDR9 = 0x15, 5094e77879SHao Wu NPCM7XX_SMB_ADDR6 = 0x16, 5194e77879SHao Wu NPCM7XX_SMB_ADDR10 = 0x17, 5294e77879SHao Wu NPCM7XX_SMB_CTL4 = 0x1a, 5394e77879SHao Wu NPCM7XX_SMB_CTL5 = 0x1b, 5494e77879SHao Wu NPCM7XX_SMB_SCLLT = 0x1c, 5594e77879SHao Wu NPCM7XX_SMB_FIF_CTL = 0x1d, 5694e77879SHao Wu NPCM7XX_SMB_SCLHT = 0x1e, 5794e77879SHao Wu }; 5894e77879SHao Wu 5994e77879SHao Wu enum NPCM7xxSMBusBank1Register { 6094e77879SHao Wu NPCM7XX_SMB_FIF_CTS = 0x10, 6194e77879SHao Wu NPCM7XX_SMB_FAIR_PER = 0x11, 6294e77879SHao Wu NPCM7XX_SMB_TXF_CTL = 0x12, 6394e77879SHao Wu NPCM7XX_SMB_T_OUT = 0x14, 6494e77879SHao Wu NPCM7XX_SMB_TXF_STS = 0x1a, 6594e77879SHao Wu NPCM7XX_SMB_RXF_STS = 0x1c, 6694e77879SHao Wu NPCM7XX_SMB_RXF_CTL = 0x1e, 6794e77879SHao Wu }; 6894e77879SHao Wu 6994e77879SHao Wu /* ST fields */ 7094e77879SHao Wu #define NPCM7XX_SMBST_STP BIT(7) 7194e77879SHao Wu #define NPCM7XX_SMBST_SDAST BIT(6) 7294e77879SHao Wu #define NPCM7XX_SMBST_BER BIT(5) 7394e77879SHao Wu #define NPCM7XX_SMBST_NEGACK BIT(4) 7494e77879SHao Wu #define NPCM7XX_SMBST_STASTR BIT(3) 7594e77879SHao Wu #define NPCM7XX_SMBST_NMATCH BIT(2) 7694e77879SHao Wu #define NPCM7XX_SMBST_MODE BIT(1) 7794e77879SHao Wu #define NPCM7XX_SMBST_XMIT BIT(0) 7894e77879SHao Wu 7994e77879SHao Wu /* CST fields */ 8094e77879SHao Wu #define NPCM7XX_SMBCST_ARPMATCH BIT(7) 8194e77879SHao Wu #define NPCM7XX_SMBCST_MATCHAF BIT(6) 8294e77879SHao Wu #define NPCM7XX_SMBCST_TGSCL BIT(5) 8394e77879SHao Wu #define NPCM7XX_SMBCST_TSDA BIT(4) 8494e77879SHao Wu #define NPCM7XX_SMBCST_GCMATCH BIT(3) 8594e77879SHao Wu #define NPCM7XX_SMBCST_MATCH BIT(2) 8694e77879SHao Wu #define NPCM7XX_SMBCST_BB BIT(1) 8794e77879SHao Wu #define NPCM7XX_SMBCST_BUSY BIT(0) 8894e77879SHao Wu 8994e77879SHao Wu /* CST2 fields */ 9094e77879SHao Wu #define NPCM7XX_SMBCST2_INTSTS BIT(7) 9194e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH7F BIT(6) 9294e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH6F BIT(5) 9394e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH5F BIT(4) 9494e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH4F BIT(3) 9594e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH3F BIT(2) 9694e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH2F BIT(1) 9794e77879SHao Wu #define NPCM7XX_SMBCST2_MATCH1F BIT(0) 9894e77879SHao Wu 9994e77879SHao Wu /* CST3 fields */ 10094e77879SHao Wu #define NPCM7XX_SMBCST3_EO_BUSY BIT(7) 10194e77879SHao Wu #define NPCM7XX_SMBCST3_MATCH10F BIT(2) 10294e77879SHao Wu #define NPCM7XX_SMBCST3_MATCH9F BIT(1) 10394e77879SHao Wu #define NPCM7XX_SMBCST3_MATCH8F BIT(0) 10494e77879SHao Wu 10594e77879SHao Wu /* CTL1 fields */ 10694e77879SHao Wu #define NPCM7XX_SMBCTL1_STASTRE BIT(7) 10794e77879SHao Wu #define NPCM7XX_SMBCTL1_NMINTE BIT(6) 10894e77879SHao Wu #define NPCM7XX_SMBCTL1_GCMEN BIT(5) 10994e77879SHao Wu #define NPCM7XX_SMBCTL1_ACK BIT(4) 11094e77879SHao Wu #define NPCM7XX_SMBCTL1_EOBINTE BIT(3) 11194e77879SHao Wu #define NPCM7XX_SMBCTL1_INTEN BIT(2) 11294e77879SHao Wu #define NPCM7XX_SMBCTL1_STOP BIT(1) 11394e77879SHao Wu #define NPCM7XX_SMBCTL1_START BIT(0) 11494e77879SHao Wu 11594e77879SHao Wu /* CTL2 fields */ 11694e77879SHao Wu #define NPCM7XX_SMBCTL2_SCLFRQ(rv) extract8((rv), 1, 6) 11794e77879SHao Wu #define NPCM7XX_SMBCTL2_ENABLE BIT(0) 11894e77879SHao Wu 11994e77879SHao Wu /* CTL3 fields */ 12094e77879SHao Wu #define NPCM7XX_SMBCTL3_SCL_LVL BIT(7) 12194e77879SHao Wu #define NPCM7XX_SMBCTL3_SDA_LVL BIT(6) 12294e77879SHao Wu #define NPCM7XX_SMBCTL3_BNK_SEL BIT(5) 12394e77879SHao Wu #define NPCM7XX_SMBCTL3_400K_MODE BIT(4) 12494e77879SHao Wu #define NPCM7XX_SMBCTL3_IDL_START BIT(3) 12594e77879SHao Wu #define NPCM7XX_SMBCTL3_ARPMEN BIT(2) 12694e77879SHao Wu #define NPCM7XX_SMBCTL3_SCLFRQ(rv) extract8((rv), 0, 2) 12794e77879SHao Wu 12894e77879SHao Wu /* ADDR fields */ 12994e77879SHao Wu #define NPCM7XX_ADDR_EN BIT(7) 13094e77879SHao Wu #define NPCM7XX_ADDR_A(rv) extract8((rv), 0, 6) 13194e77879SHao Wu 1326b6e7570SHao Wu /* FIFO Mode Register Fields */ 1336b6e7570SHao Wu /* FIF_CTL fields */ 1346b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTL_FIFO_EN BIT(4) 1356b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTL_FAIR_RDY_IE BIT(2) 1366b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTL_FAIR_RDY BIT(1) 1376b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTL_FAIR_BUSY BIT(0) 1386b6e7570SHao Wu /* FIF_CTS fields */ 1396b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTS_STR BIT(7) 1406b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTS_CLR_FIFO BIT(6) 1416b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTS_RFTE_IE BIT(3) 1426b6e7570SHao Wu #define NPCM7XX_SMBFIF_CTS_RXF_TXE BIT(1) 1436b6e7570SHao Wu /* TXF_CTL fields */ 1446b6e7570SHao Wu #define NPCM7XX_SMBTXF_CTL_THR_TXIE BIT(6) 1456b6e7570SHao Wu #define NPCM7XX_SMBTXF_CTL_TX_THR(rv) extract8((rv), 0, 5) 1466b6e7570SHao Wu /* T_OUT fields */ 1476b6e7570SHao Wu #define NPCM7XX_SMBT_OUT_ST BIT(7) 1486b6e7570SHao Wu #define NPCM7XX_SMBT_OUT_IE BIT(6) 1496b6e7570SHao Wu #define NPCM7XX_SMBT_OUT_CLKDIV(rv) extract8((rv), 0, 6) 1506b6e7570SHao Wu /* TXF_STS fields */ 1516b6e7570SHao Wu #define NPCM7XX_SMBTXF_STS_TX_THST BIT(6) 1526b6e7570SHao Wu #define NPCM7XX_SMBTXF_STS_TX_BYTES(rv) extract8((rv), 0, 5) 1536b6e7570SHao Wu /* RXF_STS fields */ 1546b6e7570SHao Wu #define NPCM7XX_SMBRXF_STS_RX_THST BIT(6) 1556b6e7570SHao Wu #define NPCM7XX_SMBRXF_STS_RX_BYTES(rv) extract8((rv), 0, 5) 1566b6e7570SHao Wu /* RXF_CTL fields */ 1576b6e7570SHao Wu #define NPCM7XX_SMBRXF_CTL_THR_RXIE BIT(6) 1586b6e7570SHao Wu #define NPCM7XX_SMBRXF_CTL_LAST BIT(5) 1596b6e7570SHao Wu #define NPCM7XX_SMBRXF_CTL_RX_THR(rv) extract8((rv), 0, 5) 1606b6e7570SHao Wu 16194e77879SHao Wu #define KEEP_OLD_BIT(o, n, b) (((n) & (~(b))) | ((o) & (b))) 16294e77879SHao Wu #define WRITE_ONE_CLEAR(o, n, b) ((n) & (b) ? (o) & (~(b)) : (o)) 16394e77879SHao Wu 16494e77879SHao Wu #define NPCM7XX_SMBUS_ENABLED(s) ((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE) 1656b6e7570SHao Wu #define NPCM7XX_SMBUS_FIFO_ENABLED(s) ((s)->fif_ctl & \ 1666b6e7570SHao Wu NPCM7XX_SMBFIF_CTL_FIFO_EN) 16794e77879SHao Wu 16894e77879SHao Wu /* VERSION fields values, read-only. */ 16994e77879SHao Wu #define NPCM7XX_SMBUS_VERSION_NUMBER 1 1706b6e7570SHao Wu #define NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED 1 17194e77879SHao Wu 17294e77879SHao Wu /* Reset values */ 17394e77879SHao Wu #define NPCM7XX_SMB_ST_INIT_VAL 0x00 17494e77879SHao Wu #define NPCM7XX_SMB_CST_INIT_VAL 0x10 17594e77879SHao Wu #define NPCM7XX_SMB_CST2_INIT_VAL 0x00 17694e77879SHao Wu #define NPCM7XX_SMB_CST3_INIT_VAL 0x00 17794e77879SHao Wu #define NPCM7XX_SMB_CTL1_INIT_VAL 0x00 17894e77879SHao Wu #define NPCM7XX_SMB_CTL2_INIT_VAL 0x00 17994e77879SHao Wu #define NPCM7XX_SMB_CTL3_INIT_VAL 0xc0 18094e77879SHao Wu #define NPCM7XX_SMB_CTL4_INIT_VAL 0x07 18194e77879SHao Wu #define NPCM7XX_SMB_CTL5_INIT_VAL 0x00 18294e77879SHao Wu #define NPCM7XX_SMB_ADDR_INIT_VAL 0x00 18394e77879SHao Wu #define NPCM7XX_SMB_SCLLT_INIT_VAL 0x00 18494e77879SHao Wu #define NPCM7XX_SMB_SCLHT_INIT_VAL 0x00 1856b6e7570SHao Wu #define NPCM7XX_SMB_FIF_CTL_INIT_VAL 0x00 1866b6e7570SHao Wu #define NPCM7XX_SMB_FIF_CTS_INIT_VAL 0x00 1876b6e7570SHao Wu #define NPCM7XX_SMB_FAIR_PER_INIT_VAL 0x00 1886b6e7570SHao Wu #define NPCM7XX_SMB_TXF_CTL_INIT_VAL 0x00 1896b6e7570SHao Wu #define NPCM7XX_SMB_T_OUT_INIT_VAL 0x3f 1906b6e7570SHao Wu #define NPCM7XX_SMB_TXF_STS_INIT_VAL 0x00 1916b6e7570SHao Wu #define NPCM7XX_SMB_RXF_STS_INIT_VAL 0x00 1926b6e7570SHao Wu #define NPCM7XX_SMB_RXF_CTL_INIT_VAL 0x01 19394e77879SHao Wu 19494e77879SHao Wu static uint8_t npcm7xx_smbus_get_version(void) 19594e77879SHao Wu { 19694e77879SHao Wu return NPCM7XX_SMBUS_VERSION_FIFO_SUPPORTED << 7 | 19794e77879SHao Wu NPCM7XX_SMBUS_VERSION_NUMBER; 19894e77879SHao Wu } 19994e77879SHao Wu 20094e77879SHao Wu static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s) 20194e77879SHao Wu { 20294e77879SHao Wu int level; 20394e77879SHao Wu 20494e77879SHao Wu if (s->ctl1 & NPCM7XX_SMBCTL1_INTEN) { 20594e77879SHao Wu level = !!((s->ctl1 & NPCM7XX_SMBCTL1_NMINTE && 20694e77879SHao Wu s->st & NPCM7XX_SMBST_NMATCH) || 20794e77879SHao Wu (s->st & NPCM7XX_SMBST_BER) || 20894e77879SHao Wu (s->st & NPCM7XX_SMBST_NEGACK) || 20994e77879SHao Wu (s->st & NPCM7XX_SMBST_SDAST) || 21094e77879SHao Wu (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE && 21194e77879SHao Wu s->st & NPCM7XX_SMBST_SDAST) || 21294e77879SHao Wu (s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE && 2136b6e7570SHao Wu s->cst3 & NPCM7XX_SMBCST3_EO_BUSY) || 2146b6e7570SHao Wu (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE && 2156b6e7570SHao Wu s->rxf_sts & NPCM7XX_SMBRXF_STS_RX_THST) || 2166b6e7570SHao Wu (s->txf_ctl & NPCM7XX_SMBTXF_CTL_THR_TXIE && 2176b6e7570SHao Wu s->txf_sts & NPCM7XX_SMBTXF_STS_TX_THST) || 2186b6e7570SHao Wu (s->fif_cts & NPCM7XX_SMBFIF_CTS_RFTE_IE && 2196b6e7570SHao Wu s->fif_cts & NPCM7XX_SMBFIF_CTS_RXF_TXE)); 22094e77879SHao Wu 22194e77879SHao Wu if (level) { 22294e77879SHao Wu s->cst2 |= NPCM7XX_SMBCST2_INTSTS; 22394e77879SHao Wu } else { 22494e77879SHao Wu s->cst2 &= ~NPCM7XX_SMBCST2_INTSTS; 22594e77879SHao Wu } 22694e77879SHao Wu qemu_set_irq(s->irq, level); 22794e77879SHao Wu } 22894e77879SHao Wu } 22994e77879SHao Wu 23094e77879SHao Wu static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s) 23194e77879SHao Wu { 23294e77879SHao Wu s->st &= ~NPCM7XX_SMBST_SDAST; 23394e77879SHao Wu s->st |= NPCM7XX_SMBST_NEGACK; 23494e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_NEGACK; 23594e77879SHao Wu } 23694e77879SHao Wu 2376b6e7570SHao Wu static void npcm7xx_smbus_clear_buffer(NPCM7xxSMBusState *s) 2386b6e7570SHao Wu { 2396b6e7570SHao Wu s->fif_cts &= ~NPCM7XX_SMBFIF_CTS_RXF_TXE; 2406b6e7570SHao Wu s->txf_sts = 0; 2416b6e7570SHao Wu s->rxf_sts = 0; 2426b6e7570SHao Wu } 2436b6e7570SHao Wu 24494e77879SHao Wu static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value) 24594e77879SHao Wu { 24694e77879SHao Wu int rv = i2c_send(s->bus, value); 24794e77879SHao Wu 24894e77879SHao Wu if (rv) { 24994e77879SHao Wu npcm7xx_smbus_nack(s); 25094e77879SHao Wu } else { 25194e77879SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 2526b6e7570SHao Wu if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { 2536b6e7570SHao Wu s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE; 2546b6e7570SHao Wu if (NPCM7XX_SMBTXF_STS_TX_BYTES(s->txf_sts) == 2556b6e7570SHao Wu NPCM7XX_SMBTXF_CTL_TX_THR(s->txf_ctl)) { 2566b6e7570SHao Wu s->txf_sts = NPCM7XX_SMBTXF_STS_TX_THST; 2576b6e7570SHao Wu } else { 2586b6e7570SHao Wu s->txf_sts = 0; 2596b6e7570SHao Wu } 2606b6e7570SHao Wu } 26194e77879SHao Wu } 26294e77879SHao Wu trace_npcm7xx_smbus_send_byte((DEVICE(s)->canonical_path), value, !rv); 26394e77879SHao Wu npcm7xx_smbus_update_irq(s); 26494e77879SHao Wu } 26594e77879SHao Wu 26694e77879SHao Wu static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s) 26794e77879SHao Wu { 26894e77879SHao Wu s->sda = i2c_recv(s->bus); 26994e77879SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 27094e77879SHao Wu if (s->st & NPCM7XX_SMBCTL1_ACK) { 27194e77879SHao Wu trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); 27294e77879SHao Wu i2c_nack(s->bus); 27394e77879SHao Wu s->st &= NPCM7XX_SMBCTL1_ACK; 27494e77879SHao Wu } 27594e77879SHao Wu trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda); 27694e77879SHao Wu npcm7xx_smbus_update_irq(s); 27794e77879SHao Wu } 27894e77879SHao Wu 2796b6e7570SHao Wu static void npcm7xx_smbus_recv_fifo(NPCM7xxSMBusState *s) 2806b6e7570SHao Wu { 2816b6e7570SHao Wu uint8_t expected_bytes = NPCM7XX_SMBRXF_CTL_RX_THR(s->rxf_ctl); 2826b6e7570SHao Wu uint8_t received_bytes = NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts); 2836b6e7570SHao Wu uint8_t pos; 2846b6e7570SHao Wu 2856b6e7570SHao Wu if (received_bytes == expected_bytes) { 2866b6e7570SHao Wu return; 2876b6e7570SHao Wu } 2886b6e7570SHao Wu 2896b6e7570SHao Wu while (received_bytes < expected_bytes && 2906b6e7570SHao Wu received_bytes < NPCM7XX_SMBUS_FIFO_SIZE) { 2916b6e7570SHao Wu pos = (s->rx_cur + received_bytes) % NPCM7XX_SMBUS_FIFO_SIZE; 2926b6e7570SHao Wu s->rx_fifo[pos] = i2c_recv(s->bus); 2936b6e7570SHao Wu trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), 2946b6e7570SHao Wu s->rx_fifo[pos]); 2956b6e7570SHao Wu ++received_bytes; 2966b6e7570SHao Wu } 2976b6e7570SHao Wu 2986b6e7570SHao Wu trace_npcm7xx_smbus_recv_fifo((DEVICE(s)->canonical_path), 2996b6e7570SHao Wu received_bytes, expected_bytes); 3006b6e7570SHao Wu s->rxf_sts = received_bytes; 3016b6e7570SHao Wu if (unlikely(received_bytes < expected_bytes)) { 3026b6e7570SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 3036b6e7570SHao Wu "%s: invalid rx_thr value: 0x%02x\n", 3046b6e7570SHao Wu DEVICE(s)->canonical_path, expected_bytes); 3056b6e7570SHao Wu return; 3066b6e7570SHao Wu } 3076b6e7570SHao Wu 3086b6e7570SHao Wu s->rxf_sts |= NPCM7XX_SMBRXF_STS_RX_THST; 3096b6e7570SHao Wu if (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_LAST) { 3106b6e7570SHao Wu trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); 3116b6e7570SHao Wu i2c_nack(s->bus); 3126b6e7570SHao Wu s->rxf_ctl &= ~NPCM7XX_SMBRXF_CTL_LAST; 3136b6e7570SHao Wu } 3146b6e7570SHao Wu if (received_bytes == NPCM7XX_SMBUS_FIFO_SIZE) { 3156b6e7570SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 3166b6e7570SHao Wu s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE; 3176b6e7570SHao Wu } else if (!(s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE)) { 3186b6e7570SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 3196b6e7570SHao Wu } else { 3206b6e7570SHao Wu s->st &= ~NPCM7XX_SMBST_SDAST; 3216b6e7570SHao Wu } 3226b6e7570SHao Wu npcm7xx_smbus_update_irq(s); 3236b6e7570SHao Wu } 3246b6e7570SHao Wu 3256b6e7570SHao Wu static void npcm7xx_smbus_read_byte_fifo(NPCM7xxSMBusState *s) 3266b6e7570SHao Wu { 3276b6e7570SHao Wu uint8_t received_bytes = NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts); 3286b6e7570SHao Wu 3296b6e7570SHao Wu if (received_bytes == 0) { 3306b6e7570SHao Wu npcm7xx_smbus_recv_fifo(s); 3316b6e7570SHao Wu return; 3326b6e7570SHao Wu } 3336b6e7570SHao Wu 3346b6e7570SHao Wu s->sda = s->rx_fifo[s->rx_cur]; 3356b6e7570SHao Wu s->rx_cur = (s->rx_cur + 1u) % NPCM7XX_SMBUS_FIFO_SIZE; 3366b6e7570SHao Wu --s->rxf_sts; 3376b6e7570SHao Wu npcm7xx_smbus_update_irq(s); 3386b6e7570SHao Wu } 3396b6e7570SHao Wu 34094e77879SHao Wu static void npcm7xx_smbus_start(NPCM7xxSMBusState *s) 34194e77879SHao Wu { 34294e77879SHao Wu /* 34394e77879SHao Wu * We can start the bus if one of these is true: 34494e77879SHao Wu * 1. The bus is idle (so we can request it) 34594e77879SHao Wu * 2. We are the occupier (it's a repeated start condition.) 34694e77879SHao Wu */ 34794e77879SHao Wu int available = !i2c_bus_busy(s->bus) || 34894e77879SHao Wu s->status != NPCM7XX_SMBUS_STATUS_IDLE; 34994e77879SHao Wu 35094e77879SHao Wu if (available) { 35194e77879SHao Wu s->st |= NPCM7XX_SMBST_MODE | NPCM7XX_SMBST_XMIT | NPCM7XX_SMBST_SDAST; 35294e77879SHao Wu s->cst |= NPCM7XX_SMBCST_BUSY; 3536b6e7570SHao Wu if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { 3546b6e7570SHao Wu s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE; 3556b6e7570SHao Wu } 35694e77879SHao Wu } else { 35794e77879SHao Wu s->st &= ~NPCM7XX_SMBST_MODE; 35894e77879SHao Wu s->cst &= ~NPCM7XX_SMBCST_BUSY; 35994e77879SHao Wu s->st |= NPCM7XX_SMBST_BER; 36094e77879SHao Wu } 36194e77879SHao Wu 36294e77879SHao Wu trace_npcm7xx_smbus_start(DEVICE(s)->canonical_path, available); 36394e77879SHao Wu s->cst |= NPCM7XX_SMBCST_BB; 36494e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_IDLE; 36594e77879SHao Wu npcm7xx_smbus_update_irq(s); 36694e77879SHao Wu } 36794e77879SHao Wu 36894e77879SHao Wu static void npcm7xx_smbus_send_address(NPCM7xxSMBusState *s, uint8_t value) 36994e77879SHao Wu { 37094e77879SHao Wu int recv; 37194e77879SHao Wu int rv; 37294e77879SHao Wu 37394e77879SHao Wu recv = value & BIT(0); 37494e77879SHao Wu rv = i2c_start_transfer(s->bus, value >> 1, recv); 37594e77879SHao Wu trace_npcm7xx_smbus_send_address(DEVICE(s)->canonical_path, 37694e77879SHao Wu value >> 1, recv, !rv); 37794e77879SHao Wu if (rv) { 37894e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 37994e77879SHao Wu "%s: requesting i2c bus for 0x%02x failed: %d\n", 38094e77879SHao Wu DEVICE(s)->canonical_path, value, rv); 38194e77879SHao Wu /* Failed to start transfer. NACK to reject.*/ 38294e77879SHao Wu if (recv) { 38394e77879SHao Wu s->st &= ~NPCM7XX_SMBST_XMIT; 38494e77879SHao Wu } else { 38594e77879SHao Wu s->st |= NPCM7XX_SMBST_XMIT; 38694e77879SHao Wu } 38794e77879SHao Wu npcm7xx_smbus_nack(s); 38894e77879SHao Wu npcm7xx_smbus_update_irq(s); 38994e77879SHao Wu return; 39094e77879SHao Wu } 39194e77879SHao Wu 39294e77879SHao Wu s->st &= ~NPCM7XX_SMBST_NEGACK; 39394e77879SHao Wu if (recv) { 39494e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_RECEIVING; 39594e77879SHao Wu s->st &= ~NPCM7XX_SMBST_XMIT; 39694e77879SHao Wu } else { 39794e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_SENDING; 39894e77879SHao Wu s->st |= NPCM7XX_SMBST_XMIT; 39994e77879SHao Wu } 40094e77879SHao Wu 40194e77879SHao Wu if (s->ctl1 & NPCM7XX_SMBCTL1_STASTRE) { 40294e77879SHao Wu s->st |= NPCM7XX_SMBST_STASTR; 40394e77879SHao Wu if (!recv) { 40494e77879SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 40594e77879SHao Wu } 40694e77879SHao Wu } else if (recv) { 4076b6e7570SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 4086b6e7570SHao Wu if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { 4096b6e7570SHao Wu npcm7xx_smbus_recv_fifo(s); 4106b6e7570SHao Wu } else { 41194e77879SHao Wu npcm7xx_smbus_recv_byte(s); 41294e77879SHao Wu } 4136b6e7570SHao Wu } else if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { 4146b6e7570SHao Wu s->st |= NPCM7XX_SMBST_SDAST; 4156b6e7570SHao Wu s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE; 4166b6e7570SHao Wu } 41794e77879SHao Wu npcm7xx_smbus_update_irq(s); 41894e77879SHao Wu } 41994e77879SHao Wu 42094e77879SHao Wu static void npcm7xx_smbus_execute_stop(NPCM7xxSMBusState *s) 42194e77879SHao Wu { 42294e77879SHao Wu i2c_end_transfer(s->bus); 42394e77879SHao Wu s->st = 0; 42494e77879SHao Wu s->cst = 0; 42594e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_IDLE; 42694e77879SHao Wu s->cst3 |= NPCM7XX_SMBCST3_EO_BUSY; 42794e77879SHao Wu trace_npcm7xx_smbus_stop(DEVICE(s)->canonical_path); 42894e77879SHao Wu npcm7xx_smbus_update_irq(s); 42994e77879SHao Wu } 43094e77879SHao Wu 43194e77879SHao Wu 43294e77879SHao Wu static void npcm7xx_smbus_stop(NPCM7xxSMBusState *s) 43394e77879SHao Wu { 43494e77879SHao Wu if (s->st & NPCM7XX_SMBST_MODE) { 43594e77879SHao Wu switch (s->status) { 43694e77879SHao Wu case NPCM7XX_SMBUS_STATUS_RECEIVING: 43794e77879SHao Wu case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE: 43894e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE; 43994e77879SHao Wu break; 44094e77879SHao Wu 44194e77879SHao Wu case NPCM7XX_SMBUS_STATUS_NEGACK: 44294e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK; 44394e77879SHao Wu break; 44494e77879SHao Wu 44594e77879SHao Wu default: 44694e77879SHao Wu npcm7xx_smbus_execute_stop(s); 44794e77879SHao Wu break; 44894e77879SHao Wu } 44994e77879SHao Wu } 45094e77879SHao Wu } 45194e77879SHao Wu 45294e77879SHao Wu static uint8_t npcm7xx_smbus_read_sda(NPCM7xxSMBusState *s) 45394e77879SHao Wu { 45494e77879SHao Wu uint8_t value = s->sda; 45594e77879SHao Wu 45694e77879SHao Wu switch (s->status) { 45794e77879SHao Wu case NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE: 4586b6e7570SHao Wu if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { 4596b6e7570SHao Wu if (NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) <= 1) { 46094e77879SHao Wu npcm7xx_smbus_execute_stop(s); 4616b6e7570SHao Wu } 4626b6e7570SHao Wu if (NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) == 0) { 4636b6e7570SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 4646b6e7570SHao Wu "%s: read to SDA with an empty rx-fifo buffer, " 4656b6e7570SHao Wu "result undefined: %u\n", 4666b6e7570SHao Wu DEVICE(s)->canonical_path, s->sda); 4676b6e7570SHao Wu break; 4686b6e7570SHao Wu } 4696b6e7570SHao Wu npcm7xx_smbus_read_byte_fifo(s); 4706b6e7570SHao Wu value = s->sda; 4716b6e7570SHao Wu } else { 4726b6e7570SHao Wu npcm7xx_smbus_execute_stop(s); 4736b6e7570SHao Wu } 47494e77879SHao Wu break; 47594e77879SHao Wu 47694e77879SHao Wu case NPCM7XX_SMBUS_STATUS_RECEIVING: 4776b6e7570SHao Wu if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { 4786b6e7570SHao Wu npcm7xx_smbus_read_byte_fifo(s); 4796b6e7570SHao Wu value = s->sda; 4806b6e7570SHao Wu } else { 48194e77879SHao Wu npcm7xx_smbus_recv_byte(s); 4826b6e7570SHao Wu } 48394e77879SHao Wu break; 48494e77879SHao Wu 48594e77879SHao Wu default: 48694e77879SHao Wu /* Do nothing */ 48794e77879SHao Wu break; 48894e77879SHao Wu } 48994e77879SHao Wu 49094e77879SHao Wu return value; 49194e77879SHao Wu } 49294e77879SHao Wu 49394e77879SHao Wu static void npcm7xx_smbus_write_sda(NPCM7xxSMBusState *s, uint8_t value) 49494e77879SHao Wu { 49594e77879SHao Wu s->sda = value; 49694e77879SHao Wu if (s->st & NPCM7XX_SMBST_MODE) { 49794e77879SHao Wu switch (s->status) { 49894e77879SHao Wu case NPCM7XX_SMBUS_STATUS_IDLE: 49994e77879SHao Wu npcm7xx_smbus_send_address(s, value); 50094e77879SHao Wu break; 50194e77879SHao Wu case NPCM7XX_SMBUS_STATUS_SENDING: 50294e77879SHao Wu npcm7xx_smbus_send_byte(s, value); 50394e77879SHao Wu break; 50494e77879SHao Wu default: 50594e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 50694e77879SHao Wu "%s: write to SDA in invalid status %d: %u\n", 50794e77879SHao Wu DEVICE(s)->canonical_path, s->status, value); 50894e77879SHao Wu break; 50994e77879SHao Wu } 51094e77879SHao Wu } 51194e77879SHao Wu } 51294e77879SHao Wu 51394e77879SHao Wu static void npcm7xx_smbus_write_st(NPCM7xxSMBusState *s, uint8_t value) 51494e77879SHao Wu { 51594e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STP); 51694e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_BER); 51794e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_STASTR); 51894e77879SHao Wu s->st = WRITE_ONE_CLEAR(s->st, value, NPCM7XX_SMBST_NMATCH); 51994e77879SHao Wu 52094e77879SHao Wu if (value & NPCM7XX_SMBST_NEGACK) { 52194e77879SHao Wu s->st &= ~NPCM7XX_SMBST_NEGACK; 52294e77879SHao Wu if (s->status == NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK) { 52394e77879SHao Wu npcm7xx_smbus_execute_stop(s); 52494e77879SHao Wu } 52594e77879SHao Wu } 52694e77879SHao Wu 52794e77879SHao Wu if (value & NPCM7XX_SMBST_STASTR && 52894e77879SHao Wu s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { 5296b6e7570SHao Wu if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) { 5306b6e7570SHao Wu npcm7xx_smbus_recv_fifo(s); 5316b6e7570SHao Wu } else { 53294e77879SHao Wu npcm7xx_smbus_recv_byte(s); 53394e77879SHao Wu } 5346b6e7570SHao Wu } 53594e77879SHao Wu 53694e77879SHao Wu npcm7xx_smbus_update_irq(s); 53794e77879SHao Wu } 53894e77879SHao Wu 53994e77879SHao Wu static void npcm7xx_smbus_write_cst(NPCM7xxSMBusState *s, uint8_t value) 54094e77879SHao Wu { 54194e77879SHao Wu uint8_t new_value = s->cst; 54294e77879SHao Wu 54394e77879SHao Wu s->cst = WRITE_ONE_CLEAR(new_value, value, NPCM7XX_SMBCST_BB); 54494e77879SHao Wu npcm7xx_smbus_update_irq(s); 54594e77879SHao Wu } 54694e77879SHao Wu 54794e77879SHao Wu static void npcm7xx_smbus_write_cst3(NPCM7xxSMBusState *s, uint8_t value) 54894e77879SHao Wu { 54994e77879SHao Wu s->cst3 = WRITE_ONE_CLEAR(s->cst3, value, NPCM7XX_SMBCST3_EO_BUSY); 55094e77879SHao Wu npcm7xx_smbus_update_irq(s); 55194e77879SHao Wu } 55294e77879SHao Wu 55394e77879SHao Wu static void npcm7xx_smbus_write_ctl1(NPCM7xxSMBusState *s, uint8_t value) 55494e77879SHao Wu { 55594e77879SHao Wu s->ctl1 = KEEP_OLD_BIT(s->ctl1, value, 55694e77879SHao Wu NPCM7XX_SMBCTL1_START | NPCM7XX_SMBCTL1_STOP | NPCM7XX_SMBCTL1_ACK); 55794e77879SHao Wu 55894e77879SHao Wu if (value & NPCM7XX_SMBCTL1_START) { 55994e77879SHao Wu npcm7xx_smbus_start(s); 56094e77879SHao Wu } 56194e77879SHao Wu 56294e77879SHao Wu if (value & NPCM7XX_SMBCTL1_STOP) { 56394e77879SHao Wu npcm7xx_smbus_stop(s); 56494e77879SHao Wu } 56594e77879SHao Wu 56694e77879SHao Wu npcm7xx_smbus_update_irq(s); 56794e77879SHao Wu } 56894e77879SHao Wu 56994e77879SHao Wu static void npcm7xx_smbus_write_ctl2(NPCM7xxSMBusState *s, uint8_t value) 57094e77879SHao Wu { 57194e77879SHao Wu s->ctl2 = value; 57294e77879SHao Wu 57394e77879SHao Wu if (!NPCM7XX_SMBUS_ENABLED(s)) { 57494e77879SHao Wu /* Disable this SMBus module. */ 57594e77879SHao Wu s->ctl1 = 0; 57694e77879SHao Wu s->st = 0; 57794e77879SHao Wu s->cst3 = s->cst3 & (~NPCM7XX_SMBCST3_EO_BUSY); 57894e77879SHao Wu s->cst = 0; 5796b6e7570SHao Wu npcm7xx_smbus_clear_buffer(s); 58094e77879SHao Wu } 58194e77879SHao Wu } 58294e77879SHao Wu 58394e77879SHao Wu static void npcm7xx_smbus_write_ctl3(NPCM7xxSMBusState *s, uint8_t value) 58494e77879SHao Wu { 58594e77879SHao Wu uint8_t old_ctl3 = s->ctl3; 58694e77879SHao Wu 58794e77879SHao Wu /* Write to SDA and SCL bits are ignored. */ 58894e77879SHao Wu s->ctl3 = KEEP_OLD_BIT(old_ctl3, value, 58994e77879SHao Wu NPCM7XX_SMBCTL3_SCL_LVL | NPCM7XX_SMBCTL3_SDA_LVL); 59094e77879SHao Wu } 59194e77879SHao Wu 5926b6e7570SHao Wu static void npcm7xx_smbus_write_fif_ctl(NPCM7xxSMBusState *s, uint8_t value) 5936b6e7570SHao Wu { 5946b6e7570SHao Wu uint8_t new_ctl = value; 5956b6e7570SHao Wu 5966b6e7570SHao Wu new_ctl = KEEP_OLD_BIT(s->fif_ctl, new_ctl, NPCM7XX_SMBFIF_CTL_FAIR_RDY); 5976b6e7570SHao Wu new_ctl = WRITE_ONE_CLEAR(new_ctl, value, NPCM7XX_SMBFIF_CTL_FAIR_RDY); 5986b6e7570SHao Wu new_ctl = KEEP_OLD_BIT(s->fif_ctl, new_ctl, NPCM7XX_SMBFIF_CTL_FAIR_BUSY); 5996b6e7570SHao Wu s->fif_ctl = new_ctl; 6006b6e7570SHao Wu } 6016b6e7570SHao Wu 6026b6e7570SHao Wu static void npcm7xx_smbus_write_fif_cts(NPCM7xxSMBusState *s, uint8_t value) 6036b6e7570SHao Wu { 6046b6e7570SHao Wu s->fif_cts = WRITE_ONE_CLEAR(s->fif_cts, value, NPCM7XX_SMBFIF_CTS_STR); 6056b6e7570SHao Wu s->fif_cts = WRITE_ONE_CLEAR(s->fif_cts, value, NPCM7XX_SMBFIF_CTS_RXF_TXE); 6066b6e7570SHao Wu s->fif_cts = KEEP_OLD_BIT(value, s->fif_cts, NPCM7XX_SMBFIF_CTS_RFTE_IE); 6076b6e7570SHao Wu 6086b6e7570SHao Wu if (value & NPCM7XX_SMBFIF_CTS_CLR_FIFO) { 6096b6e7570SHao Wu npcm7xx_smbus_clear_buffer(s); 6106b6e7570SHao Wu } 6116b6e7570SHao Wu } 6126b6e7570SHao Wu 6136b6e7570SHao Wu static void npcm7xx_smbus_write_txf_ctl(NPCM7xxSMBusState *s, uint8_t value) 6146b6e7570SHao Wu { 6156b6e7570SHao Wu s->txf_ctl = value; 6166b6e7570SHao Wu } 6176b6e7570SHao Wu 6186b6e7570SHao Wu static void npcm7xx_smbus_write_t_out(NPCM7xxSMBusState *s, uint8_t value) 6196b6e7570SHao Wu { 6206b6e7570SHao Wu uint8_t new_t_out = value; 6216b6e7570SHao Wu 6226b6e7570SHao Wu if ((value & NPCM7XX_SMBT_OUT_ST) || (!(s->t_out & NPCM7XX_SMBT_OUT_ST))) { 6236b6e7570SHao Wu new_t_out &= ~NPCM7XX_SMBT_OUT_ST; 6246b6e7570SHao Wu } else { 6256b6e7570SHao Wu new_t_out |= NPCM7XX_SMBT_OUT_ST; 6266b6e7570SHao Wu } 6276b6e7570SHao Wu 6286b6e7570SHao Wu s->t_out = new_t_out; 6296b6e7570SHao Wu } 6306b6e7570SHao Wu 6316b6e7570SHao Wu static void npcm7xx_smbus_write_txf_sts(NPCM7xxSMBusState *s, uint8_t value) 6326b6e7570SHao Wu { 6336b6e7570SHao Wu s->txf_sts = WRITE_ONE_CLEAR(s->txf_sts, value, NPCM7XX_SMBTXF_STS_TX_THST); 6346b6e7570SHao Wu } 6356b6e7570SHao Wu 6366b6e7570SHao Wu static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t value) 6376b6e7570SHao Wu { 6386b6e7570SHao Wu if (value & NPCM7XX_SMBRXF_STS_RX_THST) { 6396b6e7570SHao Wu s->rxf_sts &= ~NPCM7XX_SMBRXF_STS_RX_THST; 6406b6e7570SHao Wu if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { 6416b6e7570SHao Wu npcm7xx_smbus_recv_fifo(s); 6426b6e7570SHao Wu } 6436b6e7570SHao Wu } 6446b6e7570SHao Wu } 6456b6e7570SHao Wu 6466b6e7570SHao Wu static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t value) 6476b6e7570SHao Wu { 6486b6e7570SHao Wu uint8_t new_ctl = value; 6496b6e7570SHao Wu 6506b6e7570SHao Wu if (!(value & NPCM7XX_SMBRXF_CTL_LAST)) { 6516b6e7570SHao Wu new_ctl = KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_LAST); 6526b6e7570SHao Wu } 6536b6e7570SHao Wu s->rxf_ctl = new_ctl; 6546b6e7570SHao Wu } 6556b6e7570SHao Wu 65694e77879SHao Wu static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size) 65794e77879SHao Wu { 65894e77879SHao Wu NPCM7xxSMBusState *s = opaque; 65994e77879SHao Wu uint64_t value = 0; 66094e77879SHao Wu uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL; 66194e77879SHao Wu 66294e77879SHao Wu /* The order of the registers are their order in memory. */ 66394e77879SHao Wu switch (offset) { 66494e77879SHao Wu case NPCM7XX_SMB_SDA: 66594e77879SHao Wu value = npcm7xx_smbus_read_sda(s); 66694e77879SHao Wu break; 66794e77879SHao Wu 66894e77879SHao Wu case NPCM7XX_SMB_ST: 66994e77879SHao Wu value = s->st; 67094e77879SHao Wu break; 67194e77879SHao Wu 67294e77879SHao Wu case NPCM7XX_SMB_CST: 67394e77879SHao Wu value = s->cst; 67494e77879SHao Wu break; 67594e77879SHao Wu 67694e77879SHao Wu case NPCM7XX_SMB_CTL1: 67794e77879SHao Wu value = s->ctl1; 67894e77879SHao Wu break; 67994e77879SHao Wu 68094e77879SHao Wu case NPCM7XX_SMB_ADDR1: 68194e77879SHao Wu value = s->addr[0]; 68294e77879SHao Wu break; 68394e77879SHao Wu 68494e77879SHao Wu case NPCM7XX_SMB_CTL2: 68594e77879SHao Wu value = s->ctl2; 68694e77879SHao Wu break; 68794e77879SHao Wu 68894e77879SHao Wu case NPCM7XX_SMB_ADDR2: 68994e77879SHao Wu value = s->addr[1]; 69094e77879SHao Wu break; 69194e77879SHao Wu 69294e77879SHao Wu case NPCM7XX_SMB_CTL3: 69394e77879SHao Wu value = s->ctl3; 69494e77879SHao Wu break; 69594e77879SHao Wu 69694e77879SHao Wu case NPCM7XX_SMB_CST2: 69794e77879SHao Wu value = s->cst2; 69894e77879SHao Wu break; 69994e77879SHao Wu 70094e77879SHao Wu case NPCM7XX_SMB_CST3: 70194e77879SHao Wu value = s->cst3; 70294e77879SHao Wu break; 70394e77879SHao Wu 70494e77879SHao Wu case NPCM7XX_SMB_VER: 70594e77879SHao Wu value = npcm7xx_smbus_get_version(); 70694e77879SHao Wu break; 70794e77879SHao Wu 70894e77879SHao Wu /* This register is either invalid or banked at this point. */ 70994e77879SHao Wu default: 71094e77879SHao Wu if (bank) { 71194e77879SHao Wu /* Bank 1 */ 7126b6e7570SHao Wu switch (offset) { 7136b6e7570SHao Wu case NPCM7XX_SMB_FIF_CTS: 7146b6e7570SHao Wu value = s->fif_cts; 7156b6e7570SHao Wu break; 7166b6e7570SHao Wu 7176b6e7570SHao Wu case NPCM7XX_SMB_FAIR_PER: 7186b6e7570SHao Wu value = s->fair_per; 7196b6e7570SHao Wu break; 7206b6e7570SHao Wu 7216b6e7570SHao Wu case NPCM7XX_SMB_TXF_CTL: 7226b6e7570SHao Wu value = s->txf_ctl; 7236b6e7570SHao Wu break; 7246b6e7570SHao Wu 7256b6e7570SHao Wu case NPCM7XX_SMB_T_OUT: 7266b6e7570SHao Wu value = s->t_out; 7276b6e7570SHao Wu break; 7286b6e7570SHao Wu 7296b6e7570SHao Wu case NPCM7XX_SMB_TXF_STS: 7306b6e7570SHao Wu value = s->txf_sts; 7316b6e7570SHao Wu break; 7326b6e7570SHao Wu 7336b6e7570SHao Wu case NPCM7XX_SMB_RXF_STS: 7346b6e7570SHao Wu value = s->rxf_sts; 7356b6e7570SHao Wu break; 7366b6e7570SHao Wu 7376b6e7570SHao Wu case NPCM7XX_SMB_RXF_CTL: 7386b6e7570SHao Wu value = s->rxf_ctl; 7396b6e7570SHao Wu break; 7406b6e7570SHao Wu 7416b6e7570SHao Wu default: 74294e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 74394e77879SHao Wu "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", 74494e77879SHao Wu DEVICE(s)->canonical_path, offset); 7456b6e7570SHao Wu break; 7466b6e7570SHao Wu } 74794e77879SHao Wu } else { 74894e77879SHao Wu /* Bank 0 */ 74994e77879SHao Wu switch (offset) { 75094e77879SHao Wu case NPCM7XX_SMB_ADDR3: 75194e77879SHao Wu value = s->addr[2]; 75294e77879SHao Wu break; 75394e77879SHao Wu 75494e77879SHao Wu case NPCM7XX_SMB_ADDR7: 75594e77879SHao Wu value = s->addr[6]; 75694e77879SHao Wu break; 75794e77879SHao Wu 75894e77879SHao Wu case NPCM7XX_SMB_ADDR4: 75994e77879SHao Wu value = s->addr[3]; 76094e77879SHao Wu break; 76194e77879SHao Wu 76294e77879SHao Wu case NPCM7XX_SMB_ADDR8: 76394e77879SHao Wu value = s->addr[7]; 76494e77879SHao Wu break; 76594e77879SHao Wu 76694e77879SHao Wu case NPCM7XX_SMB_ADDR5: 76794e77879SHao Wu value = s->addr[4]; 76894e77879SHao Wu break; 76994e77879SHao Wu 77094e77879SHao Wu case NPCM7XX_SMB_ADDR9: 77194e77879SHao Wu value = s->addr[8]; 77294e77879SHao Wu break; 77394e77879SHao Wu 77494e77879SHao Wu case NPCM7XX_SMB_ADDR6: 77594e77879SHao Wu value = s->addr[5]; 77694e77879SHao Wu break; 77794e77879SHao Wu 77894e77879SHao Wu case NPCM7XX_SMB_ADDR10: 77994e77879SHao Wu value = s->addr[9]; 78094e77879SHao Wu break; 78194e77879SHao Wu 78294e77879SHao Wu case NPCM7XX_SMB_CTL4: 78394e77879SHao Wu value = s->ctl4; 78494e77879SHao Wu break; 78594e77879SHao Wu 78694e77879SHao Wu case NPCM7XX_SMB_CTL5: 78794e77879SHao Wu value = s->ctl5; 78894e77879SHao Wu break; 78994e77879SHao Wu 79094e77879SHao Wu case NPCM7XX_SMB_SCLLT: 79194e77879SHao Wu value = s->scllt; 79294e77879SHao Wu break; 79394e77879SHao Wu 7946b6e7570SHao Wu case NPCM7XX_SMB_FIF_CTL: 7956b6e7570SHao Wu value = s->fif_ctl; 7966b6e7570SHao Wu break; 7976b6e7570SHao Wu 79894e77879SHao Wu case NPCM7XX_SMB_SCLHT: 79994e77879SHao Wu value = s->sclht; 80094e77879SHao Wu break; 80194e77879SHao Wu 80294e77879SHao Wu default: 80394e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 80494e77879SHao Wu "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", 80594e77879SHao Wu DEVICE(s)->canonical_path, offset); 80694e77879SHao Wu break; 80794e77879SHao Wu } 80894e77879SHao Wu } 80994e77879SHao Wu break; 81094e77879SHao Wu } 81194e77879SHao Wu 81294e77879SHao Wu trace_npcm7xx_smbus_read(DEVICE(s)->canonical_path, offset, value, size); 81394e77879SHao Wu 81494e77879SHao Wu return value; 81594e77879SHao Wu } 81694e77879SHao Wu 81794e77879SHao Wu static void npcm7xx_smbus_write(void *opaque, hwaddr offset, uint64_t value, 81894e77879SHao Wu unsigned size) 81994e77879SHao Wu { 82094e77879SHao Wu NPCM7xxSMBusState *s = opaque; 82194e77879SHao Wu uint8_t bank = s->ctl3 & NPCM7XX_SMBCTL3_BNK_SEL; 82294e77879SHao Wu 82394e77879SHao Wu trace_npcm7xx_smbus_write(DEVICE(s)->canonical_path, offset, value, size); 82494e77879SHao Wu 82594e77879SHao Wu /* The order of the registers are their order in memory. */ 82694e77879SHao Wu switch (offset) { 82794e77879SHao Wu case NPCM7XX_SMB_SDA: 82894e77879SHao Wu npcm7xx_smbus_write_sda(s, value); 82994e77879SHao Wu break; 83094e77879SHao Wu 83194e77879SHao Wu case NPCM7XX_SMB_ST: 83294e77879SHao Wu npcm7xx_smbus_write_st(s, value); 83394e77879SHao Wu break; 83494e77879SHao Wu 83594e77879SHao Wu case NPCM7XX_SMB_CST: 83694e77879SHao Wu npcm7xx_smbus_write_cst(s, value); 83794e77879SHao Wu break; 83894e77879SHao Wu 83994e77879SHao Wu case NPCM7XX_SMB_CTL1: 84094e77879SHao Wu npcm7xx_smbus_write_ctl1(s, value); 84194e77879SHao Wu break; 84294e77879SHao Wu 84394e77879SHao Wu case NPCM7XX_SMB_ADDR1: 84494e77879SHao Wu s->addr[0] = value; 84594e77879SHao Wu break; 84694e77879SHao Wu 84794e77879SHao Wu case NPCM7XX_SMB_CTL2: 84894e77879SHao Wu npcm7xx_smbus_write_ctl2(s, value); 84994e77879SHao Wu break; 85094e77879SHao Wu 85194e77879SHao Wu case NPCM7XX_SMB_ADDR2: 85294e77879SHao Wu s->addr[1] = value; 85394e77879SHao Wu break; 85494e77879SHao Wu 85594e77879SHao Wu case NPCM7XX_SMB_CTL3: 85694e77879SHao Wu npcm7xx_smbus_write_ctl3(s, value); 85794e77879SHao Wu break; 85894e77879SHao Wu 85994e77879SHao Wu case NPCM7XX_SMB_CST2: 86094e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 86194e77879SHao Wu "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n", 86294e77879SHao Wu DEVICE(s)->canonical_path, offset); 86394e77879SHao Wu break; 86494e77879SHao Wu 86594e77879SHao Wu case NPCM7XX_SMB_CST3: 86694e77879SHao Wu npcm7xx_smbus_write_cst3(s, value); 86794e77879SHao Wu break; 86894e77879SHao Wu 86994e77879SHao Wu case NPCM7XX_SMB_VER: 87094e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 87194e77879SHao Wu "%s: write to read-only reg: offset 0x%" HWADDR_PRIx "\n", 87294e77879SHao Wu DEVICE(s)->canonical_path, offset); 87394e77879SHao Wu break; 87494e77879SHao Wu 87594e77879SHao Wu /* This register is either invalid or banked at this point. */ 87694e77879SHao Wu default: 87794e77879SHao Wu if (bank) { 87894e77879SHao Wu /* Bank 1 */ 8796b6e7570SHao Wu switch (offset) { 8806b6e7570SHao Wu case NPCM7XX_SMB_FIF_CTS: 8816b6e7570SHao Wu npcm7xx_smbus_write_fif_cts(s, value); 8826b6e7570SHao Wu break; 8836b6e7570SHao Wu 8846b6e7570SHao Wu case NPCM7XX_SMB_FAIR_PER: 8856b6e7570SHao Wu s->fair_per = value; 8866b6e7570SHao Wu break; 8876b6e7570SHao Wu 8886b6e7570SHao Wu case NPCM7XX_SMB_TXF_CTL: 8896b6e7570SHao Wu npcm7xx_smbus_write_txf_ctl(s, value); 8906b6e7570SHao Wu break; 8916b6e7570SHao Wu 8926b6e7570SHao Wu case NPCM7XX_SMB_T_OUT: 8936b6e7570SHao Wu npcm7xx_smbus_write_t_out(s, value); 8946b6e7570SHao Wu break; 8956b6e7570SHao Wu 8966b6e7570SHao Wu case NPCM7XX_SMB_TXF_STS: 8976b6e7570SHao Wu npcm7xx_smbus_write_txf_sts(s, value); 8986b6e7570SHao Wu break; 8996b6e7570SHao Wu 9006b6e7570SHao Wu case NPCM7XX_SMB_RXF_STS: 9016b6e7570SHao Wu npcm7xx_smbus_write_rxf_sts(s, value); 9026b6e7570SHao Wu break; 9036b6e7570SHao Wu 9046b6e7570SHao Wu case NPCM7XX_SMB_RXF_CTL: 9056b6e7570SHao Wu npcm7xx_smbus_write_rxf_ctl(s, value); 9066b6e7570SHao Wu break; 9076b6e7570SHao Wu 9086b6e7570SHao Wu default: 90994e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 91094e77879SHao Wu "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", 91194e77879SHao Wu DEVICE(s)->canonical_path, offset); 9126b6e7570SHao Wu break; 9136b6e7570SHao Wu } 91494e77879SHao Wu } else { 91594e77879SHao Wu /* Bank 0 */ 91694e77879SHao Wu switch (offset) { 91794e77879SHao Wu case NPCM7XX_SMB_ADDR3: 91894e77879SHao Wu s->addr[2] = value; 91994e77879SHao Wu break; 92094e77879SHao Wu 92194e77879SHao Wu case NPCM7XX_SMB_ADDR7: 92294e77879SHao Wu s->addr[6] = value; 92394e77879SHao Wu break; 92494e77879SHao Wu 92594e77879SHao Wu case NPCM7XX_SMB_ADDR4: 92694e77879SHao Wu s->addr[3] = value; 92794e77879SHao Wu break; 92894e77879SHao Wu 92994e77879SHao Wu case NPCM7XX_SMB_ADDR8: 93094e77879SHao Wu s->addr[7] = value; 93194e77879SHao Wu break; 93294e77879SHao Wu 93394e77879SHao Wu case NPCM7XX_SMB_ADDR5: 93494e77879SHao Wu s->addr[4] = value; 93594e77879SHao Wu break; 93694e77879SHao Wu 93794e77879SHao Wu case NPCM7XX_SMB_ADDR9: 93894e77879SHao Wu s->addr[8] = value; 93994e77879SHao Wu break; 94094e77879SHao Wu 94194e77879SHao Wu case NPCM7XX_SMB_ADDR6: 94294e77879SHao Wu s->addr[5] = value; 94394e77879SHao Wu break; 94494e77879SHao Wu 94594e77879SHao Wu case NPCM7XX_SMB_ADDR10: 94694e77879SHao Wu s->addr[9] = value; 94794e77879SHao Wu break; 94894e77879SHao Wu 94994e77879SHao Wu case NPCM7XX_SMB_CTL4: 95094e77879SHao Wu s->ctl4 = value; 95194e77879SHao Wu break; 95294e77879SHao Wu 95394e77879SHao Wu case NPCM7XX_SMB_CTL5: 95494e77879SHao Wu s->ctl5 = value; 95594e77879SHao Wu break; 95694e77879SHao Wu 95794e77879SHao Wu case NPCM7XX_SMB_SCLLT: 95894e77879SHao Wu s->scllt = value; 95994e77879SHao Wu break; 96094e77879SHao Wu 9616b6e7570SHao Wu case NPCM7XX_SMB_FIF_CTL: 9626b6e7570SHao Wu npcm7xx_smbus_write_fif_ctl(s, value); 9636b6e7570SHao Wu break; 9646b6e7570SHao Wu 96594e77879SHao Wu case NPCM7XX_SMB_SCLHT: 96694e77879SHao Wu s->sclht = value; 96794e77879SHao Wu break; 96894e77879SHao Wu 96994e77879SHao Wu default: 97094e77879SHao Wu qemu_log_mask(LOG_GUEST_ERROR, 97194e77879SHao Wu "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", 97294e77879SHao Wu DEVICE(s)->canonical_path, offset); 97394e77879SHao Wu break; 97494e77879SHao Wu } 97594e77879SHao Wu } 97694e77879SHao Wu break; 97794e77879SHao Wu } 97894e77879SHao Wu } 97994e77879SHao Wu 98094e77879SHao Wu static const MemoryRegionOps npcm7xx_smbus_ops = { 98194e77879SHao Wu .read = npcm7xx_smbus_read, 98294e77879SHao Wu .write = npcm7xx_smbus_write, 98394e77879SHao Wu .endianness = DEVICE_LITTLE_ENDIAN, 98494e77879SHao Wu .valid = { 98594e77879SHao Wu .min_access_size = 1, 98694e77879SHao Wu .max_access_size = 1, 98794e77879SHao Wu .unaligned = false, 98894e77879SHao Wu }, 98994e77879SHao Wu }; 99094e77879SHao Wu 99194e77879SHao Wu static void npcm7xx_smbus_enter_reset(Object *obj, ResetType type) 99294e77879SHao Wu { 99394e77879SHao Wu NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj); 99494e77879SHao Wu 99594e77879SHao Wu s->st = NPCM7XX_SMB_ST_INIT_VAL; 99694e77879SHao Wu s->cst = NPCM7XX_SMB_CST_INIT_VAL; 99794e77879SHao Wu s->cst2 = NPCM7XX_SMB_CST2_INIT_VAL; 99894e77879SHao Wu s->cst3 = NPCM7XX_SMB_CST3_INIT_VAL; 99994e77879SHao Wu s->ctl1 = NPCM7XX_SMB_CTL1_INIT_VAL; 100094e77879SHao Wu s->ctl2 = NPCM7XX_SMB_CTL2_INIT_VAL; 100194e77879SHao Wu s->ctl3 = NPCM7XX_SMB_CTL3_INIT_VAL; 100294e77879SHao Wu s->ctl4 = NPCM7XX_SMB_CTL4_INIT_VAL; 100394e77879SHao Wu s->ctl5 = NPCM7XX_SMB_CTL5_INIT_VAL; 100494e77879SHao Wu 100594e77879SHao Wu for (int i = 0; i < NPCM7XX_SMBUS_NR_ADDRS; ++i) { 100694e77879SHao Wu s->addr[i] = NPCM7XX_SMB_ADDR_INIT_VAL; 100794e77879SHao Wu } 100894e77879SHao Wu s->scllt = NPCM7XX_SMB_SCLLT_INIT_VAL; 100994e77879SHao Wu s->sclht = NPCM7XX_SMB_SCLHT_INIT_VAL; 101094e77879SHao Wu 10116b6e7570SHao Wu s->fif_ctl = NPCM7XX_SMB_FIF_CTL_INIT_VAL; 10126b6e7570SHao Wu s->fif_cts = NPCM7XX_SMB_FIF_CTS_INIT_VAL; 10136b6e7570SHao Wu s->fair_per = NPCM7XX_SMB_FAIR_PER_INIT_VAL; 10146b6e7570SHao Wu s->txf_ctl = NPCM7XX_SMB_TXF_CTL_INIT_VAL; 10156b6e7570SHao Wu s->t_out = NPCM7XX_SMB_T_OUT_INIT_VAL; 10166b6e7570SHao Wu s->txf_sts = NPCM7XX_SMB_TXF_STS_INIT_VAL; 10176b6e7570SHao Wu s->rxf_sts = NPCM7XX_SMB_RXF_STS_INIT_VAL; 10186b6e7570SHao Wu s->rxf_ctl = NPCM7XX_SMB_RXF_CTL_INIT_VAL; 10196b6e7570SHao Wu 10206b6e7570SHao Wu npcm7xx_smbus_clear_buffer(s); 102194e77879SHao Wu s->status = NPCM7XX_SMBUS_STATUS_IDLE; 10226b6e7570SHao Wu s->rx_cur = 0; 102394e77879SHao Wu } 102494e77879SHao Wu 1025ad80e367SPeter Maydell static void npcm7xx_smbus_hold_reset(Object *obj, ResetType type) 102694e77879SHao Wu { 102794e77879SHao Wu NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj); 102894e77879SHao Wu 102994e77879SHao Wu qemu_irq_lower(s->irq); 103094e77879SHao Wu } 103194e77879SHao Wu 103294e77879SHao Wu static void npcm7xx_smbus_init(Object *obj) 103394e77879SHao Wu { 103494e77879SHao Wu NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj); 103594e77879SHao Wu SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 103694e77879SHao Wu 103794e77879SHao Wu sysbus_init_irq(sbd, &s->irq); 103894e77879SHao Wu memory_region_init_io(&s->iomem, obj, &npcm7xx_smbus_ops, s, 103994e77879SHao Wu "regs", 4 * KiB); 104094e77879SHao Wu sysbus_init_mmio(sbd, &s->iomem); 104194e77879SHao Wu 104294e77879SHao Wu s->bus = i2c_init_bus(DEVICE(s), "i2c-bus"); 104394e77879SHao Wu } 104494e77879SHao Wu 104594e77879SHao Wu static const VMStateDescription vmstate_npcm7xx_smbus = { 104694e77879SHao Wu .name = "npcm7xx-smbus", 104794e77879SHao Wu .version_id = 0, 104894e77879SHao Wu .minimum_version_id = 0, 104901d9442aSRichard Henderson .fields = (const VMStateField[]) { 105094e77879SHao Wu VMSTATE_UINT8(sda, NPCM7xxSMBusState), 105194e77879SHao Wu VMSTATE_UINT8(st, NPCM7xxSMBusState), 105294e77879SHao Wu VMSTATE_UINT8(cst, NPCM7xxSMBusState), 105394e77879SHao Wu VMSTATE_UINT8(cst2, NPCM7xxSMBusState), 105494e77879SHao Wu VMSTATE_UINT8(cst3, NPCM7xxSMBusState), 105594e77879SHao Wu VMSTATE_UINT8(ctl1, NPCM7xxSMBusState), 105694e77879SHao Wu VMSTATE_UINT8(ctl2, NPCM7xxSMBusState), 105794e77879SHao Wu VMSTATE_UINT8(ctl3, NPCM7xxSMBusState), 105894e77879SHao Wu VMSTATE_UINT8(ctl4, NPCM7xxSMBusState), 105994e77879SHao Wu VMSTATE_UINT8(ctl5, NPCM7xxSMBusState), 106094e77879SHao Wu VMSTATE_UINT8_ARRAY(addr, NPCM7xxSMBusState, NPCM7XX_SMBUS_NR_ADDRS), 106194e77879SHao Wu VMSTATE_UINT8(scllt, NPCM7xxSMBusState), 106294e77879SHao Wu VMSTATE_UINT8(sclht, NPCM7xxSMBusState), 10636b6e7570SHao Wu VMSTATE_UINT8(fif_ctl, NPCM7xxSMBusState), 10646b6e7570SHao Wu VMSTATE_UINT8(fif_cts, NPCM7xxSMBusState), 10656b6e7570SHao Wu VMSTATE_UINT8(fair_per, NPCM7xxSMBusState), 10666b6e7570SHao Wu VMSTATE_UINT8(txf_ctl, NPCM7xxSMBusState), 10676b6e7570SHao Wu VMSTATE_UINT8(t_out, NPCM7xxSMBusState), 10686b6e7570SHao Wu VMSTATE_UINT8(txf_sts, NPCM7xxSMBusState), 10696b6e7570SHao Wu VMSTATE_UINT8(rxf_sts, NPCM7xxSMBusState), 10706b6e7570SHao Wu VMSTATE_UINT8(rxf_ctl, NPCM7xxSMBusState), 10716b6e7570SHao Wu VMSTATE_UINT8_ARRAY(rx_fifo, NPCM7xxSMBusState, 10726b6e7570SHao Wu NPCM7XX_SMBUS_FIFO_SIZE), 10736b6e7570SHao Wu VMSTATE_UINT8(rx_cur, NPCM7xxSMBusState), 107494e77879SHao Wu VMSTATE_END_OF_LIST(), 107594e77879SHao Wu }, 107694e77879SHao Wu }; 107794e77879SHao Wu 1078*12d1a768SPhilippe Mathieu-Daudé static void npcm7xx_smbus_class_init(ObjectClass *klass, const void *data) 107994e77879SHao Wu { 108094e77879SHao Wu ResettableClass *rc = RESETTABLE_CLASS(klass); 108194e77879SHao Wu DeviceClass *dc = DEVICE_CLASS(klass); 108294e77879SHao Wu 108394e77879SHao Wu dc->desc = "NPCM7xx System Management Bus"; 108494e77879SHao Wu dc->vmsd = &vmstate_npcm7xx_smbus; 108594e77879SHao Wu rc->phases.enter = npcm7xx_smbus_enter_reset; 108694e77879SHao Wu rc->phases.hold = npcm7xx_smbus_hold_reset; 108794e77879SHao Wu } 108894e77879SHao Wu 108994e77879SHao Wu static const TypeInfo npcm7xx_smbus_types[] = { 109094e77879SHao Wu { 109194e77879SHao Wu .name = TYPE_NPCM7XX_SMBUS, 109294e77879SHao Wu .parent = TYPE_SYS_BUS_DEVICE, 109394e77879SHao Wu .instance_size = sizeof(NPCM7xxSMBusState), 109494e77879SHao Wu .class_init = npcm7xx_smbus_class_init, 109594e77879SHao Wu .instance_init = npcm7xx_smbus_init, 109694e77879SHao Wu }, 109794e77879SHao Wu }; 109894e77879SHao Wu DEFINE_TYPES(npcm7xx_smbus_types); 1099