diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-01 18:29:36 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-01 18:29:36 -0800 |
commit | 3265568db8c37d391ee8ad2afa8b0fd7257f4526 (patch) | |
tree | 70723d4c0eed9b76f64090dfc1652289e6eb9b36 /drivers/i2c | |
parent | 31764f1b6d93e126ed341fb600d2765d630e8bf6 (diff) | |
parent | a72e27f7a47069b1b4942051bffa7dc77b4aee0c (diff) | |
download | linux-3265568db8c37d391ee8ad2afa8b0fd7257f4526.tar.bz2 |
Merge branch 'i2c/for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"I2C has mostly driver updates this time.
The few noteworthy changes are: the core has now support for analog
and digital filters with at91 being the first user, a core addition to
replace the NULL returning i2c_new_probed_device() with an ERR_PTR
variant, and the pxa driver has finally being moved to use the generic
I2C slave interface. We have quite a significant number of reviews per
patch this time, so thank you to all involved!"
* 'i2c/for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (37 commits)
video: fbdev: matrox: convert to i2c_new_scanned_device
i2c: icy: convert to i2c_new_scanned_device
i2c: replace i2c_new_probed_device with an ERR_PTR variant
i2c: Fix Kconfig indentation
i2c: smbus: Don't filter out duplicate alerts
i2c: i801: Correct Intel Jasper Lake SOC naming
i2c: i2c-stm32f7: fix 10-bits check in slave free id search loop
i2c: iproc: Add i2c repeated start capability
i2c: remove helpers for ref-counting clients
i2c: tegra: Use dma_request_chan() directly for channel request
i2c: sh_mobile: Use dma_request_chan() directly for channel request
i2c: qup: Use dma_request_chan() directly for channel request
i2c: at91: Use dma_request_chan() directly for channel request
i2c: rcar: Remove superfluous call to clk_get_rate()
i2c: pxa: remove unused i2c-slave APIs
i2c: pxa: migrate to new i2c_slave APIs
i2c: cros-ec-tunnel: Make the device acpi compatible
i2c: stm32f7: report dma error during probe
i2c: icy: no need to populate address for scanned device
i2c: xiic: Fix kerneldoc warnings
...
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 24 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-aspeed.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-at91-core.c | 38 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-at91-master.c | 53 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-at91.h | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-bcm-iproc.c | 63 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-cros-ec-tunnel.c | 15 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-icy.c | 9 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 75 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-qup.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stm32.c | 16 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stm32f7.c | 32 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-xiic.c | 2 | ||||
-rw-r--r-- | drivers/i2c/i2c-core-base.c | 63 | ||||
-rw-r--r-- | drivers/i2c/i2c-smbus.c | 7 | ||||
-rw-r--r-- | drivers/i2c/muxes/Kconfig | 18 |
20 files changed, 321 insertions, 131 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 146ce40d8e0a..6a0aa76859f3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -145,6 +145,7 @@ config I2C_I801 Comet Lake (PCH) Elkhart Lake (PCH) Tiger Lake (PCH) + Jasper Lake (SOC) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -292,7 +293,7 @@ config I2C_VIA select I2C_ALGOBIT help If you say yes to this option, support will be included for the VIA - 82C586B I2C interface + 82C586B I2C interface This driver can also be built as a module. If so, the module will be called i2c-via. @@ -677,11 +678,11 @@ config I2C_IMX_LPI2C tristate "IMX Low Power I2C interface" depends on ARCH_MXC || COMPILE_TEST help - Say Y here if you want to use the Low Power IIC bus controller - on the Freescale i.MX processors. + Say Y here if you want to use the Low Power IIC bus controller + on the Freescale i.MX processors. - This driver can also be built as a module. If so, the module - will be called i2c-imx-lpi2c. + This driver can also be built as a module. If so, the module + will be called i2c-imx-lpi2c. config I2C_IOP3XX tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" @@ -874,6 +875,7 @@ config I2C_PXA_PCI config I2C_PXA_SLAVE bool "Intel PXA2XX I2C Slave comms support" depends on I2C_PXA && !X86_32 + select I2C_SLAVE help Support I2C slave mode communications on the PXA I2C bus. This is necessary for systems where the PXA may be a target on the @@ -1182,9 +1184,9 @@ config I2C_DIOLAN_U2C will be called i2c-diolan-u2c. config I2C_DLN2 - tristate "Diolan DLN-2 USB I2C adapter" - depends on MFD_DLN2 - help + tristate "Diolan DLN-2 USB I2C adapter" + depends on MFD_DLN2 + help If you say yes to this option, support will be included for Diolan DLN2, a USB to I2C interface. @@ -1283,9 +1285,9 @@ config I2C_VIPERBOARD help Say yes here to access the I2C part of the Nano River Technologies Viperboard as I2C master. - See viperboard API specification and Nano - River Tech's viperboard.h for detailed meaning - of the module parameters. + See viperboard API specification and Nano + River Tech's viperboard.h for detailed meaning + of the module parameters. comment "Other I2C/SMBus bus drivers" diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 7b098ff5f5dd..a7be6f24450b 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -952,6 +952,10 @@ static const struct of_device_id aspeed_i2c_bus_of_table[] = { .compatible = "aspeed,ast2500-i2c-bus", .data = aspeed_i2c_25xx_get_clk_reg_val, }, + { + .compatible = "aspeed,ast2600-i2c-bus", + .data = aspeed_i2c_25xx_get_clk_reg_val, + }, { }, }; MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table); diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c index 435c7d7377a3..e13af4874976 100644 --- a/drivers/i2c/busses/i2c-at91-core.c +++ b/drivers/i2c/busses/i2c-at91-core.c @@ -68,6 +68,9 @@ static struct at91_twi_pdata at91rm9200_config = { .has_unre_flag = true, .has_alt_cmd = false, .has_hold_field = false, + .has_dig_filtr = false, + .has_adv_dig_filtr = false, + .has_ana_filtr = false, }; static struct at91_twi_pdata at91sam9261_config = { @@ -76,6 +79,9 @@ static struct at91_twi_pdata at91sam9261_config = { .has_unre_flag = false, .has_alt_cmd = false, .has_hold_field = false, + .has_dig_filtr = false, + .has_adv_dig_filtr = false, + .has_ana_filtr = false, }; static struct at91_twi_pdata at91sam9260_config = { @@ -84,6 +90,9 @@ static struct at91_twi_pdata at91sam9260_config = { .has_unre_flag = false, .has_alt_cmd = false, .has_hold_field = false, + .has_dig_filtr = false, + .has_adv_dig_filtr = false, + .has_ana_filtr = false, }; static struct at91_twi_pdata at91sam9g20_config = { @@ -92,6 +101,9 @@ static struct at91_twi_pdata at91sam9g20_config = { .has_unre_flag = false, .has_alt_cmd = false, .has_hold_field = false, + .has_dig_filtr = false, + .has_adv_dig_filtr = false, + .has_ana_filtr = false, }; static struct at91_twi_pdata at91sam9g10_config = { @@ -100,6 +112,9 @@ static struct at91_twi_pdata at91sam9g10_config = { .has_unre_flag = false, .has_alt_cmd = false, .has_hold_field = false, + .has_dig_filtr = false, + .has_adv_dig_filtr = false, + .has_ana_filtr = false, }; static const struct platform_device_id at91_twi_devtypes[] = { @@ -130,6 +145,9 @@ static struct at91_twi_pdata at91sam9x5_config = { .has_unre_flag = false, .has_alt_cmd = false, .has_hold_field = false, + .has_dig_filtr = false, + .has_adv_dig_filtr = false, + .has_ana_filtr = false, }; static struct at91_twi_pdata sama5d4_config = { @@ -138,6 +156,9 @@ static struct at91_twi_pdata sama5d4_config = { .has_unre_flag = false, .has_alt_cmd = false, .has_hold_field = true, + .has_dig_filtr = true, + .has_adv_dig_filtr = false, + .has_ana_filtr = false, }; static struct at91_twi_pdata sama5d2_config = { @@ -146,6 +167,20 @@ static struct at91_twi_pdata sama5d2_config = { .has_unre_flag = true, .has_alt_cmd = true, .has_hold_field = true, + .has_dig_filtr = true, + .has_adv_dig_filtr = true, + .has_ana_filtr = true, +}; + +static struct at91_twi_pdata sam9x60_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = true, + .has_alt_cmd = true, + .has_hold_field = true, + .has_dig_filtr = true, + .has_adv_dig_filtr = true, + .has_ana_filtr = true, }; static const struct of_device_id atmel_twi_dt_ids[] = { @@ -174,6 +209,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = { .compatible = "atmel,sama5d2-i2c", .data = &sama5d2_config, }, { + .compatible = "microchip,sam9x60-i2c", + .data = &sam9x60_config, + }, { /* sentinel */ } }; diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index a3fcc35ffd3b..7a862e00b475 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -31,12 +31,32 @@ void at91_init_twi_bus_master(struct at91_twi_dev *dev) { + struct at91_twi_pdata *pdata = dev->pdata; + u32 filtr = 0; + /* FIFO should be enabled immediately after the software reset */ if (dev->fifo_size) at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_FIFOEN); at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN); at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS); at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg); + + /* enable digital filter */ + if (pdata->has_dig_filtr && dev->enable_dig_filt) + filtr |= AT91_TWI_FILTR_FILT; + + /* enable advanced digital filter */ + if (pdata->has_adv_dig_filtr && dev->enable_dig_filt) + filtr |= AT91_TWI_FILTR_FILT | + (AT91_TWI_FILTR_THRES(dev->filter_width) & + AT91_TWI_FILTR_THRES_MASK); + + /* enable analog filter */ + if (pdata->has_ana_filtr && dev->enable_ana_filt) + filtr |= AT91_TWI_FILTR_PADFEN; + + if (filtr) + at91_twi_write(dev, AT91_TWI_FILTR, filtr); } /* @@ -45,7 +65,7 @@ void at91_init_twi_bus_master(struct at91_twi_dev *dev) */ static void at91_calc_twi_clock(struct at91_twi_dev *dev) { - int ckdiv, cdiv, div, hold = 0; + int ckdiv, cdiv, div, hold = 0, filter_width = 0; struct at91_twi_pdata *pdata = dev->pdata; int offset = pdata->clk_offset; int max_ckdiv = pdata->clk_max_div; @@ -84,11 +104,29 @@ static void at91_calc_twi_clock(struct at91_twi_dev *dev) } } + if (pdata->has_adv_dig_filtr) { + /* + * filter width = 0 to AT91_TWI_FILTR_THRES_MAX + * peripheral clocks + */ + filter_width = DIV_ROUND_UP(t->digital_filter_width_ns + * (clk_get_rate(dev->clk) / 1000), 1000000); + if (filter_width > AT91_TWI_FILTR_THRES_MAX) { + dev_warn(dev->dev, + "Filter threshold set to its maximum value (%d instead of %d)\n", + AT91_TWI_FILTR_THRES_MAX, filter_width); + filter_width = AT91_TWI_FILTR_THRES_MAX; + } + } + dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv | AT91_TWI_CWGR_HOLD(hold); - dev_dbg(dev->dev, "cdiv %d ckdiv %d hold %d (%d ns)\n", - cdiv, ckdiv, hold, t->sda_hold_ns); + dev->filter_width = filter_width; + + dev_dbg(dev->dev, "cdiv %d ckdiv %d hold %d (%d ns), filter_width %d (%d ns)\n", + cdiv, ckdiv, hold, t->sda_hold_ns, filter_width, + t->digital_filter_width_ns); } static void at91_twi_dma_cleanup(struct at91_twi_dev *dev) @@ -720,14 +758,14 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr) slave_config.dst_maxburst = 1; slave_config.device_fc = false; - dma->chan_tx = dma_request_slave_channel_reason(dev->dev, "tx"); + dma->chan_tx = dma_request_chan(dev->dev, "tx"); if (IS_ERR(dma->chan_tx)) { ret = PTR_ERR(dma->chan_tx); dma->chan_tx = NULL; goto error; } - dma->chan_rx = dma_request_slave_channel_reason(dev->dev, "rx"); + dma->chan_rx = dma_request_chan(dev->dev, "rx"); if (IS_ERR(dma->chan_rx)) { ret = PTR_ERR(dma->chan_rx); dma->chan_rx = NULL; @@ -793,6 +831,11 @@ int at91_twi_probe_master(struct platform_device *pdev, dev_info(dev->dev, "Using FIFO (%u data)\n", dev->fifo_size); } + dev->enable_dig_filt = of_property_read_bool(pdev->dev.of_node, + "i2c-digital-filter"); + + dev->enable_ana_filt = of_property_read_bool(pdev->dev.of_node, + "i2c-analog-filter"); at91_calc_twi_clock(dev); dev->adapter.algo = &at91_twi_algorithm; diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h index 499b506f6128..977a67bc0f88 100644 --- a/drivers/i2c/busses/i2c-at91.h +++ b/drivers/i2c/busses/i2c-at91.h @@ -84,6 +84,13 @@ #define AT91_TWI_ACR_DATAL(len) ((len) & 0xff) #define AT91_TWI_ACR_DIR BIT(8) +#define AT91_TWI_FILTR 0x0044 +#define AT91_TWI_FILTR_FILT BIT(0) +#define AT91_TWI_FILTR_PADFEN BIT(1) +#define AT91_TWI_FILTR_THRES(v) ((v) << 8) +#define AT91_TWI_FILTR_THRES_MAX 7 +#define AT91_TWI_FILTR_THRES_MASK GENMASK(10, 8) + #define AT91_TWI_FMR 0x0050 /* FIFO Mode Register */ #define AT91_TWI_FMR_TXRDYM(mode) (((mode) & 0x3) << 0) #define AT91_TWI_FMR_TXRDYM_MASK (0x3 << 0) @@ -108,6 +115,9 @@ struct at91_twi_pdata { bool has_unre_flag; bool has_alt_cmd; bool has_hold_field; + bool has_dig_filtr; + bool has_adv_dig_filtr; + bool has_ana_filtr; struct at_dma_slave dma_slave; }; @@ -145,6 +155,9 @@ struct at91_twi_dev { unsigned smr; struct i2c_client *slave; #endif + bool enable_dig_filt; + bool enable_ana_filt; + u32 filter_width; }; unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg); diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 9ffdffaf6141..30efb7913b2e 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -81,6 +81,7 @@ #define M_CMD_PROTOCOL_MASK 0xf #define M_CMD_PROTOCOL_BLK_WR 0x7 #define M_CMD_PROTOCOL_BLK_RD 0x8 +#define M_CMD_PROTOCOL_PROCESS 0xa #define M_CMD_PEC_SHIFT 8 #define M_CMD_RD_CNT_SHIFT 0 #define M_CMD_RD_CNT_MASK 0xff @@ -675,13 +676,20 @@ static int bcm_iproc_i2c_xfer_wait(struct bcm_iproc_i2c_dev *iproc_i2c, return 0; } -static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, - struct i2c_msg *msg) +/* + * If 'process_call' is true, then this is a multi-msg transfer that requires + * a repeated start between the messages. + * More specifically, it must be a write (reg) followed by a read (data). + * The i2c quirks are set to enforce this rule. + */ +static int bcm_iproc_i2c_xfer_internal(struct bcm_iproc_i2c_dev *iproc_i2c, + struct i2c_msg *msgs, bool process_call) { int i; u8 addr; u32 val, tmp, val_intr_en; unsigned int tx_bytes; + struct i2c_msg *msg = &msgs[0]; /* check if bus is busy */ if (!!(iproc_i2c_rd_reg(iproc_i2c, @@ -707,14 +715,29 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, val = msg->buf[i]; /* mark the last byte */ - if (i == msg->len - 1) - val |= BIT(M_TX_WR_STATUS_SHIFT); + if (!process_call && (i == msg->len - 1)) + val |= 1 << M_TX_WR_STATUS_SHIFT; iproc_i2c_wr_reg(iproc_i2c, M_TX_OFFSET, val); } iproc_i2c->tx_bytes = tx_bytes; } + /* Process the read message if this is process call */ + if (process_call) { + msg++; + iproc_i2c->msg = msg; /* point to second msg */ + + /* + * The last byte to be sent out should be a slave + * address with read operation + */ + addr = i2c_8bit_addr_from_msg(msg); + /* mark it the last byte out */ + val = addr | (1 << M_TX_WR_STATUS_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, M_TX_OFFSET, val); + } + /* mark as incomplete before starting the transaction */ if (iproc_i2c->irq) reinit_completion(&iproc_i2c->done); @@ -733,7 +756,7 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, * underrun interrupt, which will be triggerred when the TX FIFO is * empty. When that happens we can then pump more data into the FIFO */ - if (!(msg->flags & I2C_M_RD) && + if (!process_call && !(msg->flags & I2C_M_RD) && msg->len > iproc_i2c->tx_bytes) val_intr_en |= BIT(IE_M_TX_UNDERRUN_SHIFT); @@ -743,6 +766,8 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, */ val = BIT(M_CMD_START_BUSY_SHIFT); if (msg->flags & I2C_M_RD) { + u32 protocol; + iproc_i2c->rx_bytes = 0; if (msg->len > M_RX_FIFO_MAX_THLD_VALUE) iproc_i2c->thld_bytes = M_RX_FIFO_THLD_VALUE; @@ -758,7 +783,10 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, /* enable the RX threshold interrupt */ val_intr_en |= BIT(IE_M_RX_THLD_SHIFT); - val |= (M_CMD_PROTOCOL_BLK_RD << M_CMD_PROTOCOL_SHIFT) | + protocol = process_call ? + M_CMD_PROTOCOL_PROCESS : M_CMD_PROTOCOL_BLK_RD; + + val |= (protocol << M_CMD_PROTOCOL_SHIFT) | (msg->len << M_CMD_RD_CNT_SHIFT); } else { val |= (M_CMD_PROTOCOL_BLK_WR << M_CMD_PROTOCOL_SHIFT); @@ -774,17 +802,24 @@ static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num) { struct bcm_iproc_i2c_dev *iproc_i2c = i2c_get_adapdata(adapter); - int ret, i; + bool process_call = false; + int ret; - /* go through all messages */ - for (i = 0; i < num; i++) { - ret = bcm_iproc_i2c_xfer_single_msg(iproc_i2c, &msgs[i]); - if (ret) { - dev_dbg(iproc_i2c->device, "xfer failed\n"); - return ret; + if (num == 2) { + /* Repeated start, use process call */ + process_call = true; + if (msgs[1].flags & I2C_M_NOSTART) { + dev_err(iproc_i2c->device, "Invalid repeated start\n"); + return -EOPNOTSUPP; } } + ret = bcm_iproc_i2c_xfer_internal(iproc_i2c, msgs, process_call); + if (ret) { + dev_dbg(iproc_i2c->device, "xfer failed\n"); + return ret; + } + return num; } @@ -809,6 +844,8 @@ static struct i2c_algorithm bcm_iproc_algo = { }; static const struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { + .flags = I2C_AQ_COMB_WRITE_THEN_READ, + .max_comb_1st_msg_len = M_TX_RX_FIFO_SIZE, .max_read_len = M_RX_MAX_READ_LEN, }; diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index c551aa96a2e3..958161c71985 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -3,6 +3,7 @@ // // Copyright (C) 2013 Google, Inc. +#include <linux/acpi.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/platform_data/cros_ec_commands.h> @@ -240,7 +241,6 @@ static const struct i2c_algorithm ec_i2c_algorithm = { static int ec_i2c_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); struct device *dev = &pdev->dev; struct ec_i2c_device *bus = NULL; @@ -256,7 +256,7 @@ static int ec_i2c_probe(struct platform_device *pdev) if (bus == NULL) return -ENOMEM; - err = of_property_read_u32(np, "google,remote-bus", &remote_bus); + err = device_property_read_u32(dev, "google,remote-bus", &remote_bus); if (err) { dev_err(dev, "Couldn't read remote-bus property\n"); return err; @@ -271,7 +271,7 @@ static int ec_i2c_probe(struct platform_device *pdev) bus->adap.algo = &ec_i2c_algorithm; bus->adap.algo_data = bus; bus->adap.dev.parent = &pdev->dev; - bus->adap.dev.of_node = np; + bus->adap.dev.of_node = pdev->dev.of_node; bus->adap.retries = I2C_MAX_RETRIES; err = i2c_add_adapter(&bus->adap); @@ -291,19 +291,24 @@ static int ec_i2c_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_OF static const struct of_device_id cros_ec_i2c_of_match[] = { { .compatible = "google,cros-ec-i2c-tunnel" }, {}, }; MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match); -#endif + +static const struct acpi_device_id cros_ec_i2c_tunnel_acpi_id[] = { + { "GOOG001A", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_tunnel_acpi_id); static struct platform_driver ec_i2c_tunnel_driver = { .probe = ec_i2c_probe, .remove = ec_i2c_remove, .driver = { .name = "cros-ec-i2c-tunnel", + .acpi_match_table = ACPI_PTR(cros_ec_i2c_tunnel_acpi_id), .of_match_table = of_match_ptr(cros_ec_i2c_of_match), }, }; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f1c714acc280..f5e69fe56532 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -64,8 +64,10 @@ * Cedar Fork (PCH) 0x18df 32 hard yes yes yes * Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes * Comet Lake (PCH) 0x02a3 32 hard yes yes yes + * Comet Lake-H (PCH) 0x06a3 32 hard yes yes yes * Elkhart Lake (PCH) 0x4b23 32 hard yes yes yes * Tiger Lake-LP (PCH) 0xa0a3 32 hard yes yes yes + * Jasper Lake (SOC) 0x4da3 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -205,6 +207,7 @@ /* Older devices have their ID defined in <linux/pci_ids.h> */ #define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3 +#define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS 0x06a3 #define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 #define PCI_DEVICE_ID_INTEL_CDF_SMBUS 0x18df #define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df @@ -223,6 +226,7 @@ #define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS 0x34a3 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 +#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2 @@ -1069,8 +1073,10 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) }, { 0, } }; @@ -1750,8 +1756,10 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) case PCI_DEVICE_ID_INTEL_CDF_SMBUS: case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS: + case PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS: case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS: case PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS: + case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS: priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_IRQ; diff --git a/drivers/i2c/busses/i2c-icy.c b/drivers/i2c/busses/i2c-icy.c index 8382eb64b424..271470f4d8a9 100644 --- a/drivers/i2c/busses/i2c-icy.c +++ b/drivers/i2c/busses/i2c-icy.c @@ -122,7 +122,6 @@ static int icy_probe(struct zorro_dev *z, struct fwnode_handle *new_fwnode; struct i2c_board_info ltc2990_info = { .type = "ltc2990", - .addr = 0x4c, }; i2c = devm_kzalloc(&z->dev, sizeof(*i2c), GFP_KERNEL); @@ -188,10 +187,10 @@ static int icy_probe(struct zorro_dev *z, ltc2990_info.fwnode = new_fwnode; i2c->ltc2990_client = - i2c_new_probed_device(&i2c->adapter, - <c2990_info, - icy_ltc2990_addresses, - NULL); + i2c_new_scanned_device(&i2c->adapter, + <c2990_info, + icy_ltc2990_addresses, + NULL); } return 0; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 2c3c3d6935c0..466e4f681d7a 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -25,7 +25,6 @@ #include <linux/delay.h> #include <linux/errno.h> #include <linux/interrupt.h> -#include <linux/i2c-pxa.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -180,7 +179,7 @@ struct pxa_i2c { struct i2c_adapter adap; struct clk *clk; #ifdef CONFIG_I2C_PXA_SLAVE - struct i2c_slave_client *slave; + struct i2c_client *slave; #endif unsigned int irqlogidx; @@ -544,22 +543,23 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) if (isr & ISR_BED) { /* what should we do here? */ } else { - int ret = 0; + u8 byte = 0; if (i2c->slave != NULL) - ret = i2c->slave->read(i2c->slave->data); + i2c_slave_event(i2c->slave, I2C_SLAVE_READ_PROCESSED, + &byte); - writel(ret, _IDBR(i2c)); + writel(byte, _IDBR(i2c)); writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); /* allow next byte */ } } static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) { - unsigned int byte = readl(_IDBR(i2c)); + u8 byte = readl(_IDBR(i2c)); if (i2c->slave != NULL) - i2c->slave->write(i2c->slave->data, byte); + i2c_slave_event(i2c->slave, I2C_SLAVE_WRITE_RECEIVED, &byte); writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); } @@ -572,9 +572,18 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) dev_dbg(&i2c->adap.dev, "SAD, mode is slave-%cx\n", (isr & ISR_RWM) ? 'r' : 't'); - if (i2c->slave != NULL) - i2c->slave->event(i2c->slave->data, - (isr & ISR_RWM) ? I2C_SLAVE_EVENT_START_READ : I2C_SLAVE_EVENT_START_WRITE); + if (i2c->slave != NULL) { + if (isr & ISR_RWM) { + u8 byte = 0; + + i2c_slave_event(i2c->slave, I2C_SLAVE_READ_REQUESTED, + &byte); + writel(byte, _IDBR(i2c)); + } else { + i2c_slave_event(i2c->slave, I2C_SLAVE_WRITE_REQUESTED, + NULL); + } + } /* * slave could interrupt in the middle of us generating a @@ -607,7 +616,7 @@ static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop)\n"); if (i2c->slave != NULL) - i2c->slave->event(i2c->slave->data, I2C_SLAVE_EVENT_STOP); + i2c_slave_event(i2c->slave, I2C_SLAVE_STOP, NULL); if (i2c_debug > 2) dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop) acked\n"); @@ -619,6 +628,38 @@ static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) if (i2c->msg) i2c_pxa_master_complete(i2c, I2C_RETRY); } + +static int i2c_pxa_slave_reg(struct i2c_client *slave) +{ + struct pxa_i2c *i2c = slave->adapter->algo_data; + + if (i2c->slave) + return -EBUSY; + + if (!i2c->reg_isar) + return -EAFNOSUPPORT; + + i2c->slave = slave; + i2c->slave_addr = slave->addr; + + writel(i2c->slave_addr, _ISAR(i2c)); + + return 0; +} + +static int i2c_pxa_slave_unreg(struct i2c_client *slave) +{ + struct pxa_i2c *i2c = slave->adapter->algo_data; + + WARN_ON(!i2c->slave); + + i2c->slave_addr = I2C_PXA_SLAVE_ADDR; + writel(i2c->slave_addr, _ISAR(i2c)); + + i2c->slave = NULL; + + return 0; +} #else static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) { @@ -1141,11 +1182,19 @@ static u32 i2c_pxa_functionality(struct i2c_adapter *adap) static const struct i2c_algorithm i2c_pxa_algorithm = { .master_xfer = i2c_pxa_xfer, .functionality = i2c_pxa_functionality, +#ifdef CONFIG_I2C_PXA_SLAVE + .reg_slave = i2c_pxa_slave_reg, + .unreg_slave = i2c_pxa_slave_unreg, +#endif }; static const struct i2c_algorithm i2c_pxa_pio_algorithm = { .master_xfer = i2c_pxa_pio_xfer, .functionality = i2c_pxa_functionality, +#ifdef CONFIG_I2C_PXA_SLAVE + .reg_slave = i2c_pxa_slave_reg, + .unreg_slave = i2c_pxa_slave_unreg, +#endif }; static const struct of_device_id i2c_pxa_dt_ids[] = { @@ -1270,10 +1319,6 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->highmode_enter = false; if (plat) { -#ifdef CONFIG_I2C_PXA_SLAVE - i2c->slave_addr = plat->slave_addr; - i2c->slave = plat->slave; -#endif i2c->adap.class = plat->class; } diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index e09cd0775ae9..2d7dabe12723 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -628,7 +628,7 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup) int err; if (!qup->btx.dma) { - qup->btx.dma = dma_request_slave_channel_reason(qup->dev, "tx"); + qup->btx.dma = dma_request_chan(qup->dev, "tx"); if (IS_ERR(qup->btx.dma)) { err = PTR_ERR(qup->btx.dma); qup->btx.dma = NULL; @@ -638,7 +638,7 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup) } if (!qup->brx.dma) { - qup->brx.dma = dma_request_slave_channel_reason(qup->dev, "rx"); + qup->brx.dma = dma_request_chan(qup->dev, "rx"); if (IS_ERR(qup->brx.dma)) { dev_err(qup->dev, "\n rx channel not available"); err = PTR_ERR(qup->brx.dma); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 531c01100b56..879f0e61a496 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -317,7 +317,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, struct i2c_timin scgd_find: dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n", - scl, t->bus_freq_hz, clk_get_rate(priv->clk), round, cdf, scgd); + scl, t->bus_freq_hz, rate, round, cdf, scgd); /* keep icccr value */ priv->icccr = scgd << cdf_width | cdf; diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 8777af4c695e..82b3b795e0bd 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -486,7 +486,7 @@ static struct dma_chan *sh_mobile_i2c_request_dma_chan(struct device *dev, char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx"; int ret; - chan = dma_request_slave_channel_reason(dev, chan_name); + chan = dma_request_chan(dev, chan_name); if (IS_ERR(chan)) { dev_dbg(dev, "request_channel failed for %s (%ld)\n", chan_name, PTR_ERR(chan)); diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c index 07d5dfce68d4..1da347e6a358 100644 --- a/drivers/i2c/busses/i2c-stm32.c +++ b/drivers/i2c/busses/i2c-stm32.c @@ -20,13 +20,13 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); if (!dma) - return NULL; + return ERR_PTR(-ENOMEM); /* Request and configure I2C TX dma channel */ - dma->chan_tx = dma_request_slave_channel(dev, "tx"); - if (!dma->chan_tx) { + dma->chan_tx = dma_request_chan(dev, "tx"); + if (IS_ERR(dma->chan_tx)) { dev_dbg(dev, "can't request DMA tx channel\n"); - ret = -EINVAL; + ret = PTR_ERR(dma->chan_tx); goto fail_al; } @@ -42,10 +42,10 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, } /* Request and configure I2C RX dma channel */ - dma->chan_rx = dma_request_slave_channel(dev, "rx"); - if (!dma->chan_rx) { + dma->chan_rx = dma_request_chan(dev, "rx"); + if (IS_ERR(dma->chan_rx)) { dev_err(dev, "can't request DMA rx channel\n"); - ret = -EINVAL; + ret = PTR_ERR(dma->chan_rx); goto fail_tx; } @@ -75,7 +75,7 @@ fail_al: devm_kfree(dev, dma); dev_info(dev, "can't use DMA\n"); - return NULL; + return ERR_PTR(ret); } void stm32_i2c_dma_free(struct stm32_i2c_dma *dma) diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index b24e7b937f21..b2634afe066d 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -1267,8 +1267,8 @@ static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev, * slave[0] supports 7-bit and 10-bit slave address * slave[1] supports 7-bit slave address only */ - for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) { - if (i == 1 && (slave->flags & I2C_CLIENT_PEC)) + for (i = STM32F7_I2C_MAX_SLAVE - 1; i >= 0; i--) { + if (i == 1 && (slave->flags & I2C_CLIENT_TEN)) continue; if (!i2c_dev->slave[i]) { *id = i; @@ -1955,6 +1955,15 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr, STM32F7_I2C_TXDR, STM32F7_I2C_RXDR); + if (PTR_ERR(i2c_dev->dma) == -ENODEV) + i2c_dev->dma = NULL; + else if (IS_ERR(i2c_dev->dma)) { + ret = PTR_ERR(i2c_dev->dma); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "Failed to request dma error %i\n", ret); + goto clk_free; + } platform_set_drvdata(pdev, i2c_dev); @@ -1985,6 +1994,11 @@ pm_disable: pm_runtime_set_suspended(i2c_dev->dev); pm_runtime_dont_use_autosuspend(i2c_dev->dev); + if (i2c_dev->dma) { + stm32_i2c_dma_free(i2c_dev->dma); + i2c_dev->dma = NULL; + } + clk_free: clk_disable_unprepare(i2c_dev->clk); @@ -1995,21 +2009,21 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) { struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - if (i2c_dev->dma) { - stm32_i2c_dma_free(i2c_dev->dma); - i2c_dev->dma = NULL; - } - i2c_del_adapter(&i2c_dev->adap); pm_runtime_get_sync(i2c_dev->dev); - clk_disable_unprepare(i2c_dev->clk); - pm_runtime_put_noidle(i2c_dev->dev); pm_runtime_disable(i2c_dev->dev); pm_runtime_set_suspended(i2c_dev->dev); pm_runtime_dont_use_autosuspend(i2c_dev->dev); + if (i2c_dev->dma) { + stm32_i2c_dma_free(i2c_dev->dma); + i2c_dev->dma = NULL; + } + + clk_disable_unprepare(i2c_dev->clk); + return 0; } diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c1683f9338b4..a98bf31d0e5c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -413,7 +413,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) return 0; } - chan = dma_request_slave_channel_reason(i2c_dev->dev, "rx"); + chan = dma_request_chan(i2c_dev->dev, "rx"); if (IS_ERR(chan)) { err = PTR_ERR(chan); goto err_out; @@ -421,7 +421,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) i2c_dev->rx_dma_chan = chan; - chan = dma_request_slave_channel_reason(i2c_dev->dev, "tx"); + chan = dma_request_chan(i2c_dev->dev, "tx"); if (IS_ERR(chan)) { err = PTR_ERR(chan); goto err_out; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 37b3b9307d07..d8d49f1814c7 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -46,6 +46,7 @@ enum xiic_endian { /** * struct xiic_i2c - Internal representation of the XIIC I2C bus + * @dev: Pointer to device structure * @base: Memory base of the HW registers * @wait: Wait queue for callers * @adap: Kernel adapter representation @@ -57,6 +58,7 @@ enum xiic_endian { * @rx_msg: Current RX message * @rx_pos: Position within current RX message * @endianness: big/little-endian byte order + * @clk: Pointer to AXI4-lite input clock */ struct xiic_i2c { struct device *dev; diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 5f6a4985f2bc..9333c865d4a9 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1656,6 +1656,12 @@ void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_de t->sda_fall_ns = t->scl_fall_ns; device_property_read_u32(dev, "i2c-sda-hold-time-ns", &t->sda_hold_ns); + + device_property_read_u32(dev, "i2c-digital-filter-width-ns", + &t->digital_filter_width_ns); + + device_property_read_u32(dev, "i2c-analog-filter-cutoff-frequency", + &t->analog_filter_cutoff_freq_hz); } EXPORT_SYMBOL_GPL(i2c_parse_fw_timings); @@ -1737,38 +1743,6 @@ EXPORT_SYMBOL(i2c_del_driver); /* ------------------------------------------------------------------------- */ -/** - * i2c_use_client - increments the reference count of the i2c client structure - * @client: the client being referenced - * - * Each live reference to a client should be refcounted. The driver model does - * that automatically as part of driver binding, so that most drivers don't - * need to do this explicitly: they hold a reference until they're unbound - * from the device. - * - * A pointer to the client with the incremented reference counter is returned. - */ -struct i2c_client *i2c_use_client(struct i2c_client *client) -{ - if (client && get_device(&client->dev)) - return client; - return NULL; -} -EXPORT_SYMBOL(i2c_use_client); - -/** - * i2c_release_client - release a use of the i2c client structure - * @client: the client being no longer referenced - * - * Must be called when a user of a client is finished with it. - */ -void i2c_release_client(struct i2c_client *client) -{ - if (client) - put_device(&client->dev); -} -EXPORT_SYMBOL(i2c_release_client); - struct i2c_cmd_arg { unsigned cmd; void *arg; @@ -2271,10 +2245,10 @@ int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); struct i2c_client * -i2c_new_probed_device(struct i2c_adapter *adap, - struct i2c_board_info *info, - unsigned short const *addr_list, - int (*probe)(struct i2c_adapter *adap, unsigned short addr)) +i2c_new_scanned_device(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *adap, unsigned short addr)) { int i; @@ -2304,11 +2278,24 @@ i2c_new_probed_device(struct i2c_adapter *adap, if (addr_list[i] == I2C_CLIENT_END) { dev_dbg(&adap->dev, "Probing failed, no device found\n"); - return NULL; + return ERR_PTR(-ENODEV); } info->addr = addr_list[i]; - return i2c_new_device(adap, info); + return i2c_new_client_device(adap, info); +} +EXPORT_SYMBOL_GPL(i2c_new_scanned_device); + +struct i2c_client * +i2c_new_probed_device(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *adap, unsigned short addr)) +{ + struct i2c_client *client; + + client = i2c_new_scanned_device(adap, info, addr_list, probe); + return IS_ERR(client) ? NULL : client; } EXPORT_SYMBOL_GPL(i2c_new_probed_device); diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 03096f47e6ab..7e2f5d0eacdb 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -66,7 +66,6 @@ static irqreturn_t smbus_alert(int irq, void *d) { struct i2c_smbus_alert *alert = d; struct i2c_client *ara; - unsigned short prev_addr = 0; /* Not a valid address */ ara = alert->ara; @@ -90,18 +89,12 @@ static irqreturn_t smbus_alert(int irq, void *d) data.addr = status >> 1; data.type = I2C_PROTOCOL_SMBUS_ALERT; - if (data.addr == prev_addr) { - dev_warn(&ara->dev, "Duplicate SMBALERT# from dev " - "0x%02x, skipping\n", data.addr); - break; - } dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n", data.addr, data.data); /* Notify driver for the device which issued the alert */ device_for_each_child(&ara->adapter->dev, &data, smbus_do_alert); - prev_addr = data.addr; } return IRQ_HANDLED; diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index c6040aa839ac..1708b1a82da2 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -109,14 +109,14 @@ config I2C_DEMUX_PINCTRL want to change the I2C master at run-time depending on features. config I2C_MUX_MLXCPLD - tristate "Mellanox CPLD based I2C multiplexer" - help - If you say yes to this option, support will be included for a - CPLD based I2C multiplexer. This driver provides access to - I2C busses connected through a MUX, which is controlled - by a CPLD register. - - This driver can also be built as a module. If so, the module - will be called i2c-mux-mlxcpld. + tristate "Mellanox CPLD based I2C multiplexer" + help + If you say yes to this option, support will be included for a + CPLD based I2C multiplexer. This driver provides access to + I2C busses connected through a MUX, which is controlled + by a CPLD register. + + This driver can also be built as a module. If so, the module + will be called i2c-mux-mlxcpld. endmenu |