staticint gpu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{ struct gpu_i2c_dev *i2cd = i2c_get_adapdata(adap); int status, status2; bool send_stop = true; int i, j;
/* * The controller supports maximum 4 byte read due to known * limitation of sending STOP after every read.
*/
pm_runtime_get_sync(i2cd->dev); for (i = 0; i < num; i++) { if (msgs[i].flags & I2C_M_RD) { /* program client address before starting read */
writel(msgs[i].addr, i2cd->regs + I2C_MST_ADDR); /* gpu_i2c_read has implicit start */
status = gpu_i2c_read(i2cd, msgs[i].buf, msgs[i].len); if (status < 0) gotoexit;
} else {
u8 addr = i2c_8bit_addr_from_msg(msgs + i);
status = gpu_i2c_start(i2cd); if (status < 0) { if (i == 0)
send_stop = false; gotoexit;
}
status = gpu_i2c_write(i2cd, addr); if (status < 0) gotoexit;
for (j = 0; j < msgs[i].len; j++) {
status = gpu_i2c_write(i2cd, msgs[i].buf[j]); if (status < 0) gotoexit;
}
}
}
send_stop = false;
status = gpu_i2c_stop(i2cd); if (status < 0) gotoexit;
status = i; exit: if (send_stop) {
status2 = gpu_i2c_stop(i2cd); if (status2 < 0)
dev_err(i2cd->dev, "i2c stop failed %d\n", status2);
}
pm_runtime_mark_last_busy(i2cd->dev);
pm_runtime_put_autosuspend(i2cd->dev); return status;
}
/* * This driver is for Nvidia GPU cards with USB Type-C interface. * We want to identify the cards using vendor ID and class code only * to avoid dependency of adding product id for any new card which * requires this driver. * Currently there is no class code defined for UCSI device over PCI * so using UNKNOWN class for now and it will be updated when UCSI * over PCI gets a class code. * There is no other NVIDIA cards with UNKNOWN class code. Even if the * driver gets loaded for an undesired card then eventually i2c_read() * (initiated from UCSI i2c_client) will timeout or UCSI commands will * timeout.
*/ #define PCI_CLASS_SERIAL_UNKNOWN 0x0c80 staticconststruct pci_device_id gpu_i2c_ids[] = {
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_SERIAL_UNKNOWN << 8, 0xffffff00},
{ }
};
MODULE_DEVICE_TABLE(pci, gpu_i2c_ids);
staticconststruct property_entry ccgx_props[] = { /* Use FW built for NVIDIA GPU only */
PROPERTY_ENTRY_STRING("firmware-name", "nvidia,gpu"), /* USB-C doesn't power the system */
PROPERTY_ENTRY_U8("scope", POWER_SUPPLY_SCOPE_DEVICE),
{ }
};
gpu_enable_i2c_bus(i2cd); /* * Runtime resume ccgx client so that it can see for any * connector change event. Old ccg firmware has known * issue of not triggering interrupt when a device is * connected to runtime resume the controller.
*/
pm_request_resume(&i2cd->ccgx_client->dev); return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.