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