1 /* 2 * QEMU PowerPC PowerNV Processor I2C model 3 * 4 * Copyright (c) 2019-2023, IBM Corporation. 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu/module.h" 11 #include "qemu/log.h" 12 #include "sysemu/reset.h" 13 14 #include "hw/irq.h" 15 #include "hw/qdev-properties.h" 16 17 #include "hw/ppc/pnv.h" 18 #include "hw/ppc/pnv_chip.h" 19 #include "hw/ppc/pnv_i2c.h" 20 #include "hw/ppc/pnv_xscom.h" 21 #include "hw/ppc/fdt.h" 22 23 #include <libfdt.h> 24 25 #include "hw/i2c/pnv_i2c_regs.h" 26 27 static I2CBus *pnv_i2c_get_bus(PnvI2C *i2c) 28 { 29 uint8_t port = GETFIELD(I2C_MODE_PORT_NUM, i2c->regs[I2C_MODE_REG]); 30 31 if (port >= i2c->num_busses) { 32 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid bus number %d/%d\n", port, 33 i2c->num_busses); 34 return NULL; 35 } 36 return i2c->busses[port]; 37 } 38 39 static void pnv_i2c_update_irq(PnvI2C *i2c) 40 { 41 I2CBus *bus = pnv_i2c_get_bus(i2c); 42 bool recv = !!(i2c->regs[I2C_CMD_REG] & I2C_CMD_READ_NOT_WRITE); 43 uint16_t front_end = GETFIELD(I2C_RESIDUAL_FRONT_END, 44 i2c->regs[I2C_RESIDUAL_LEN_REG]); 45 uint16_t back_end = GETFIELD(I2C_RESIDUAL_BACK_END, 46 i2c->regs[I2C_RESIDUAL_LEN_REG]); 47 uint8_t fifo_count = GETFIELD(I2C_STAT_FIFO_ENTRY_COUNT, 48 i2c->regs[I2C_STAT_REG]); 49 uint8_t fifo_free = PNV_I2C_FIFO_SIZE - fifo_count; 50 51 if (!bus) { 52 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid port\n"); 53 return; 54 } 55 56 if (i2c_bus_busy(bus)) { 57 i2c->regs[I2C_STAT_REG] &= ~I2C_STAT_DATA_REQ; 58 59 if (recv) { 60 if (fifo_count >= 61 GETFIELD(I2C_WATERMARK_HIGH, i2c->regs[I2C_WATERMARK_REG])) { 62 i2c->regs[I2C_EXTD_STAT_REG] |= I2C_EXTD_STAT_HIGH_WATER; 63 } else { 64 i2c->regs[I2C_EXTD_STAT_REG] &= ~I2C_EXTD_STAT_HIGH_WATER; 65 } 66 67 if (((i2c->regs[I2C_EXTD_STAT_REG] & I2C_EXTD_STAT_HIGH_WATER) && 68 fifo_count != 0) || front_end == 0) { 69 i2c->regs[I2C_STAT_REG] |= I2C_STAT_DATA_REQ; 70 } 71 } else { 72 if (fifo_count <= 73 GETFIELD(I2C_WATERMARK_LOW, i2c->regs[I2C_WATERMARK_REG])) { 74 i2c->regs[I2C_EXTD_STAT_REG] |= I2C_EXTD_STAT_LOW_WATER; 75 } else { 76 i2c->regs[I2C_EXTD_STAT_REG] &= ~I2C_EXTD_STAT_LOW_WATER; 77 } 78 79 if (back_end > 0 && 80 (fifo_free >= back_end || 81 (i2c->regs[I2C_EXTD_STAT_REG] & I2C_EXTD_STAT_LOW_WATER))) { 82 i2c->regs[I2C_STAT_REG] |= I2C_STAT_DATA_REQ; 83 } 84 } 85 86 if (back_end == 0 && front_end == 0) { 87 i2c->regs[I2C_STAT_REG] &= ~I2C_STAT_DATA_REQ; 88 i2c->regs[I2C_STAT_REG] |= I2C_STAT_CMD_COMP; 89 90 if (i2c->regs[I2C_CMD_REG] & I2C_CMD_WITH_STOP) { 91 i2c_end_transfer(bus); 92 i2c->regs[I2C_EXTD_STAT_REG] &= 93 ~(I2C_EXTD_STAT_I2C_BUSY | I2C_EXTD_STAT_SELF_BUSY); 94 } 95 } else { 96 i2c->regs[I2C_STAT_REG] &= ~I2C_STAT_CMD_COMP; 97 } 98 } 99 100 /* 101 * Status and interrupt registers have nearly the same layout. 102 */ 103 i2c->regs[I2C_INTR_RAW_COND_REG] = i2c->regs[I2C_STAT_REG] >> 16; 104 i2c->regs[I2C_INTR_COND_REG] = 105 i2c->regs[I2C_INTR_RAW_COND_REG] & i2c->regs[I2C_INTR_MASK_REG]; 106 107 qemu_set_irq(i2c->psi_irq, i2c->regs[I2C_INTR_COND_REG] != 0); 108 } 109 110 static void pnv_i2c_fifo_update_count(PnvI2C *i2c) 111 { 112 uint64_t stat = i2c->regs[I2C_STAT_REG]; 113 114 i2c->regs[I2C_STAT_REG] = SETFIELD(I2C_STAT_FIFO_ENTRY_COUNT, stat, 115 fifo8_num_used(&i2c->fifo)); 116 } 117 118 static void pnv_i2c_frontend_update(PnvI2C *i2c) 119 { 120 uint64_t residual_end = i2c->regs[I2C_RESIDUAL_LEN_REG]; 121 uint16_t front_end = GETFIELD(I2C_RESIDUAL_FRONT_END, residual_end); 122 123 i2c->regs[I2C_RESIDUAL_LEN_REG] = 124 SETFIELD(I2C_RESIDUAL_FRONT_END, residual_end, front_end - 1); 125 } 126 127 static void pnv_i2c_fifo_flush(PnvI2C *i2c) 128 { 129 I2CBus *bus = pnv_i2c_get_bus(i2c); 130 uint8_t data; 131 int ret; 132 133 if (!bus) { 134 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid port\n"); 135 return; 136 } 137 if (!i2c_bus_busy(bus)) { 138 return; 139 } 140 141 if (i2c->regs[I2C_CMD_REG] & I2C_CMD_READ_NOT_WRITE) { 142 if (fifo8_is_full(&i2c->fifo)) { 143 return; 144 } 145 146 data = i2c_recv(bus); 147 fifo8_push(&i2c->fifo, data); 148 } else { 149 if (fifo8_is_empty(&i2c->fifo)) { 150 return; 151 } 152 153 data = fifo8_pop(&i2c->fifo); 154 ret = i2c_send(bus, data); 155 if (ret) { 156 i2c->regs[I2C_STAT_REG] |= I2C_STAT_NACK_RCVD_ERR; 157 i2c_end_transfer(bus); 158 } 159 } 160 161 pnv_i2c_fifo_update_count(i2c); 162 pnv_i2c_frontend_update(i2c); 163 } 164 165 static void pnv_i2c_handle_cmd(PnvI2C *i2c, uint64_t val) 166 { 167 I2CBus *bus = pnv_i2c_get_bus(i2c); 168 uint8_t addr = GETFIELD(I2C_CMD_DEV_ADDR, val); 169 int recv = !!(val & I2C_CMD_READ_NOT_WRITE); 170 uint32_t len_bytes = GETFIELD(I2C_CMD_LEN_BYTES, val); 171 172 if (!(val & I2C_CMD_WITH_START) && !(val & I2C_CMD_WITH_ADDR) && 173 !(val & I2C_CMD_WITH_STOP) && !len_bytes) { 174 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 175 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid command 0x%"PRIx64"\n", 176 val); 177 return; 178 } 179 180 if (!(i2c->regs[I2C_STAT_REG] & I2C_STAT_CMD_COMP)) { 181 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 182 qemu_log_mask(LOG_GUEST_ERROR, "I2C: command in progress\n"); 183 return; 184 } 185 186 if (!bus) { 187 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid port\n"); 188 return; 189 } 190 191 i2c->regs[I2C_RESIDUAL_LEN_REG] = 192 SETFIELD(I2C_RESIDUAL_FRONT_END, 0ull, len_bytes) | 193 SETFIELD(I2C_RESIDUAL_BACK_END, 0ull, len_bytes); 194 195 if (val & I2C_CMD_WITH_START) { 196 if (i2c_start_transfer(bus, addr, recv)) { 197 i2c->regs[I2C_STAT_REG] |= I2C_STAT_NACK_RCVD_ERR; 198 } else { 199 i2c->regs[I2C_EXTD_STAT_REG] |= 200 (I2C_EXTD_STAT_I2C_BUSY | I2C_EXTD_STAT_SELF_BUSY); 201 pnv_i2c_fifo_flush(i2c); 202 } 203 } 204 } 205 206 static void pnv_i2c_backend_update(PnvI2C *i2c) 207 { 208 uint64_t residual_end = i2c->regs[I2C_RESIDUAL_LEN_REG]; 209 uint16_t back_end = GETFIELD(I2C_RESIDUAL_BACK_END, residual_end); 210 211 if (!back_end) { 212 i2c->regs[I2C_STAT_REG] |= I2C_STAT_BKEND_ACCESS_ERR; 213 return; 214 } 215 216 i2c->regs[I2C_RESIDUAL_LEN_REG] = 217 SETFIELD(I2C_RESIDUAL_BACK_END, residual_end, back_end - 1); 218 } 219 220 static void pnv_i2c_fifo_in(PnvI2C *i2c) 221 { 222 uint8_t data = GETFIELD(I2C_FIFO, i2c->regs[I2C_FIFO_REG]); 223 I2CBus *bus = pnv_i2c_get_bus(i2c); 224 225 if (!bus) { 226 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid port\n"); 227 return; 228 } 229 230 if (!i2c_bus_busy(bus)) { 231 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 232 qemu_log_mask(LOG_GUEST_ERROR, "I2C: no command in progress\n"); 233 return; 234 } 235 236 if (i2c->regs[I2C_CMD_REG] & I2C_CMD_READ_NOT_WRITE) { 237 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 238 qemu_log_mask(LOG_GUEST_ERROR, "I2C: read command in progress\n"); 239 return; 240 } 241 242 if (fifo8_is_full(&i2c->fifo)) { 243 if (!(i2c->regs[I2C_MODE_REG] & I2C_MODE_PACING_ALLOW)) { 244 i2c->regs[I2C_STAT_REG] |= I2C_STAT_BKEND_OVERRUN_ERR; 245 } 246 return; 247 } 248 249 fifo8_push(&i2c->fifo, data); 250 pnv_i2c_fifo_update_count(i2c); 251 pnv_i2c_backend_update(i2c); 252 pnv_i2c_fifo_flush(i2c); 253 } 254 255 static void pnv_i2c_fifo_out(PnvI2C *i2c) 256 { 257 uint8_t data; 258 I2CBus *bus = pnv_i2c_get_bus(i2c); 259 260 if (!bus) { 261 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid port\n"); 262 return; 263 } 264 265 if (!i2c_bus_busy(bus)) { 266 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 267 qemu_log_mask(LOG_GUEST_ERROR, "I2C: no command in progress\n"); 268 return; 269 } 270 271 if (!(i2c->regs[I2C_CMD_REG] & I2C_CMD_READ_NOT_WRITE)) { 272 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 273 qemu_log_mask(LOG_GUEST_ERROR, "I2C: write command in progress\n"); 274 return; 275 } 276 277 if (fifo8_is_empty(&i2c->fifo)) { 278 if (!(i2c->regs[I2C_MODE_REG] & I2C_MODE_PACING_ALLOW)) { 279 i2c->regs[I2C_STAT_REG] |= I2C_STAT_BKEND_OVERRUN_ERR; 280 } 281 return; 282 } 283 284 data = fifo8_pop(&i2c->fifo); 285 286 i2c->regs[I2C_FIFO_REG] = SETFIELD(I2C_FIFO, 0ull, data); 287 pnv_i2c_fifo_update_count(i2c); 288 pnv_i2c_backend_update(i2c); 289 } 290 291 static uint64_t pnv_i2c_xscom_read(void *opaque, hwaddr addr, 292 unsigned size) 293 { 294 PnvI2C *i2c = PNV_I2C(opaque); 295 uint32_t offset = addr >> 3; 296 uint64_t val = -1; 297 int i; 298 299 switch (offset) { 300 case I2C_STAT_REG: 301 val = i2c->regs[offset]; 302 break; 303 304 case I2C_FIFO_REG: 305 pnv_i2c_fifo_out(i2c); 306 val = i2c->regs[offset]; 307 break; 308 309 case I2C_PORT_BUSY_REG: /* compute busy bit for each port */ 310 val = 0; 311 for (i = 0; i < i2c->num_busses; i++) { 312 val |= (uint64_t)i2c_bus_busy(i2c->busses[i]) << i; 313 } 314 break; 315 316 case I2C_CMD_REG: 317 case I2C_MODE_REG: 318 case I2C_WATERMARK_REG: 319 case I2C_INTR_MASK_REG: 320 case I2C_INTR_RAW_COND_REG: 321 case I2C_INTR_COND_REG: 322 case I2C_EXTD_STAT_REG: 323 case I2C_RESIDUAL_LEN_REG: 324 val = i2c->regs[offset]; 325 break; 326 default: 327 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 328 qemu_log_mask(LOG_GUEST_ERROR, "I2C: read at register: 0x%" 329 HWADDR_PRIx "\n", addr >> 3); 330 } 331 332 pnv_i2c_update_irq(i2c); 333 334 return val; 335 } 336 337 static void pnv_i2c_reset(void *dev) 338 { 339 PnvI2C *i2c = PNV_I2C(dev); 340 341 memset(i2c->regs, 0, sizeof(i2c->regs)); 342 343 i2c->regs[I2C_STAT_REG] = 344 SETFIELD(I2C_STAT_UPPER_THRS, 0ull, i2c->num_busses - 1) | 345 I2C_STAT_CMD_COMP | I2C_STAT_SCL_INPUT_LEVEL | 346 I2C_STAT_SDA_INPUT_LEVEL; 347 i2c->regs[I2C_EXTD_STAT_REG] = 348 SETFIELD(I2C_EXTD_STAT_FIFO_SIZE, 0ull, PNV_I2C_FIFO_SIZE) | 349 SETFIELD(I2C_EXTD_STAT_I2C_VERSION, 0ull, 23); /* last version */ 350 351 fifo8_reset(&i2c->fifo); 352 } 353 354 static void pnv_i2c_xscom_write(void *opaque, hwaddr addr, 355 uint64_t val, unsigned size) 356 { 357 PnvI2C *i2c = PNV_I2C(opaque); 358 uint32_t offset = addr >> 3; 359 360 switch (offset) { 361 case I2C_MODE_REG: 362 { 363 i2c->regs[offset] = val; 364 I2CBus *bus = pnv_i2c_get_bus(i2c); 365 if (!bus) { 366 qemu_log_mask(LOG_GUEST_ERROR, "I2C: invalid port\n"); 367 return; 368 } 369 if (i2c_bus_busy(bus)) { 370 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 371 qemu_log_mask(LOG_GUEST_ERROR, "I2C: command in progress\n"); 372 } 373 } 374 break; 375 376 case I2C_CMD_REG: 377 i2c->regs[offset] = val; 378 pnv_i2c_handle_cmd(i2c, val); 379 break; 380 381 case I2C_FIFO_REG: 382 i2c->regs[offset] = val; 383 pnv_i2c_fifo_in(i2c); 384 break; 385 386 case I2C_WATERMARK_REG: 387 i2c->regs[offset] = val; 388 break; 389 390 case I2C_RESET_I2C_REG: 391 pnv_i2c_reset(i2c); 392 break; 393 394 case I2C_RESET_ERRORS: 395 i2c->regs[I2C_STAT_REG] &= ~I2C_STAT_ANY_ERR; 396 i2c->regs[I2C_RESIDUAL_LEN_REG] = 0; 397 i2c->regs[I2C_EXTD_STAT_REG] &= 398 (I2C_EXTD_STAT_FIFO_SIZE | I2C_EXTD_STAT_I2C_VERSION); 399 fifo8_reset(&i2c->fifo); 400 break; 401 402 case I2C_INTR_MASK_REG: 403 i2c->regs[offset] = val; 404 break; 405 406 case I2C_INTR_MASK_OR_REG: 407 i2c->regs[I2C_INTR_MASK_REG] |= val; 408 break; 409 410 case I2C_INTR_MASK_AND_REG: 411 i2c->regs[I2C_INTR_MASK_REG] &= val; 412 break; 413 414 case I2C_PORT_BUSY_REG: 415 case I2C_SET_S_SCL_REG: 416 case I2C_RESET_S_SCL_REG: 417 case I2C_SET_S_SDA_REG: 418 case I2C_RESET_S_SDA_REG: 419 i2c->regs[offset] = val; 420 break; 421 default: 422 i2c->regs[I2C_STAT_REG] |= I2C_STAT_INVALID_CMD; 423 qemu_log_mask(LOG_GUEST_ERROR, "I2C: write at register: 0x%" 424 HWADDR_PRIx " val=0x%"PRIx64"\n", addr >> 3, val); 425 } 426 427 pnv_i2c_update_irq(i2c); 428 } 429 430 static const MemoryRegionOps pnv_i2c_xscom_ops = { 431 .read = pnv_i2c_xscom_read, 432 .write = pnv_i2c_xscom_write, 433 .valid.min_access_size = 8, 434 .valid.max_access_size = 8, 435 .impl.min_access_size = 8, 436 .impl.max_access_size = 8, 437 .endianness = DEVICE_BIG_ENDIAN, 438 }; 439 440 static int pnv_i2c_bus_dt_xscom(PnvI2C *i2c, void *fdt, 441 int offset, int index) 442 { 443 int i2c_bus_offset; 444 const char i2c_compat[] = 445 "ibm,opal-i2c\0ibm,power8-i2c-port\0ibm,power9-i2c-port"; 446 g_autofree char *i2c_port_name = NULL; 447 g_autofree char *name = g_strdup_printf("i2c-bus@%x", index); 448 449 i2c_bus_offset = fdt_add_subnode(fdt, offset, name); 450 _FDT(i2c_bus_offset); 451 452 _FDT((fdt_setprop_cell(fdt, i2c_bus_offset, "reg", index))); 453 _FDT((fdt_setprop_cell(fdt, i2c_bus_offset, "#address-cells", 1))); 454 _FDT((fdt_setprop_cell(fdt, i2c_bus_offset, "#size-cells", 0))); 455 _FDT(fdt_setprop(fdt, i2c_bus_offset, "compatible", i2c_compat, 456 sizeof(i2c_compat))); 457 _FDT((fdt_setprop_cell(fdt, i2c_bus_offset, "bus-frequency", 400000))); 458 459 i2c_port_name = g_strdup_printf("p8_%08x_e%dp%d", i2c->chip->chip_id, 460 i2c->engine, index); 461 _FDT(fdt_setprop_string(fdt, i2c_bus_offset, "ibm,port-name", 462 i2c_port_name)); 463 return 0; 464 } 465 466 #define XSCOM_BUS_FREQUENCY 466500000 467 #define I2C_CLOCK_FREQUENCY (XSCOM_BUS_FREQUENCY / 4) 468 469 static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt, 470 int offset) 471 { 472 PnvI2C *i2c = PNV_I2C(dev); 473 int i2c_offset; 474 const char i2c_compat[] = "ibm,power8-i2cm\0ibm,power9-i2cm"; 475 uint32_t i2c_pcba = PNV9_XSCOM_I2CM_BASE + 476 (i2c->engine - 1) * PNV9_XSCOM_I2CM_SIZE; 477 uint32_t reg[2] = { 478 cpu_to_be32(i2c_pcba), 479 cpu_to_be32(PNV9_XSCOM_I2CM_SIZE) 480 }; 481 int i; 482 g_autofree char *name = g_strdup_printf("i2cm@%x", i2c_pcba); 483 484 i2c_offset = fdt_add_subnode(fdt, offset, name); 485 _FDT(i2c_offset); 486 487 _FDT(fdt_setprop(fdt, i2c_offset, "reg", reg, sizeof(reg))); 488 489 _FDT((fdt_setprop_cell(fdt, i2c_offset, "#address-cells", 1))); 490 _FDT((fdt_setprop_cell(fdt, i2c_offset, "#size-cells", 0))); 491 _FDT(fdt_setprop(fdt, i2c_offset, "compatible", i2c_compat, 492 sizeof(i2c_compat))); 493 _FDT((fdt_setprop_cell(fdt, i2c_offset, "chip-engine#", i2c->engine))); 494 _FDT((fdt_setprop_cell(fdt, i2c_offset, "clock-frequency", 495 I2C_CLOCK_FREQUENCY))); 496 497 for (i = 0; i < i2c->num_busses; i++) { 498 pnv_i2c_bus_dt_xscom(i2c, fdt, i2c_offset, i); 499 } 500 return 0; 501 } 502 503 static void pnv_i2c_sys_reset(void *dev) 504 { 505 int port; 506 PnvI2C *i2c = PNV_I2C(dev); 507 508 pnv_i2c_reset(dev); 509 510 /* reset all buses connected to this i2c controller */ 511 for (port = 0; port < i2c->num_busses; port++) { 512 bus_cold_reset(BUS(i2c->busses[port])); 513 } 514 } 515 516 static void pnv_i2c_realize(DeviceState *dev, Error **errp) 517 { 518 PnvI2C *i2c = PNV_I2C(dev); 519 int i; 520 521 assert(i2c->chip); 522 523 if (i2c->num_busses > PNV_I2C_MAX_BUSSES) { 524 error_setg(errp, "Invalid number of busses: %u", i2c->num_busses); 525 return; 526 } 527 528 pnv_xscom_region_init(&i2c->xscom_regs, OBJECT(i2c), &pnv_i2c_xscom_ops, 529 i2c, "xscom-i2c", PNV9_XSCOM_I2CM_SIZE); 530 531 i2c->busses = g_new(I2CBus *, i2c->num_busses); 532 for (i = 0; i < i2c->num_busses; i++) { 533 char name[32]; 534 535 snprintf(name, sizeof(name), TYPE_PNV_I2C ".%d", i); 536 i2c->busses[i] = i2c_init_bus(dev, name); 537 } 538 539 fifo8_create(&i2c->fifo, PNV_I2C_FIFO_SIZE); 540 541 qemu_register_reset(pnv_i2c_sys_reset, dev); 542 543 qdev_init_gpio_out(DEVICE(dev), &i2c->psi_irq, 1); 544 } 545 546 static Property pnv_i2c_properties[] = { 547 DEFINE_PROP_LINK("chip", PnvI2C, chip, TYPE_PNV_CHIP, PnvChip *), 548 DEFINE_PROP_UINT32("engine", PnvI2C, engine, 1), 549 DEFINE_PROP_UINT32("num-busses", PnvI2C, num_busses, 1), 550 DEFINE_PROP_END_OF_LIST(), 551 }; 552 553 static void pnv_i2c_class_init(ObjectClass *klass, void *data) 554 { 555 DeviceClass *dc = DEVICE_CLASS(klass); 556 PnvXScomInterfaceClass *xscomc = PNV_XSCOM_INTERFACE_CLASS(klass); 557 558 xscomc->dt_xscom = pnv_i2c_dt_xscom; 559 560 dc->desc = "PowerNV I2C"; 561 dc->realize = pnv_i2c_realize; 562 device_class_set_props(dc, pnv_i2c_properties); 563 } 564 565 static const TypeInfo pnv_i2c_info = { 566 .name = TYPE_PNV_I2C, 567 .parent = TYPE_DEVICE, 568 .instance_size = sizeof(PnvI2C), 569 .class_init = pnv_i2c_class_init, 570 .interfaces = (InterfaceInfo[]) { 571 { TYPE_PNV_XSCOM_INTERFACE }, 572 { } 573 } 574 }; 575 576 static void pnv_i2c_register_types(void) 577 { 578 type_register_static(&pnv_i2c_info); 579 } 580 581 type_init(pnv_i2c_register_types); 582