diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-ismt.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-ismt.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index 2f95e25a10f7..7aaefb21416a 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -53,7 +53,7 @@ * Features supported by this driver: * Hardware PEC yes * Block buffer yes - * Block process call transaction no + * Block process call transaction yes * Slave mode no */ @@ -77,10 +77,12 @@ #define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a #define PCI_DEVICE_ID_INTEL_CDF_SMT 0x18ac #define PCI_DEVICE_ID_INTEL_DNV_SMT 0x19ac +#define PCI_DEVICE_ID_INTEL_EBG_SMT 0x1bff #define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15 #define ISMT_DESC_ENTRIES 2 /* number of descriptor entries */ #define ISMT_MAX_RETRIES 3 /* number of SMBus retries to attempt */ +#define ISMT_LOG_ENTRIES 3 /* number of interrupt cause log entries */ /* Hardware Descriptor Constants - Control Field */ #define ISMT_DESC_CWRL 0x01 /* Command/Write Length */ @@ -144,8 +146,8 @@ #define ISMT_SPGT_SPD_MASK 0xc0000000 /* SMBus Speed mask */ #define ISMT_SPGT_SPD_80K 0x00 /* 80 kHz */ #define ISMT_SPGT_SPD_100K (0x1 << 30) /* 100 kHz */ -#define ISMT_SPGT_SPD_400K (0x2 << 30) /* 400 kHz */ -#define ISMT_SPGT_SPD_1M (0x3 << 30) /* 1 MHz */ +#define ISMT_SPGT_SPD_400K (0x2U << 30) /* 400 kHz */ +#define ISMT_SPGT_SPD_1M (0x3U << 30) /* 1 MHz */ /* MSI Control Register (MSICTL) bit definitions */ @@ -174,16 +176,16 @@ struct ismt_priv { u8 head; /* ring buffer head pointer */ struct completion cmp; /* interrupt completion */ u8 buffer[I2C_SMBUS_BLOCK_MAX + 16]; /* temp R/W data buffer */ + dma_addr_t log_dma; + u32 *log; }; -/** - * ismt_ids - PCI device IDs supported by this driver - */ static const struct pci_device_id ismt_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMT) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EBG_SMT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) }, { 0, } }; @@ -197,6 +199,8 @@ MODULE_PARM_DESC(bus_speed, "Bus Speed in kHz (0 = BIOS default)"); /** * __ismt_desc_dump() - dump the contents of a specific descriptor + * @dev: the iSMT device + * @desc: the iSMT hardware descriptor */ static void __ismt_desc_dump(struct device *dev, const struct ismt_desc *desc) { @@ -331,7 +335,8 @@ static int ismt_process_desc(const struct ismt_desc *desc, if (desc->status & ISMT_DESC_SCS) { if (read_write == I2C_SMBUS_WRITE && - size != I2C_SMBUS_PROC_CALL) + size != I2C_SMBUS_PROC_CALL && + size != I2C_SMBUS_BLOCK_PROC_CALL) return 0; switch (size) { @@ -344,6 +349,7 @@ static int ismt_process_desc(const struct ismt_desc *desc, data->word = dma_buffer[0] | (dma_buffer[1] << 8); break; case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_BLOCK_PROC_CALL: if (desc->rxbytes != dma_buffer[0] + 1) return -EMSGSIZE; @@ -376,6 +382,15 @@ static int ismt_process_desc(const struct ismt_desc *desc, } /** + * ismt_kill_transaction() - kill current transaction + * @priv: iSMT private data + */ +static void ismt_kill_transaction(struct ismt_priv *priv) +{ + writel(ISMT_GCTRL_KILL, priv->smba + ISMT_GR_GCTRL); +} + +/** * ismt_access() - process an SMBus command * @adap: the i2c host adapter * @addr: address of the i2c/SMBus target @@ -408,6 +423,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, memset(desc, 0, sizeof(struct ismt_desc)); desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write); + /* Always clear the log entries */ + memset(priv->log, 0, ISMT_LOG_ENTRIES * sizeof(u32)); + /* Initialize common control bits */ if (likely(pci_dev_msi_enabled(priv->pci_dev))) desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR; @@ -500,6 +518,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, if (read_write == I2C_SMBUS_WRITE) { /* Block Write */ dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: WRITE\n"); + if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) + return -EINVAL; + dma_size = data->block[0] + 1; dma_direction = DMA_TO_DEVICE; desc->wr_len_cmd = dma_size; @@ -517,6 +538,21 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, } break; + case I2C_SMBUS_BLOCK_PROC_CALL: + dev_dbg(dev, "I2C_SMBUS_BLOCK_PROC_CALL\n"); + if (data->block[0] > I2C_SMBUS_BLOCK_MAX) + return -EINVAL; + + dma_size = I2C_SMBUS_BLOCK_MAX; + desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 1); + desc->wr_len_cmd = data->block[0] + 1; + desc->rd_len = dma_size; + desc->control |= ISMT_DESC_BLK; + dma_direction = DMA_BIDIRECTIONAL; + dma_buffer[0] = command; + memcpy(&dma_buffer[1], &data->block[1], data->block[0]); + break; + case I2C_SMBUS_I2C_BLOCK_DATA: /* Make sure the length is valid */ if (data->block[0] < 1) @@ -596,7 +632,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, dma_unmap_single(dev, dma_addr, dma_size, dma_direction); if (unlikely(!time_left)) { - dev_err(dev, "completion wait timed out\n"); + ismt_kill_transaction(priv); ret = -ETIMEDOUT; goto out; } @@ -623,16 +659,12 @@ static u32 ismt_func(struct i2c_adapter *adap) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL | + I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC; } -/** - * smbus_algorithm - the adapter algorithm and supported functionality - * @smbus_xfer: the adapter algorithm - * @functionality: functionality supported by the adapter - */ static const struct i2c_algorithm smbus_algorithm = { .smbus_xfer = ismt_access, .functionality = ismt_func, @@ -697,6 +729,8 @@ static void ismt_hw_init(struct ismt_priv *priv) /* initialize the Master Descriptor Base Address (MDBA) */ writeq(priv->io_rng_dma, priv->smba + ISMT_MSTR_MDBA); + writeq(priv->log_dma, priv->smba + ISMT_GR_SMTICL); + /* initialize the Master Control Register (MCTRL) */ writel(ISMT_MCTRL_MEIE, priv->smba + ISMT_MSTR_MCTRL); @@ -784,6 +818,12 @@ static int ismt_dev_init(struct ismt_priv *priv) priv->head = 0; init_completion(&priv->cmp); + priv->log = dmam_alloc_coherent(&priv->pci_dev->dev, + ISMT_LOG_ENTRIES * sizeof(u32), + &priv->log_dma, GFP_KERNEL); + if (!priv->log) + return -ENOMEM; + return 0; } @@ -893,7 +933,7 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) return err; } - err = pci_request_region(pdev, SMBBAR, ismt_driver.name); + err = pcim_request_region(pdev, SMBBAR, ismt_driver.name); if (err) { dev_err(&pdev->dev, "Failed to request SMBus region 0x%lx-0x%lx\n", @@ -907,15 +947,10 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENODEV; } - if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) || - (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)) { - if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || - (pci_set_consistent_dma_mask(pdev, - DMA_BIT_MASK(32)) != 0)) { - dev_err(&pdev->dev, "pci_set_dma_mask fail %p\n", - pdev); - return -ENODEV; - } + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (err) { + dev_err(&pdev->dev, "dma_set_mask fail\n"); + return -ENODEV; } err = ismt_dev_init(priv); |
