/* Wait for BUSY being cleared and either INTR or an error flag being set */ staticint i801_wait_intr(struct i801_priv *priv)
{ unsignedlong timeout = jiffies + priv->adapter.timeout; int status, busy;
do {
usleep_range(250, 500);
status = ioread8(SMBHSTSTS(priv));
busy = status & SMBHSTSTS_HOST_BUSY;
status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; if (!busy && status) return status & STATUS_ERROR_FLAGS;
} while (time_is_after_eq_jiffies(timeout));
return -ETIMEDOUT;
}
/* Wait for either BYTE_DONE or an error flag being set */ staticint i801_wait_byte_done(struct i801_priv *priv)
{ unsignedlong timeout = jiffies + priv->adapter.timeout; int status;
do {
usleep_range(250, 500);
status = ioread8(SMBHSTSTS(priv)); if (status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) return status & STATUS_ERROR_FLAGS;
} while (time_is_after_eq_jiffies(timeout));
return -ETIMEDOUT;
}
staticint i801_get_block_len(struct i801_priv *priv)
{
u8 len = ioread8(SMBHSTDAT0(priv));
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
pci_err(priv->pci_dev, "Illegal SMBus block read size %u\n", len); return -EPROTO;
}
if (!(priv->features & FEATURE_SMBUS_PEC)) return 0;
status = ioread8(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE; if (status) {
iowrite8(status, SMBAUXSTS(priv)); return -EBADMSG;
}
return 0;
}
/* Make sure the SMBus host is ready to start transmitting.
Return 0 if it is, -EBUSY if it is not. */ staticint i801_check_pre(struct i801_priv *priv)
{ int status, result;
status = ioread8(SMBHSTSTS(priv)); if (status & SMBHSTSTS_HOST_BUSY) {
pci_err(priv->pci_dev, "SMBus is busy, can't use it!\n"); return -EBUSY;
}
status &= STATUS_FLAGS; if (status) {
pci_dbg(priv->pci_dev, "Clearing status flags (%02x)\n", status);
iowrite8(status, SMBHSTSTS(priv));
}
/* * Clear CRC status if needed. * During normal operation, i801_check_post() takes care * of it after every operation. We do it here only in case * the hardware was already in this state when the driver * started.
*/
result = i801_check_and_clear_pec_error(priv); if (result)
pci_dbg(priv->pci_dev, "Clearing aux status flag CRCE\n");
return 0;
}
staticint i801_check_post(struct i801_priv *priv, int status)
{ int result = 0;
/* * If the SMBus is still busy, we give up
*/ if (unlikely(status < 0)) { /* try to stop the current command */
iowrite8(SMBHSTCNT_KILL, SMBHSTCNT(priv));
status = i801_wait_intr(priv);
iowrite8(0, SMBHSTCNT(priv));
/* Check if it worked */ if (status < 0 || !(status & SMBHSTSTS_FAILED))
pci_dbg(priv->pci_dev, "Failed terminating the transaction\n"); return -ETIMEDOUT;
}
if (status & SMBHSTSTS_FAILED) {
result = -EIO;
pci_err(priv->pci_dev, "Transaction failed\n");
} if (status & SMBHSTSTS_DEV_ERR) { /* * This may be a PEC error, check and clear it. * * AUXSTS is handled differently from HSTSTS. * For HSTSTS, i801_isr() or i801_wait_intr() * has already cleared the error bits in hardware, * and we are passed a copy of the original value * in "status". * For AUXSTS, the hardware register is left * for us to handle here. * This is asymmetric, slightly iffy, but safe, * since all this code is serialized and the CRCE * bit is harmless as long as it's cleared before * the next operation.
*/
result = i801_check_and_clear_pec_error(priv); if (result) {
pci_dbg(priv->pci_dev, "PEC error\n");
} else {
result = -ENXIO;
pci_dbg(priv->pci_dev, "No response\n");
}
} if (status & SMBHSTSTS_BUS_ERR) {
result = -EAGAIN;
pci_dbg(priv->pci_dev, "Lost arbitration\n");
}
staticint i801_block_transaction_by_block(struct i801_priv *priv, union i2c_smbus_data *data, char read_write, int command)
{ int len, status, xact;
switch (command) { case I2C_SMBUS_BLOCK_PROC_CALL:
xact = I801_BLOCK_PROC_CALL; break; case I2C_SMBUS_BLOCK_DATA:
xact = I801_BLOCK_DATA; break; default: return -EOPNOTSUPP;
}
/* Set block buffer mode */
iowrite8(ioread8(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0];
iowrite8(len, SMBHSTDAT0(priv));
ioread8(SMBHSTCNT(priv)); /* reset the data buffer index */
iowrite8_rep(SMBBLKDAT(priv), data->block + 1, len);
}
status = i801_transaction(priv, xact); if (status) goto out;
if (read_write == I2C_SMBUS_READ ||
command == I2C_SMBUS_BLOCK_PROC_CALL) {
len = i801_get_block_len(priv); if (len < 0) {
status = len; goto out;
}
data->block[0] = len;
ioread8(SMBHSTCNT(priv)); /* reset the data buffer index */
ioread8_rep(SMBBLKDAT(priv), data->block + 1, len);
}
out:
iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_E32B, SMBAUXCTL(priv)); return status;
}
staticvoid i801_isr_byte_done(struct i801_priv *priv)
{ if (priv->is_read) { /* * At transfer start i801_smbus_block_transaction() marks * the block length as invalid. Check for this sentinel value * and read the block length from SMBHSTDAT0.
*/ if (priv->len == SMBUS_LEN_SENTINEL) {
priv->len = i801_get_block_len(priv); if (priv->len < 0) /* FIXME: Recover */
priv->len = I2C_SMBUS_BLOCK_MAX;
priv->data[-1] = priv->len;
}
/* Read next byte */ if (priv->count < priv->len)
priv->data[priv->count++] = ioread8(SMBBLKDAT(priv)); else
pci_dbg(priv->pci_dev, "Discarding extra byte on block read\n");
/* Set LAST_BYTE for last byte of read transaction */ if (priv->count == priv->len - 1)
iowrite8(priv->cmd | SMBHSTCNT_LAST_BYTE,
SMBHSTCNT(priv));
} elseif (priv->count < priv->len - 1) { /* Write next byte, except for IRQ after last byte */
iowrite8(priv->data[++priv->count], SMBBLKDAT(priv));
}
}
/* * With the tested platforms, reading SMBNTFDDAT (22 + (p)->smba) * always returns 0. Our current implementation doesn't provide * data, so we just ignore it.
*/
i2c_handle_smbus_host_notify(&priv->adapter, addr);
/* clear Host Notify bit and return */
iowrite8(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); return IRQ_HANDLED;
}
/* * There are three kinds of interrupts: * * 1) i801 signals transaction completion with one of these interrupts: * INTR - Success * DEV_ERR - Invalid command, NAK or communication timeout * BUS_ERR - SMI# transaction collision * FAILED - transaction was canceled due to a KILL request * When any of these occur, update ->status and signal completion. * * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt * occurs for each byte of a byte-by-byte to prepare the next byte. * * 3) Host Notify interrupts
*/ static irqreturn_t i801_isr(int irq, void *dev_id)
{ struct i801_priv *priv = dev_id;
u16 pcists;
u8 status;
/* Confirm this is our interrupt */
pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); if (!(pcists & PCI_STATUS_INTERRUPT)) return IRQ_NONE;
if (priv->features & FEATURE_HOST_NOTIFY) {
status = ioread8(SMBSLVSTS(priv)); if (status & SMBSLVSTS_HST_NTFY_STS) return i801_host_notify_isr(priv);
}
status = ioread8(SMBHSTSTS(priv)); if ((status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS)) == SMBHSTSTS_BYTE_DONE)
i801_isr_byte_done(priv);
/* * Clear IRQ sources: SMB_ALERT status is set after signal assertion * independently of the interrupt generation being blocked or not * so clear it always when the status is set.
*/
status &= STATUS_FLAGS | SMBHSTSTS_SMBALERT_STS;
iowrite8(status, SMBHSTSTS(priv));
status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; if (status) {
priv->status = status & STATUS_ERROR_FLAGS;
complete(&priv->done);
}
return IRQ_HANDLED;
}
/* * For "byte-by-byte" block transactions: * I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1 * I2C read uses cmd=I801_I2C_BLOCK_DATA
*/ staticint i801_block_transaction_byte_by_byte(struct i801_priv *priv, union i2c_smbus_data *data, char read_write, int command)
{ int i, len; int smbcmd; int status; unsignedlong result; conststruct i2c_adapter *adap = &priv->adapter;
if (command == I2C_SMBUS_BLOCK_PROC_CALL) return -EOPNOTSUPP;
len = data->block[0];
if (read_write == I2C_SMBUS_WRITE) {
iowrite8(len, SMBHSTDAT0(priv));
iowrite8(data->block[1], SMBBLKDAT(priv));
}
for (i = 1; i <= len; i++) {
status = i801_wait_byte_done(priv); if (status) return status;
/* * At transfer start i801_smbus_block_transaction() marks * the block length as invalid. Check for this sentinel value * and read the block length from SMBHSTDAT0.
*/ if (len == SMBUS_LEN_SENTINEL) {
len = i801_get_block_len(priv); if (len < 0) { /* Recover */ while (ioread8(SMBHSTSTS(priv)) &
SMBHSTSTS_HOST_BUSY)
iowrite8(SMBHSTSTS_BYTE_DONE,
SMBHSTSTS(priv));
iowrite8(SMBHSTSTS_INTR, SMBHSTSTS(priv)); return -EPROTO;
}
data->block[0] = len;
}
if (read_write == I2C_SMBUS_READ) {
data->block[i] = ioread8(SMBBLKDAT(priv)); if (i == len - 1)
iowrite8(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv));
}
if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
iowrite8(data->block[i+1], SMBBLKDAT(priv));
/* Single value transaction function */ staticint i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
u8 addr, u8 hstcmd, char read_write, int command)
{ int xact, ret;
staticint i801_i2c_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
u8 addr, u8 hstcmd, char read_write, int command)
{ int result;
u8 hostc;
if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) return -EPROTO; /* * NB: page 240 of ICH5 datasheet shows that the R/#W bit should be cleared here, * even when reading. However if SPD Write Disable is set (Lynx Point and later), * the read will fail if we don't set the R/#W bit.
*/
i801_set_hstadd(priv, addr,
priv->original_hstcfg & SMBHSTCFG_SPD_WD ? read_write : I2C_SMBUS_WRITE);
/* NB: page 240 of ICH5 datasheet shows that DATA1 is the cmd field when reading */ if (read_write == I2C_SMBUS_READ)
iowrite8(hstcmd, SMBHSTDAT1(priv)); else
iowrite8(hstcmd, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE) { /* set I2C_EN bit in configuration register */
pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN);
} elseif (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
pci_err(priv->pci_dev, "I2C block read is unsupported!\n"); return -EOPNOTSUPP;
}
/* Block buffer isn't supported for I2C block transactions */
result = i801_block_transaction_byte_by_byte(priv, data, read_write, command);
/* restore saved configuration register value */ if (read_write == I2C_SMBUS_WRITE)
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
return result;
}
/* Return negative errno on error. */ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsignedshort flags, char read_write, u8 command, int size, union i2c_smbus_data *data)
{ int hwpec, ret; struct i801_priv *priv = i2c_get_adapdata(adap);
if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_BLOCK_PROC_CALL)
ret = i801_smbus_block_transaction(priv, data, addr, command, read_write, size); elseif (size == I2C_SMBUS_I2C_BLOCK_DATA)
ret = i801_i2c_block_transaction(priv, data, addr, command, read_write, size); else
ret = i801_simple_transaction(priv, data, addr, command, read_write, size);
ret = i801_check_post(priv, ret);
/* Some BIOSes don't like it when PEC is enabled at reboot or resume * time, so we forcibly disable it after every transaction.
*/ if (hwpec)
iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv));
out: /* * Unlock the SMBus device for use by BIOS/ACPI, * and clear status flags if not done already.
*/
iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));
if (!(priv->features & FEATURE_HOST_NOTIFY)) return;
/* * Enable host notify interrupt and block the generation of interrupt * from the SMB_ALERT signal because the driver does not support * SMBus Alert.
*/
iowrite8(SMBSLVCMD_HST_NTFY_INTREN | SMBSLVCMD_SMBALERT_DISABLE |
priv->original_slvcmd, SMBSLVCMD(priv));
/* clear Host Notify bit to allow a new notification */
iowrite8(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv));
}
staticvoid i801_disable_host_notify(struct i801_priv *priv)
{ if (!(priv->features & FEATURE_HOST_NOTIFY)) return;
#ifdefined CONFIG_X86 && defined CONFIG_DMI staticunsignedchar apanel_addr __ro_after_init;
/* Scan the system ROM for the signature "FJKEYINF" */ static __init constvoid __iomem *bios_signature(constvoid __iomem *bios)
{
ssize_t offset; constunsignedchar signature[] = "FJKEYINF";
for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) { /* & ~0x80, ignore enabled/disabled bit */ if ((type & ~0x80) != dmi_devices[i].type) continue; if (strcasecmp(name, dmi_devices[i].name)) continue;
/* We use our own function to check for onboard devices instead of dmi_find_device() as some buggy BIOS's have the devices we are interested
in marked as disabled */ staticvoid dmi_check_onboard_devices(conststruct dmi_header *dm, void *adap)
{ int i, count;
if (dm->type != DMI_ENTRY_ONBOARD_DEVICE) return;
count = (dm->length - sizeof(struct dmi_header)) / 2; for (i = 0; i < count; i++) { const u8 *d = (char *)(dm + 1) + (i * 2); constchar *name = ((char *) dm) + dm->length;
u8 type = d[0];
u8 s = d[1];
if (!s) continue;
s--; while (s > 0 && name[0]) {
name += strlen(name) + 1;
s--;
} if (name[0] == 0) /* Bogus string reference */ continue;
dmi_check_onboard_device(type, name, adap);
}
}
/* Register optional targets */ staticvoid i801_probe_optional_targets(struct i801_priv *priv)
{ /* Only register targets on main SMBus channel */ if (priv->features & FEATURE_IDF) return;
if (apanel_addr) { struct i2c_board_info info = {
.addr = apanel_addr,
.type = "fujitsu_apanel",
};
i2c_new_client_device(&priv->adapter, &info);
}
if (dmi_name_in_vendors("FUJITSU"))
dmi_walk(dmi_check_onboard_devices, &priv->adapter);
/* Instantiate SPD EEPROMs unless the SMBus is multiplexed */ #ifdef CONFIG_I2C_I801_MUX if (!priv->mux_pdev) #endif
i2c_register_spd_write_enable(&priv->adapter);
} #else staticvoid __init input_apanel_init(void) {} staticvoid i801_probe_optional_targets(struct i801_priv *priv) {} #endif/* CONFIG_X86 && CONFIG_DMI */
/* Register GPIO descriptor lookup table */
lookup = devm_kzalloc(dev,
struct_size(lookup, table, mux_config->n_gpios + 1),
GFP_KERNEL); if (!lookup) return;
lookup->dev_id = "i2c-mux-gpio"; for (i = 0; i < mux_config->n_gpios; i++)
lookup->table[i] = GPIO_LOOKUP(mux_config->gpio_chip,
mux_config->gpios[i], "mux", 0);
gpiod_add_lookup_table(lookup);
priv->mux_notifier_block.notifier_call = i801_notifier_call; if (bus_register_notifier(&i2c_bus_type, &priv->mux_notifier_block)) return; /* * Register the mux device, we use PLATFORM_DEVID_NONE here * because since we are referring to the GPIO chip by name we are * anyways in deep trouble if there is more than one of these * devices, and there should likely only be one platform controller * hub.
*/
priv->mux_pdev = platform_device_register_data(dev, "i2c-mux-gpio",
PLATFORM_DEVID_NONE, &gpio_data, sizeof(struct i2c_mux_gpio_platform_data)); if (IS_ERR(priv->mux_pdev)) {
gpiod_remove_lookup_table(lookup);
devm_kfree(dev, lookup);
dev_err(dev, "Failed to register i2c-mux-gpio device\n");
} else {
priv->lookup = lookup;
}
}
memset(tco_res, 0, sizeof(tco_res)); /* * Always populate the main iTCO IO resource here. The second entry * for NO_REBOOT MMIO is filled by the SPT specific function.
*/
res = &tco_res[0];
res->start = tco_base & ~1;
res->end = res->start + 32 - 1;
res->flags = IORESOURCE_IO;
/* * Once BIOS AML code touches the OpRegion we warn and inhibit any * further access from the driver itself. This device is now owned * by the system firmware.
*/
i2c_lock_bus(&priv->adapter, I2C_LOCK_SEGMENT);
if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) {
priv->acpi_reserved = true;
/* Disable features on user request */ for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { if (priv->features & disable_features & (1 << i))
pci_notice(dev, "%s disabled by user\n", i801_feature_names[i]);
}
priv->features &= ~disable_features;
/* The block process call uses block buffer mode */ if (!(priv->features & FEATURE_BLOCK_BUFFER))
priv->features &= ~FEATURE_BLOCK_PROC;
/* * Do not call pcim_enable_device(), because the device has to remain * enabled on driver detach. See i801_remove() for the reasoning.
*/
err = pci_enable_device(dev); if (err) {
pci_err(dev, "Failed to enable SMBus PCI device (%d)\n", err); return err;
}
/* Determine the address of the SMBus area */ if (!pci_resource_start(dev, SMBBAR)) {
pci_err(dev, "SMBus base address uninitialized, upgrade BIOS\n"); return -ENODEV;
}
if (i801_acpi_probe(priv)) return -ENODEV;
if (pci_resource_flags(dev, SMBBAR_MMIO) & IORESOURCE_MEM)
bar = SMBBAR_MMIO;
priv->smba = pcim_iomap_region(dev, bar, DRV_NAME); if (IS_ERR(priv->smba)) {
pci_err(dev, "Failed to request SMBus region %pr\n",
pci_resource_n(dev, bar));
i801_acpi_remove(priv); return PTR_ERR(priv->smba);
}
if (priv->original_hstcfg & SMBHSTCFG_SMB_SMI_EN) {
pci_dbg(dev, "SMBus using interrupt SMI#\n"); /* Disable SMBus interrupt feature if SMBus using SMI# */
priv->features &= ~FEATURE_IRQ;
} if (priv->original_hstcfg & SMBHSTCFG_SPD_WD)
pci_info(dev, "SPD Write Disable is set\n");
/* Clear special mode bits */ if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
iowrite8(ioread8(SMBAUXCTL(priv)) &
~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
/* Default timeout in interrupt mode: 200 ms */
priv->adapter.timeout = HZ / 5;
if (dev->irq == IRQ_NOTCONNECTED)
priv->features &= ~FEATURE_IRQ;
if (priv->features & FEATURE_IRQ) {
u16 pcists;
/* Complain if an interrupt is already pending */
pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); if (pcists & PCI_STATUS_INTERRUPT)
pci_warn(dev, "An interrupt is pending!\n");
}
if (priv->features & FEATURE_IRQ) {
init_completion(&priv->done);
/* Host notification uses an interrupt */ if (!(priv->features & FEATURE_IRQ))
priv->features &= ~FEATURE_HOST_NOTIFY;
/* Remember original Interrupt and Host Notify settings */
priv->original_hstcnt = ioread8(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL; if (priv->features & FEATURE_HOST_NOTIFY)
priv->original_slvcmd = ioread8(SMBSLVCMD(priv));
i801_add_tco(priv);
/* * adapter.name is used by platform code to find the main I801 adapter * to instantiante i2c_clients, do not change.
*/
snprintf(priv->adapter.name, sizeof(priv->adapter.name), "SMBus %s adapter at %s",
(priv->features & FEATURE_IDF) ? "I801 IDF" : "I801",
pci_name(dev));
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.