/* * Copyright (c) 2013 Andrew Lutomirski <[hidden email]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ //#include #include #include #include #include #include /* * The datasheet can be found here, for example: * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e5-1600-2600-vol-2-datasheet.pdf * * There seem to be quite a few bugs or spec errors, though: * * - A successful transaction sets WOD and RDO. * * - The docs for TSOD_POLL_EN make no sense (see imc_channel_claim). * * - Erratum BT109, which says: * * The processor may not complete SMBus (System Management Bus) * transactions targeting the TSOD (Temperature Sensor On DIMM) * when Package C-States are enabled. Due to this erratum, if the * processor transitions into a Package C-State while an SMBus * transaction with the TSOD is in process, the processor will * suspend receipt of the transaction. The transaction completes * while the processor is in a Package C-State. Upon exiting * Package C-State, the processor will attempt to resume the * SMBus transaction, detect a protocol violation, and log an * error. * * The description notwithstanding, I've seen difficult-to-reproduce * issues when the system goes completely idle (so package C-states can * be entered) while software-initiated SMBUS transactions are in * progress. */ /* Register offsets (in PCI configuration space) */ #define SMB_CMD_CFG(i) (0x9C + 0x04*i) #define SMB_STATUS_CFG(i) (0xA8 + 0x04*i) #define SMB_DATA_CFG(i) (0xB4 + 0x04*i) #define SMB_TSOD_POLL_RATE_CNTR(i) (0xC0 + 0x04*i) #define SMB_TSOD_POLL_RATE(i) (0x84 + 0x04*i) /* SMBSTAT fields */ #define SMBSTAT_RDO (1U << 2) /* Read Data Valid */ #define SMBSTAT_WOD (1U << 3) /* Write Operation Done */ #define SMBSTAT_SBE (1U << 1) /* SMBus Error */ #define SMBSTAT_SMB_BUSY (1U << 0) /* SMBus Busy State */ /* 26:24 is the last automatically polled TSOD address */ #define SMBDATA_RDATA_MASK 0xffff /* result of a read */ /* SMBCMD fields */ #define SMBCMD_CKOVRD (1U << 29) /* # Clock Override */ #define SMBCMD_TRIGGER (1U << 19) /* CMD Trigger */ #define SMBCMD_PNTR_SEL (1U << 18) /* HW polls TSOD with pointer */ #define SMBCMD_WORD_ACCESS (1U << 17) /* word (vs byte) access */ #define SMBCMD_TYPE_MASK (3U << 27) /* Mask for access type */ #define SMBCMD_TYPE_READ (0U << 15) /* Read */ #define SMBCMD_TYPE_WRITE (1U << 15) /* Write */ #define SMBCMD_WRT_MASK 0x00018000 #define SMBCMD_TYPE_PNTR_WRITE (3U << 27) /* Write to pointer */ #define SMBCMD_SA_MASK (7U << 8) /* Slave Address high bits */ #define SMBCMD_SA_SHIFT 8 #define SMBCMD_BA_MASK 0x0000ff /* Bus Txn address */ #define SMBCMD_BA_SHIFT 0 #define SMBCMD_WDATA_MASK 0xffff /* data to write */ #define SMBCMD_DTI_MASK 0x00007800 /* Slave Address low bits */ #define SMBCMD_DTI_SHIFT 11 /* Slave Address low bits */ #define SMBCMD_DIS_WRT (1U << 28) /* Disable Write (sadly) */ #define SMBCMD_SOFT_RST (1U << 24) /* Soft Reset */ #define SMBCMD_TSOD_POLL_EN (1U << 20) /* TSOD Polling Enable */ /* Bits 0-3 and 4-6 indicate TSOD presence in various slots */ /* Bits that might randomly change if we race with something. */ #define SMBCMD_OUR_BITS (~(u32)SMBCMD_TRIGGER) #define SMBCNTL_OUR_BITS (SMBCMD_DTI_MASK | SMBCMD_TSOD_POLL_EN) /* System Address Controller, PCI dev 13 fn 6, 8086.3cf5 */ #define SAD_CONTROL 0xf4 #define PCI_DEVICE_ID_INTEL_SBRIDGE_BR 0x3cf5 /* 13.6 */ #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA 0x3ca8 /* 15.0 */ #define PCI_DEVICE_ID_INTEL_HASWELL_BR 0x2ffc #define PCI_DEVICE_ID_INTEL_HASWELL_IMC0_TA 0x2fa8 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC1_TA 0x2f68 #define PCI_DEVICE_ID_INTEL_BROADWELL_BR 0x6fa0 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC0_TA 0x6fa8 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC1_TA 0x6f68 #define PCI_DEVICE_ID_INTEL_SKYLAKE_BR 0x2055 #define PCI_DEVICE_ID_INTEL_SKYLAKE_IMC0_TA 0x2085 s32 config_page(struct i2c_adapter *adap,u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); s32 imc_smbus_xfer_normal(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); void i2c_scan_dimm_bus(struct i2c_adapter *adapter); static atomic_t imc_raced; /* Set permanently to 1 if we screw up. */ struct imc_channel { struct i2c_adapter adapter; struct mutex mutex; bool can_write, suspended; bool prev_tsod_poll; }; struct imc_priv { struct pci_dev *pci_dev; struct imc_channel channels[2]; }; static bool probe_addr(struct i2c_adapter *adapter, int addr) { /* * So far, all known devices that live on DIMMs can be safely * and reliably detected by trying to read a byte at address * zero. (The exception is the SPD write protection control, * which can't be probed and requires special hardware and/or * quick writes to access, and has no driver.) */ union i2c_smbus_data dummy; return i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE_DATA, &dummy) >= 0; } /** * i2c_scan_dimm_bus() - Scans an SMBUS segment known to contain DIMMs * @adapter: The SMBUS adapter to scan * * This function tells the DIMM-bus code that the adapter is known to * contain DIMMs. i2c_scan_dimm_bus will probe for devices known to * live on DIMMs. * * Do NOT call this function on general-purpose system SMBUS segments * unless you know that the only things on the bus are DIMMs. * Otherwise is it very likely to mis-identify other things on the * bus. * * Callers are advised not to set adapter->class = I2C_CLASS_SPD. */ void i2c_scan_dimm_bus(struct i2c_adapter *adapter) { struct i2c_board_info info = { }; int slot; /* * We probe with "read byte data". If any DIMM SMBUS driver can't * support that access type, this function should be updated. */ if (WARN_ON(!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA))) return; /* * Addresses on DIMMs use the three low bits to identify the slot * and the four high bits to identify the device type. Known * devices are: * * - 0x50 - 0x57: SPD (Serial Presence Detect) EEPROM * - 0x30 - 0x37: SPD WP control -- not worth trying to probe * - 0x18 - 0x1f: TSOD (Temperature Sensor on DIMM) * * There may be more some day. */ for (slot = 0; slot < 8; slot++) { /* If there's no SPD, then assume there's no DIMM here. */ if (!probe_addr(adapter, 0x50 | slot)) continue; strcpy(info.type, "spd"); info.addr = 0x50 | slot; i2c_new_device(adapter, &info); //printk(KERN_ALERT "====>slot:0x%x fuction:%s: line:%d\n",slot,__FUNCTION__,__LINE__); #if 0 if (probe_addr(adapter, 0x18 | slot)) { /* This is a temperature sensor. */ strcpy(info.type, "jc42"); info.addr = 0x18 | slot; i2c_new_device(adapter, &info); } #endif } } static int imc_wait_not_busy(struct imc_priv *priv, int chan, u32 * stat) { /* * The clock is around 100kHz, and transactions are nine cycles * per byte plus a few start/stop cycles, plus whatever clock * streching is involved. This means that polling every 70us * or so will give decent performance. * * Ideally we would calculate a good estimate for the * transaction time and sleep, but busy-waiting is an effective * workaround for an apparent Sandy Bridge bug that causes bogus * output if the system enters a package C-state. (NB: these * states are systemwide -- we don't need be running on the * right package for this to work.) */ int i; for (i = 0; i < 50; i++) { pci_read_config_dword(priv->pci_dev, SMB_STATUS_CFG(chan), stat); if (!(*stat & SMBSTAT_SMB_BUSY)) return 0; udelay(70); } return -ETIMEDOUT; } static void imc_channel_release(struct imc_priv *priv, int chan) { /* Return to HW control. */ if (priv->channels[chan].prev_tsod_poll) { u32 cntl; pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &cntl); cntl |= SMBCMD_TSOD_POLL_EN; pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), cntl); } } static int imc_channel_claim(struct imc_priv *priv, int chan) { /* * The docs are a bit confused here. We're supposed to disable TSOD * polling, then wait for busy to be cleared, then set * SMBCMD_TSOD_POLL_EN to zero to switch to software control. But * SMBCMD_TSOD_POLL_EN is the only documented way to turn off polling. */ u32 cntl, stat; if (priv->channels[chan].suspended) return -EIO; pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &cntl); priv->channels[chan].prev_tsod_poll = ! !(cntl & SMBCMD_TSOD_POLL_EN); cntl &= ~SMBCMD_TSOD_POLL_EN; pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), cntl); /* Sometimes the hardware won't let go. */ pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &cntl); if (cntl & SMBCMD_TSOD_POLL_EN) return -EBUSY; if (imc_wait_not_busy(priv, chan, &stat) != 0) { imc_channel_release(priv, chan); return -EBUSY; } return 0; /* The channel is ours. */ } static bool imc_channel_can_claim(struct imc_priv *priv, int chan) { u32 orig_cntl, cntl; dev_warn(&priv->pci_dev->dev, "Don't check TSOD_POLL_EN\n"); //Don't check TSOD_POLL_EN just return true return true; /* See if we can turn off TSOD_POLL_EN. */ pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &orig_cntl); pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), orig_cntl & ~SMBCMD_TSOD_POLL_EN); pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &cntl); if (cntl & SMBCMD_TSOD_POLL_EN) return false; /* Failed. */ pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), orig_cntl); return true; } /* * The iMC supports five access types. The terminology is rather * inconsistent. These are the types: * * "Write to pointer register SMBus": I2C_SMBUS_WRITE, I2C_SMBUS_BYTE * * Read byte/word: I2C_SMBUS_READ, I2C_SMBUS_{BYTE|WORD}_DATA * * Write byte/word: I2C_SMBUS_WRITE, I2C_SMBUS_{BYTE|WORD}_DATA * * The pointer write operations is AFAICT completely useless for * software control, for two reasons. First, HW periodically polls any * TSODs on the bus, so it will corrupt the pointer in between SW * transactions. More importantly, the matching "read byte"/"receive * byte" (the address-less single-byte read) is not available for SW * control. Therefore, this driver doesn't implement pointer writes * * There is no PEC support. */ static u32 imc_func(struct i2c_adapter *adapter) { int chan; struct imc_channel *ch; struct imc_priv *priv = i2c_get_adapdata(adapter); chan = (adapter == &priv->channels[0].adapter ? 0 : 1); ch = &priv->channels[chan]; if (ch->can_write) return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA; else return I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA; } static s32 imc_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { int ret = 0; #define CONFIG_PAGE_1 0x57 #define CONFIG_PAGE_0 0x56 /*config raed page 1 */ if( addr == CONFIG_PAGE_1 || addr == CONFIG_PAGE_0) { data->byte = 0; read_write = I2C_SMBUS_WRITE; command = 0; ret = config_page(adap,addr,flags,read_write,command,size,data); if(ret < 0 ) { printk("config page error\n"); return -EOPNOTSUPP; /* No large address support */ } } else { ret = imc_smbus_xfer_normal(adap,addr,flags,read_write,command,size,data); if(ret < 0 ) { printk("normal operaton error\n"); return -EOPNOTSUPP; /* No large address support */ } } return ret; } s32 imc_smbus_xfer_normal(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { int ret, chan; u32 cmd = 0, /*cntl = 0,*/ final_cmd, final_cntl, stat, final_data; struct imc_channel *ch; struct imc_priv *priv = i2c_get_adapdata(adap); if (atomic_read(&imc_raced)) return -EIO; /* Minimize damage. */ chan = (adap == &priv->channels[0].adapter ? 0 : 1); ch = &priv->channels[chan]; if (addr > 0x7f) return -EOPNOTSUPP; /* No large address support */ if (flags) return -EOPNOTSUPP; /* No PEC */ if (size != I2C_SMBUS_BYTE_DATA && size != I2C_SMBUS_WORD_DATA) return -EOPNOTSUPP; //Read the orignal SMB_CMD_CFG register content pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &cmd); //Clear some register bit cmd &= ~SMBCMD_SA_MASK; cmd &= ~SMBCMD_BA_MASK; cmd &= ~SMBCMD_TSOD_POLL_EN; cmd &= ~SMBCMD_WORD_ACCESS; cmd &= ~SMBCMD_WRT_MASK; /* Encode CMD part of addresses and access size */ cmd |= ((u32) addr & 0x7) << SMBCMD_SA_SHIFT; cmd |= ((u32) command) << SMBCMD_BA_SHIFT; if (size == I2C_SMBUS_WORD_DATA) cmd |= SMBCMD_WORD_ACCESS; /* Encode read/write and data to write */ if (read_write == I2C_SMBUS_READ) { cmd |= SMBCMD_TYPE_READ; } else { cmd |= SMBCMD_TYPE_WRITE; if (size == I2C_SMBUS_WORD_DATA) pci_write_config_dword(priv->pci_dev, SMB_DATA_CFG(chan), data->word << 16); else pci_write_config_dword(priv->pci_dev, SMB_DATA_CFG(chan), data->byte << 16); } mutex_lock(&ch->mutex); ret = imc_channel_claim(priv, chan); if (ret) goto out_unlock; cmd &= ~SMBCMD_DTI_MASK; cmd |= ((u32) addr >> 3) << SMBCMD_DTI_SHIFT; /* * This clears SMBCMD_PNTR_SEL. We leave it cleared so that we don't * need to think about keeping the TSOD pointer state consistent with * the hardware's expectation. This probably has some miniscule * power cost, as TSOD polls will take 9 extra cycles. */ cmd |= SMBCMD_TRIGGER; pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), cmd); if (imc_wait_not_busy(priv, chan, &stat) != 0) { /* Timeout. TODO: Reset the controller? */ ret = -EIO; printk(KERN_ALERT "fuction:%s: line:%d\n",__FUNCTION__,__LINE__); dev_err(&priv->pci_dev->dev, "controller is wedged\n"); goto out_release; } /* * Be paranoid: try to detect races. This will only detect races * against BIOS, not against hardware. (I've never seen this happen.) */ pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &final_cmd); pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &final_cntl); if (((cmd ^ final_cmd) & SMBCMD_OUR_BITS) || ((cmd ^ final_cntl) & SMBCNTL_OUR_BITS)) { printk("iMC SMBUS raced against firmware"); //dev_emerg(&priv->pci_dev->dev, // "Access to channel %d raced: cmd 0x%08X->0x%08X, cntl 0x%08X->0x%08X\n", // chan, cmd, final_cmd, cntl, final_cntl); //atomic_set(&imc_raced, 1); ret = -EIO; goto out_release; } if (stat & SMBSTAT_SBE) { /* * Clear the error to re-enable TSOD polling. The docs say * that, as long as SBE is set, TSOD polling won't happen. * The docs also say that writing zero to this bit (which is * the only writable bit in the whole register) will clear * the error. Empirically, writing 0 does not clear SBE, but * it's probably still good to do the write in compliance with * the spec. (TSOD polling still happens and seems to * clear SBE on its own.) */ //pci_write_config_dword(priv->pci_dev, SMB_STATUS_CFG(chan), 0); //ret = -ENXIO; //goto out_release; //Clear the SBE error pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &cmd); cmd |= SMBCMD_SOFT_RST; cmd &= ~SMBCMD_CKOVRD; pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), cmd); mdelay(40); cmd &= ~SMBCMD_SOFT_RST; cmd |= SMBCMD_CKOVRD; pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), cmd); } if (read_write == I2C_SMBUS_READ) { if (stat & SMBSTAT_RDO) { /* * The iMC SMBUS controller thinks of SMBUS * words as being big-endian (MSB first). * Linux treats them as little-endian, so we need * to swap them. * * Note: the controller will often (always?) set * WOD here. This is probably a bug. */ pci_read_config_dword(priv->pci_dev, SMB_DATA_CFG(chan), &final_data); if (size == I2C_SMBUS_WORD_DATA) data->word = final_data & 0x0000FFFF; else data->byte = final_data & 0x000000FF; ret = 0; } else { dev_err(&priv->pci_dev->dev, "Unexpected read status 0x%08X\n", stat); ret = -EIO; } } else { if (stat & SMBSTAT_WOD) { /* Same bug (?) as in the read case. */ ret = 0; } else { dev_err(&priv->pci_dev->dev, "Unexpected write status 0x%08X\n", stat); ret = -EIO; } } out_release: imc_channel_release(priv, chan); out_unlock: mutex_unlock(&ch->mutex); return ret; } s32 config_page(struct i2c_adapter *adap,u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { int ret, chan; u32 cmd = 0, stat, final_data; struct imc_channel *ch; struct imc_priv *priv = i2c_get_adapdata(adap); if (atomic_read(&imc_raced)) return -EIO; /* Minimize damage. */ chan = (adap == &priv->channels[0].adapter ? 0 : 1); ch = &priv->channels[chan]; if (addr > 0x7f) return -EOPNOTSUPP; /* No large address support */ if (flags) return -EOPNOTSUPP; /* No PEC */ if (size != I2C_SMBUS_BYTE_DATA && size != I2C_SMBUS_WORD_DATA) return -EOPNOTSUPP; if(addr == 0x57 ) { /* config page 1 */ addr = 0x07; } if(addr == 0x56) { /* config page 0 */ addr = 0x06; } //Read the orignal SMB_CMD_CFG register content pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), &cmd); //Clear some register bit cmd &= ~SMBCMD_SA_MASK; cmd &= ~SMBCMD_BA_MASK; cmd &= ~SMBCMD_TSOD_POLL_EN; cmd &= ~SMBCMD_WORD_ACCESS; cmd &= ~SMBCMD_WRT_MASK; /* Encode CMD part of addresses and access size */ cmd |= ((u32) addr & 0x7) << SMBCMD_SA_SHIFT; cmd |= ((u32) command) << SMBCMD_BA_SHIFT; if (size == I2C_SMBUS_WORD_DATA) cmd |= SMBCMD_WORD_ACCESS; /* Encode read/write and data to write */ if (read_write == I2C_SMBUS_READ) { cmd |= SMBCMD_TYPE_READ; } else { cmd |= SMBCMD_TYPE_WRITE; cmd |= (size == I2C_SMBUS_WORD_DATA ? swab16(data->word) : data->byte); } mutex_lock(&ch->mutex); ret = imc_channel_claim(priv, chan); if (ret) goto out_unlock; cmd &= ~SMBCMD_DTI_MASK; cmd |= ((u32) 0x06) << SMBCMD_DTI_SHIFT; /* * This clears SMBCMD_PNTR_SEL. We leave it cleared so that we don't * need to think about keeping the TSOD pointer state consistent with * the hardware's expectation. This probably has some miniscule * power cost, as TSOD polls will take 9 extra cycles. */ cmd |= SMBCMD_TRIGGER; pci_write_config_dword(priv->pci_dev, SMB_CMD_CFG(chan), cmd); if (imc_wait_not_busy(priv, chan, &stat) != 0) { /* Timeout. TODO: Reset the controller? */ ret = -EIO; dev_err(&priv->pci_dev->dev, "controller is wedged\n"); goto out_release; } if (read_write == I2C_SMBUS_READ) { if (stat & SMBSTAT_RDO) { /* * The iMC SMBUS controller thinks of SMBUS * words as being big-endian (MSB first). * Linux treats them as little-endian, so we need * to swap them. * * Note: the controller will often (always?) set * WOD here. This is probably a bug. */ pci_read_config_dword(priv->pci_dev, SMB_DATA_CFG(chan), &final_data); if (size == I2C_SMBUS_WORD_DATA) data->word = final_data & 0x0000FFFF; else data->byte = final_data & 0x000000FF; ret = 0; } else { dev_err(&priv->pci_dev->dev, "Unexpected read status 0x%08X\n", stat); ret = -EIO; } } else { if (stat & SMBSTAT_WOD) { /* Same bug (?) as in the read case. */ ret = 0; } else { dev_err(&priv->pci_dev->dev, "Unexpected write status 0x%08X\n", stat); ret = -EIO; } } out_release: imc_channel_release(priv, chan); out_unlock: mutex_unlock(&ch->mutex); return ret; } static const struct i2c_algorithm imc_smbus_algorithm = { .smbus_xfer = imc_smbus_xfer, .functionality = imc_func, }; static int imc_init_channel(struct imc_priv *priv, int i, int socket) { int err; u32 val; struct imc_channel *ch = &priv->channels[i]; //printk(KERN_ALERT "====>channels:0x%x fuction:%s: line:%d\n",i,__FUNCTION__,__LINE__); /* * With CLTT enabled, the hardware won't let us turn * off TSOD polling. The device is completely useless * when this happens (at least without help from Intel), * but we can at least minimize confusion. */ if (!imc_channel_can_claim(priv, i)) { dev_warn(&priv->pci_dev->dev, "iMC channel %d: we cannot control the HW. Is CLTT on?\n", i); return -EBUSY; } i2c_set_adapdata(&ch->adapter, priv); ch->adapter.owner = THIS_MODULE; ch->adapter.algo = &imc_smbus_algorithm; ch->adapter.dev.parent = &priv->pci_dev->dev; pci_read_config_dword(priv->pci_dev, SMB_CMD_CFG(i), &val); ch->can_write = !(val & SMBCMD_DIS_WRT); /* * i2c_add_addapter can call imc_smbus_xfer, so we need to be * ready immediately. */ mutex_init(&ch->mutex); snprintf(ch->adapter.name, sizeof(ch->adapter.name), "iMC socket %d IMC%d (Bus: %x)", socket, i, priv->pci_dev->bus->number); err = i2c_add_adapter(&ch->adapter); if (err) { mutex_destroy(&ch->mutex); return err; } //i2c_scan_dimm_bus(&ch->adapter); return 0; } static void imc_free_channel(struct imc_priv *priv, int i) { struct imc_channel *ch = &priv->channels[i]; /* This can recurse into imc_smbus_xfer. */ i2c_del_adapter(&ch->adapter); mutex_destroy(&ch->mutex); } static struct pci_dev *imc_get_related_device(struct pci_bus *bus, unsigned int devfn, u16 devid) { struct pci_dev *ret = pci_get_slot(bus, devfn); if (!ret) return NULL; if (ret->vendor != PCI_VENDOR_ID_INTEL || ret->device != devid) { pci_dev_put(ret); return NULL; } return ret; } static int imc_probe(struct pci_dev *dev, const struct pci_device_id *id) { int i, err; struct imc_priv *priv; struct pci_dev *sad; /* System Address Decoder */ u32 sad_control = 0; printk("Intel CPU SMBus driver initializing\n"); /* Paranoia: the datasheet says this is always at 15.0 */ if (dev->devfn != PCI_DEVFN(30, 5)) { printk(KERN_ALERT "para1: 0x%x\n",dev->devfn); return -ENODEV; } /* * The socket number is hidden away on a different PCI device. * There's another copy at devfn 11.0 offset 0x40, and an even * less convincing copy at 5.0 0x140. The actual APICID register * is "not used ... and is still implemented in hardware because * of FUD". * * In principle we could double-check that the socket matches * the numa_node from SRAT, but this is probably not worth it. */ //sad = imc_get_related_device(dev->bus, PCI_DEVFN(13, 6), // PCI_DEVICE_ID_INTEL_SBRIDGE_BR); // // printk(KERN_ALERT "Vendor:0x%x Devid:0x%x\n",dev->vendor,dev->device); sad = imc_get_related_device(dev->bus, PCI_DEVFN(29, 1), PCI_DEVICE_ID_INTEL_SKYLAKE_BR); if (!sad){ printk(KERN_ALERT "fuction:%s: line:%d\n",__FUNCTION__,__LINE__); return -ENODEV; } pci_read_config_dword(sad, SAD_CONTROL, &sad_control); pci_dev_put(sad); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->pci_dev = dev; pci_set_drvdata(dev, priv); for (i = 0; i < 2; i++) { int j; err = imc_init_channel(priv, i, sad_control & 0x7); if (err) { for (j = 0; j < i; j++) imc_free_channel(priv, j); goto exit_free; } } return 0; exit_free: kfree(priv); return err; } static void imc_remove(struct pci_dev *dev) { int i; struct imc_priv *priv = pci_get_drvdata(dev); for (i = 0; i < 2; i++) imc_free_channel(priv, i); kfree(priv); } static int imc_suspend(struct pci_dev *dev, pm_message_t mesg) { int i; struct imc_priv *priv = pci_get_drvdata(dev); /* BIOS is in charge. We should finish any pending transaction */ for (i = 0; i < 2; i++) { mutex_lock(&priv->channels[i].mutex); priv->channels[i].suspended = true; mutex_unlock(&priv->channels[i].mutex); } return 0; } static int imc_resume(struct pci_dev *dev) { int i; struct imc_priv *priv = pci_get_drvdata(dev); for (i = 0; i < 2; i++) { mutex_lock(&priv->channels[i].mutex); priv->channels[i].suspended = false; mutex_unlock(&priv->channels[i].mutex); } return 0; } static const struct pci_device_id imc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC0_TA) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC1_TA) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC0_TA) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC1_TA) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKYLAKE_IMC0_TA) }, { 0,} }; MODULE_DEVICE_TABLE(pci, imc_ids); static struct pci_driver imc_pci_driver = { .name = "imc_smbus", .id_table = imc_ids, .probe = imc_probe, .remove = imc_remove, .suspend = imc_suspend, .resume = imc_resume, }; static int __init pci_imc_init(void) { //printk(KERN_ALERT "fuction:%s: line:%d\n",__FUNCTION__,__LINE__); return pci_register_driver(&imc_pci_driver); } static void __exit pci_imc_exit(void) { //printk(KERN_ALERT "fuction:%s: line:%d\n",__FUNCTION__,__LINE__); return pci_unregister_driver(&imc_pci_driver); } module_init(pci_imc_init); module_exit(pci_imc_exit); //module_pci_driver(imc_pci_driver); MODULE_AUTHOR("Andrew Lutomirski <[hidden email]>"); MODULE_LICENSE("GPL");