From 7629254054820bead6e18f8c3ae65c2bb01a5ae2 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Thu, 5 Aug 2021 00:54:46 +0530 Subject: [PATCH 01/43] dt-bindings: at24: add ON Semi CAT24C04 and CAT24C05 Add bindings for ON Semi CAT24C04 and CAT24C05 eeproms, which are compatible with Atmel AT24C04. Signed-off-by: Raag Jadav Signed-off-by: Bartosz Golaszewski --- Documentation/devicetree/bindings/eeprom/at24.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml index 914a423ec449..4c5396a9744f 100644 --- a/Documentation/devicetree/bindings/eeprom/at24.yaml +++ b/Documentation/devicetree/bindings/eeprom/at24.yaml @@ -97,6 +97,12 @@ properties: - items: - const: nxp,se97b - const: atmel,24c02 + - items: + - const: onnn,cat24c04 + - const: atmel,24c04 + - items: + - const: onnn,cat24c05 + - const: atmel,24c04 - items: - const: renesas,r1ex24002 - const: atmel,24c02 From c119e7d00c916881913011e6f4c6ac349a41e4e2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Aug 2021 23:41:40 +0200 Subject: [PATCH 02/43] i2c: xiic: Fix broken locking on tx_msg The tx_msg is set from multiple places, sometimes without locking, which fall apart on any SMP system. Only ever access tx_msg inside the driver mutex. Signed-off-by: Marek Vasut Acked-by: Michal Simek Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xiic.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index bb93db98404e..50320dd32eea 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -170,7 +170,7 @@ struct xiic_i2c { #define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos) #define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos) -static int xiic_start_xfer(struct xiic_i2c *i2c); +static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num); static void __xiic_start_xfer(struct xiic_i2c *i2c); /* @@ -684,15 +684,25 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c) } -static int xiic_start_xfer(struct xiic_i2c *i2c) +static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) { int ret; + mutex_lock(&i2c->lock); + ret = xiic_busy(i2c); + if (ret) + goto out; + + i2c->tx_msg = msgs; + i2c->rx_msg = NULL; + i2c->nmsgs = num; + ret = xiic_reinit(i2c); if (!ret) __xiic_start_xfer(i2c); +out: mutex_unlock(&i2c->lock); return ret; @@ -710,14 +720,7 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (err < 0) return err; - err = xiic_busy(i2c); - if (err) - goto out; - - i2c->tx_msg = msgs; - i2c->nmsgs = num; - - err = xiic_start_xfer(i2c); + err = xiic_start_xfer(i2c, msgs, num); if (err < 0) { dev_err(adap->dev.parent, "Error xiic_start_xfer\n"); goto out; @@ -725,9 +728,11 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || (i2c->state == STATE_DONE), HZ)) { + mutex_lock(&i2c->lock); err = (i2c->state == STATE_DONE) ? num : -EIO; goto out; } else { + mutex_lock(&i2c->lock); i2c->tx_msg = NULL; i2c->rx_msg = NULL; i2c->nmsgs = 0; @@ -735,6 +740,7 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) goto out; } out: + mutex_unlock(&i2c->lock); pm_runtime_mark_last_busy(i2c->dev); pm_runtime_put_autosuspend(i2c->dev); return err; From 861dcffe1b9e986d254ea0d7e9f0a542bfc5ab11 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Aug 2021 23:41:41 +0200 Subject: [PATCH 03/43] i2c: xiic: Drop broken interrupt handler The interrupt handler is missing locking when reading out registers and is racing with other threads which might access the driver. Drop it altogether, so that the threaded interrupt is always executed, as that one is already serialized by the driver mutex. This also allows dropping local_irq_save()/local_irq_restore() in xiic_start_recv(). Signed-off-by: Marek Vasut Acked-by: Michal Simek Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xiic.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 50320dd32eea..b13166e94d89 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -554,7 +554,6 @@ static void xiic_start_recv(struct xiic_i2c *i2c) { u8 rx_watermark; struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg; - unsigned long flags; /* Clear and enable Rx full interrupt. */ xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK); @@ -570,7 +569,6 @@ static void xiic_start_recv(struct xiic_i2c *i2c) rx_watermark = IIC_RX_FIFO_DEPTH; xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); - local_irq_save(flags); if (!(msg->flags & I2C_M_NOSTART)) /* write the address */ xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, @@ -580,7 +578,6 @@ static void xiic_start_recv(struct xiic_i2c *i2c) xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0)); - local_irq_restore(flags); if (i2c->nmsgs == 1) /* very last, enable bus not busy as well */ @@ -620,26 +617,6 @@ static void xiic_start_send(struct xiic_i2c *i2c) XIIC_INTR_BNB_MASK); } -static irqreturn_t xiic_isr(int irq, void *dev_id) -{ - struct xiic_i2c *i2c = dev_id; - u32 pend, isr, ier; - irqreturn_t ret = IRQ_NONE; - /* Do not processes a devices interrupts if the device has no - * interrupts pending - */ - - dev_dbg(i2c->adap.dev.parent, "%s entry\n", __func__); - - isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); - ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - pend = isr & ier; - if (pend) - ret = IRQ_WAKE_THREAD; - - return ret; -} - static void __xiic_start_xfer(struct xiic_i2c *i2c) { int first = 1; @@ -818,7 +795,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(i2c->dev); pm_runtime_set_active(i2c->dev); pm_runtime_enable(i2c->dev); - ret = devm_request_threaded_irq(&pdev->dev, irq, xiic_isr, + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, xiic_process, IRQF_ONESHOT, pdev->name, i2c); From 743e227a895923c37a333eb2ebf3e391f00c406d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Aug 2021 23:41:42 +0200 Subject: [PATCH 04/43] i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process() The __xiic_start_xfer() manipulates the interrupt flags, xiic_wakeup() may result in return from xiic_xfer() early. Defer both to the end of the xiic_process() interrupt thread, so that they are executed after all the other interrupt bits handling completed and once it completely safe to perform changes to the interrupt bits in the hardware. Signed-off-by: Marek Vasut Acked-by: Michal Simek Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xiic.c | 37 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index b13166e94d89..aecdeec57997 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -375,6 +375,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id) struct xiic_i2c *i2c = dev_id; u32 pend, isr, ier; u32 clr = 0; + int xfer_more = 0; + int wakeup_req = 0; + int wakeup_code = 0; /* Get the interrupt Status from the IPIF. There is no clearing of * interrupts in the IPIF. Interrupts must be cleared at the source. @@ -411,10 +414,14 @@ static irqreturn_t xiic_process(int irq, void *dev_id) */ xiic_reinit(i2c); - if (i2c->rx_msg) - xiic_wakeup(i2c, STATE_ERROR); - if (i2c->tx_msg) - xiic_wakeup(i2c, STATE_ERROR); + if (i2c->rx_msg) { + wakeup_req = 1; + wakeup_code = STATE_ERROR; + } + if (i2c->tx_msg) { + wakeup_req = 1; + wakeup_code = STATE_ERROR; + } } if (pend & XIIC_INTR_RX_FULL_MASK) { /* Receive register/FIFO is full */ @@ -448,8 +455,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) i2c->tx_msg++; dev_dbg(i2c->adap.dev.parent, "%s will start next...\n", __func__); - - __xiic_start_xfer(i2c); + xfer_more = 1; } } } @@ -463,11 +469,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id) if (!i2c->tx_msg) goto out; - if ((i2c->nmsgs == 1) && !i2c->rx_msg && - xiic_tx_space(i2c) == 0) - xiic_wakeup(i2c, STATE_DONE); + wakeup_req = 1; + + if (i2c->nmsgs == 1 && !i2c->rx_msg && + xiic_tx_space(i2c) == 0) + wakeup_code = STATE_DONE; else - xiic_wakeup(i2c, STATE_ERROR); + wakeup_code = STATE_ERROR; } if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { /* Transmit register/FIFO is empty or ½ empty */ @@ -491,7 +499,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) if (i2c->nmsgs > 1) { i2c->nmsgs--; i2c->tx_msg++; - __xiic_start_xfer(i2c); + xfer_more = 1; } else { xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); @@ -509,6 +517,13 @@ out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); + if (xfer_more) + __xiic_start_xfer(i2c); + if (wakeup_req) + xiic_wakeup(i2c, wakeup_code); + + WARN_ON(xfer_more && wakeup_req); + mutex_unlock(&i2c->lock); return IRQ_HANDLED; } From fdacc3c7405d1fc33c1f2771699a4fc24551e480 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Aug 2021 23:41:43 +0200 Subject: [PATCH 05/43] i2c: xiic: Switch from waitqueue to completion There will never be threads queueing up in the xiic_xmit(), use completion synchronization primitive to wait for the interrupt handler thread to complete instead as it is much better fit and there is no need to overload it for this purpose. Signed-off-by: Marek Vasut Acked-by: Michal Simek Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xiic.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index aecdeec57997..f7277629923f 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,7 +48,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 + * @completion: Completion for callers * @adap: Kernel adapter representation * @tx_msg: Messages from above to be sent * @lock: Mutual exclusion @@ -64,7 +64,7 @@ enum xiic_endian { struct xiic_i2c { struct device *dev; void __iomem *base; - wait_queue_head_t wait; + struct completion completion; struct i2c_adapter adap; struct i2c_msg *tx_msg; struct mutex lock; @@ -160,6 +160,9 @@ struct xiic_i2c { #define XIIC_PM_TIMEOUT 1000 /* ms */ /* timeout waiting for the controller to respond */ #define XIIC_I2C_TIMEOUT (msecs_to_jiffies(1000)) +/* timeout waiting for the controller finish transfers */ +#define XIIC_XFER_TIMEOUT (msecs_to_jiffies(10000)) + /* * The following constant is used for the device global interrupt enable * register, to enable all interrupts for the device, this is the only bit @@ -367,7 +370,7 @@ static void xiic_wakeup(struct xiic_i2c *i2c, int code) i2c->rx_msg = NULL; i2c->nmsgs = 0; i2c->state = code; - wake_up(&i2c->wait); + complete(&i2c->completion); } static irqreturn_t xiic_process(int irq, void *dev_id) @@ -689,6 +692,7 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) i2c->tx_msg = msgs; i2c->rx_msg = NULL; i2c->nmsgs = num; + init_completion(&i2c->completion); ret = xiic_reinit(i2c); if (!ret) @@ -715,23 +719,23 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) err = xiic_start_xfer(i2c, msgs, num); if (err < 0) { dev_err(adap->dev.parent, "Error xiic_start_xfer\n"); - goto out; + return err; } - if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || - (i2c->state == STATE_DONE), HZ)) { - mutex_lock(&i2c->lock); - err = (i2c->state == STATE_DONE) ? num : -EIO; - goto out; - } else { - mutex_lock(&i2c->lock); + err = wait_for_completion_timeout(&i2c->completion, XIIC_XFER_TIMEOUT); + mutex_lock(&i2c->lock); + if (err == 0) { /* Timeout */ i2c->tx_msg = NULL; i2c->rx_msg = NULL; i2c->nmsgs = 0; err = -ETIMEDOUT; - goto out; + } else if (err < 0) { /* Completion error */ + i2c->tx_msg = NULL; + i2c->rx_msg = NULL; + i2c->nmsgs = 0; + } else { + err = (i2c->state == STATE_DONE) ? num : -EIO; } -out: mutex_unlock(&i2c->lock); pm_runtime_mark_last_busy(i2c->dev); pm_runtime_put_autosuspend(i2c->dev); @@ -793,7 +797,6 @@ static int xiic_i2c_probe(struct platform_device *pdev) i2c->adap.dev.of_node = pdev->dev.of_node; mutex_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); i2c->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) From d12e4bbb190b9edb47b31511e624f2a90f35f443 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Aug 2021 23:41:44 +0200 Subject: [PATCH 06/43] i2c: xiic: Only ever transfer single message Transferring multiple messages via XIIC suffers from strange interaction between the interrupt status/enable register flags. These flags are being reused in the hardware to indicate different things for read and write transfer, and doing multiple transactions becomes horribly complex. Just send a single transaction and reload the controller with another message once the transaction is done in the interrupt handler thread. Signed-off-by: Marek Vasut Acked-by: Michal Simek Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xiic.c | 44 ++++++++--------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index f7277629923f..6cd7830fe489 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -609,8 +609,6 @@ static void xiic_start_send(struct xiic_i2c *i2c) { struct i2c_msg *msg = i2c->tx_msg; - xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK); - dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d", __func__, msg, msg->len); dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", @@ -628,16 +626,17 @@ static void xiic_start_send(struct xiic_i2c *i2c) xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); } - xiic_fill_tx_fifo(i2c); - /* Clear any pending Tx empty, Tx Error and then enable them. */ xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK | - XIIC_INTR_BNB_MASK); + XIIC_INTR_BNB_MASK | + ((i2c->nmsgs > 1 || xiic_tx_space(i2c)) ? + XIIC_INTR_TX_HALF_MASK : 0)); + + xiic_fill_tx_fifo(i2c); } static void __xiic_start_xfer(struct xiic_i2c *i2c) { - int first = 1; int fifo_space = xiic_tx_fifo_space(i2c); dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n", __func__, i2c->tx_msg, fifo_space); @@ -648,35 +647,12 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c) i2c->rx_pos = 0; i2c->tx_pos = 0; i2c->state = STATE_START; - while ((fifo_space >= 2) && (first || (i2c->nmsgs > 1))) { - if (!first) { - i2c->nmsgs--; - i2c->tx_msg++; - i2c->tx_pos = 0; - } else - first = 0; - - if (i2c->tx_msg->flags & I2C_M_RD) { - /* we dont date putting several reads in the FIFO */ - xiic_start_recv(i2c); - return; - } else { - xiic_start_send(i2c); - if (xiic_tx_space(i2c) != 0) { - /* the message could not be completely sent */ - break; - } - } - - fifo_space = xiic_tx_fifo_space(i2c); + if (i2c->tx_msg->flags & I2C_M_RD) { + /* we dont date putting several reads in the FIFO */ + xiic_start_recv(i2c); + } else { + xiic_start_send(i2c); } - - /* there are more messages or the current one could not be completely - * put into the FIFO, also enable the half empty interrupt - */ - if (i2c->nmsgs > 1 || xiic_tx_space(i2c)) - xiic_irq_clr_en(i2c, XIIC_INTR_TX_HALF_MASK); - } static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) From 294b29f15469e90893c2b72a738a962ee02a12eb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Aug 2021 23:41:45 +0200 Subject: [PATCH 07/43] i2c: xiic: Fix RX IRQ busy check In case the XIIC does TX/RX transfer, make sure no other kernel thread can start another TX transfer at the same time. This could happen since the driver only checks tx_msg for being non-NULL and returns -EBUSY in that case, however it is necessary to check also rx_msg for the same. Signed-off-by: Marek Vasut Acked-by: Michal Simek Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xiic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 6cd7830fe489..eb789cfb9973 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -543,7 +543,7 @@ static int xiic_busy(struct xiic_i2c *i2c) int tries = 3; int err; - if (i2c->tx_msg) + if (i2c->tx_msg || i2c->rx_msg) return -EBUSY; /* In single master mode bus can only be busy, when in use by this From 2b3db4db660f9cc04878d81c2517f840763e6733 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 6 Aug 2021 23:15:15 +0200 Subject: [PATCH 08/43] i2c: i801: Improve is_dell_system_with_lis3lv02d Replace the ugly cast of the return_value pointer with proper usage. In addition use dmi_match() instead of open-coding it. Signed-off-by: Heiner Kallweit Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 89ae78ef1a1c..f56060fcf5ac 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1192,7 +1192,7 @@ static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle, kfree(info); - *((bool *)return_value) = true; + *return_value = NULL; return AE_CTRL_TERMINATE; smo88xx_not_found: @@ -1202,11 +1202,9 @@ smo88xx_not_found: static bool is_dell_system_with_lis3lv02d(void) { - bool found; - const char *vendor; + void *err = ERR_PTR(-ENOENT); - vendor = dmi_get_system_info(DMI_SYS_VENDOR); - if (!vendor || strcmp(vendor, "Dell Inc.")) + if (!dmi_match(DMI_SYS_VENDOR, "Dell Inc.")) return false; /* @@ -1217,11 +1215,9 @@ static bool is_dell_system_with_lis3lv02d(void) * accelerometer but unfortunately ACPI does not provide any other * information (like I2C address). */ - found = false; - acpi_get_devices(NULL, check_acpi_smo88xx_device, NULL, - (void **)&found); + acpi_get_devices(NULL, check_acpi_smo88xx_device, NULL, &err); - return found; + return !IS_ERR(err); } /* From e462aa7e39b5b6f70bc993d5ce50f7cc2e71182a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 6 Aug 2021 23:15:51 +0200 Subject: [PATCH 09/43] i2c: i801: Remove not needed check for PCI_COMMAND_INTX_DISABLE do_pci_enable_device() takes care that PCI_COMMAND_INTX_DISABLE is cleared if a legacy interrupt is used. Signed-off-by: Heiner Kallweit Reviewed-by: Andy Shevchenko Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f56060fcf5ac..7fa06b85fa97 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1827,19 +1827,12 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) priv->features &= ~FEATURE_IRQ; if (priv->features & FEATURE_IRQ) { - u16 pcictl, pcists; + u16 pcists; /* Complain if an interrupt is already pending */ pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); if (pcists & PCI_STATUS_INTERRUPT) dev_warn(&dev->dev, "An interrupt is pending!\n"); - - /* Check if interrupts have been disabled */ - pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pcictl); - if (pcictl & PCI_COMMAND_INTX_DISABLE) { - dev_info(&dev->dev, "Interrupts are disabled\n"); - priv->features &= ~FEATURE_IRQ; - } } if (priv->features & FEATURE_IRQ) { From 4811a411a92913e5327e4b32d4bb783823348537 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 6 Aug 2021 23:16:33 +0200 Subject: [PATCH 10/43] i2c: i801: Improve i801_acpi_probe/remove functions By using ACPI_HANDLE() the handler argument can be retrieved directly. Both address space handler functions check the handler argument and return an error if it's NULL. This allows to further simplify the code. Reviewed-by: Jean Delvare Tested-by: Jean Delvare Reviewed-by: Mika Westerberg Signed-off-by: Heiner Kallweit Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 7fa06b85fa97..bd1db0f0aa19 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1635,31 +1635,22 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, static int i801_acpi_probe(struct i801_priv *priv) { - struct acpi_device *adev; + acpi_handle ah = ACPI_HANDLE(&priv->pci_dev->dev); acpi_status status; - adev = ACPI_COMPANION(&priv->pci_dev->dev); - if (adev) { - status = acpi_install_address_space_handler(adev->handle, - ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler, - NULL, priv); - if (ACPI_SUCCESS(status)) - return 0; - } + status = acpi_install_address_space_handler(ah, ACPI_ADR_SPACE_SYSTEM_IO, + i801_acpi_io_handler, NULL, priv); + if (ACPI_SUCCESS(status)) + return 0; return acpi_check_resource_conflict(&priv->pci_dev->resource[SMBBAR]); } static void i801_acpi_remove(struct i801_priv *priv) { - struct acpi_device *adev; + acpi_handle ah = ACPI_HANDLE(&priv->pci_dev->dev); - adev = ACPI_COMPANION(&priv->pci_dev->dev); - if (!adev) - return; - - acpi_remove_address_space_handler(adev->handle, - ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler); + acpi_remove_address_space_handler(ah, ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler); } #else static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; } From 4c5910631cc1a9c3b8d34ebb0048727eded9148c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 6 Aug 2021 23:17:10 +0200 Subject: [PATCH 11/43] i2c: i801: Improve i801_add_mux The return value of i801_add_mux() isn't used, so let's change it to void. In addition remove the not needed cast to struct gpiod_lookup. GPIO_LOOKUP() uses GPIO_LOOKUP_IDX() that includes this cast. Reviewed-by: Jean Delvare Tested-by: Jean Delvare Signed-off-by: Heiner Kallweit Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index bd1db0f0aa19..6e9aca81b7f0 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1391,7 +1391,7 @@ static const struct dmi_system_id mux_dmi_table[] = { }; /* Setup multiplexing if needed */ -static int i801_add_mux(struct i801_priv *priv) +static void i801_add_mux(struct i801_priv *priv) { struct device *dev = &priv->adapter.dev; const struct i801_mux_config *mux_config; @@ -1400,7 +1400,7 @@ static int i801_add_mux(struct i801_priv *priv) int i; if (!priv->mux_drvdata) - return 0; + return; mux_config = priv->mux_drvdata; /* Prepare the platform data */ @@ -1416,13 +1416,11 @@ static int i801_add_mux(struct i801_priv *priv) struct_size(lookup, table, mux_config->n_gpios + 1), GFP_KERNEL); if (!lookup) - return -ENOMEM; + return; lookup->dev_id = "i2c-mux-gpio"; - for (i = 0; i < mux_config->n_gpios; i++) { - lookup->table[i] = (struct gpiod_lookup) - GPIO_LOOKUP(mux_config->gpio_chip, - mux_config->gpios[i], "mux", 0); - } + 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->lookup = lookup; @@ -1440,8 +1438,6 @@ static int i801_add_mux(struct i801_priv *priv) gpiod_remove_lookup_table(lookup); dev_err(dev, "Failed to register i2c-mux-gpio device\n"); } - - return PTR_ERR_OR_ZERO(priv->mux_pdev); } static void i801_del_mux(struct i801_priv *priv) @@ -1471,7 +1467,7 @@ static unsigned int i801_get_adapter_class(struct i801_priv *priv) return class; } #else -static inline int i801_add_mux(struct i801_priv *priv) { return 0; } +static inline void i801_add_mux(struct i801_priv *priv) { } static inline void i801_del_mux(struct i801_priv *priv) { } static inline unsigned int i801_get_adapter_class(struct i801_priv *priv) From 7d6b61c394a42b8385858bb9e306d48a0112823c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 5 Sep 2021 17:59:42 +0200 Subject: [PATCH 12/43] i2c: i801: Use PCI bus rescan mutex to protect P2SB access As pointed out by Andy in [0] using a local mutex here isn't strictly wrong but not sufficient. We should hold the PCI rescan lock for P2SB operations. [0] https://www.spinics.net/lists/linux-i2c/msg52717.html Fixes: 1a987c69ce2c ("i2c: i801: make p2sb_spinlock a mutex") Reported-by: Andy Shevchenko Signed-off-by: Heiner Kallweit Reviewed-by: Andy Shevchenko Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 6e9aca81b7f0..260fc41b5ca7 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1485,7 +1485,6 @@ static struct platform_device * i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, struct resource *tco_res) { - static DEFINE_MUTEX(p2sb_mutex); struct resource *res; unsigned int devfn; u64 base64_addr; @@ -1498,7 +1497,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, * enumerated by the PCI subsystem, so we need to unhide/hide it * to lookup the P2SB BAR. */ - mutex_lock(&p2sb_mutex); + pci_lock_rescan_remove(); devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1); @@ -1516,7 +1515,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, /* Hide the P2SB device, if it was hidden before */ if (hidden) pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden); - mutex_unlock(&p2sb_mutex); + pci_unlock_rescan_remove(); res = &tco_res[1]; if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS) From c073b25dad0c2668b73ae9e8652bc3b8012e762b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 7 Sep 2021 22:33:02 +0200 Subject: [PATCH 13/43] i2c: i801: Stop using pm_runtime_set_autosuspend_delay(-1) The original change works as intended, but Andy pointed in [0] that now userspace could re-enable RPM via sysfs, even though we explicitly want to disable it. So effectively revert the original patch, just with small improvements: - Calls to pm_runtime_allow()/pm_runtime_forbid() don't have to be balanced, so we can remove the call to pm_runtime_forbid() in i801_remove(). - priv->acpi_reserved is accessed after i801_acpi_remove(), and according to Robert [1] the custom handler can't run any longer. Therefore we don't have to take priv->acpi_lock. [0] https://www.spinics.net/lists/linux-i2c/msg52730.html [1] https://lore.kernel.org/linux-acpi/BYAPR11MB32561D19A0FD9AB93E2B1E5287D39@BYAPR11MB3256.namprd11.prod.outlook.com/T/#t Fixes: 4e60d5dd10cd ("i2c: i801: Improve disabling runtime pm") Reported-by: Andy Shevchenko Signed-off-by: Heiner Kallweit Acked-by: Rafael J. Wysocki Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 260fc41b5ca7..115660dce722 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1615,7 +1615,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, * BIOS is accessing the host controller so prevent it from * suspending automatically from now on. */ - pm_runtime_set_autosuspend_delay(&pdev->dev, -1); + pm_runtime_get_sync(&pdev->dev); } if ((function & ACPI_IO_MASK) == ACPI_READ) @@ -1866,9 +1866,6 @@ static void i801_remove(struct pci_dev *dev) { struct i801_priv *priv = pci_get_drvdata(dev); - pm_runtime_forbid(&dev->dev); - pm_runtime_get_noresume(&dev->dev); - i801_disable_host_notify(priv); i801_del_mux(priv); i2c_del_adapter(&priv->adapter); @@ -1877,6 +1874,10 @@ static void i801_remove(struct pci_dev *dev) platform_device_unregister(priv->tco_pdev); + /* if acpi_reserved is set then usage_count is incremented already */ + if (!priv->acpi_reserved) + pm_runtime_get_noresume(&dev->dev); + /* * do not call pci_disable_device(dev) since it can cause hard hangs on * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010) From e7f4264821a4ee07775f3775f8530cfa9a6d4b5d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 15 Sep 2021 15:48:27 +0200 Subject: [PATCH 14/43] i2c: rcar: enable interrupts before starting transfer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to enable the interrupts _before_ starting the transfer because it is good programming style and also the proposed order in the R-Car manual. There is no difference in practice because it doesn't matter in which order both conditions appear if we wait for both to happen. Signed-off-by: Ryo Kataoka Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Ulrich Hecht Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rcar.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index bff9913c37b8..fc13511f4562 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -339,6 +339,9 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv) priv->flags |= ID_LAST_MSG; rcar_i2c_write(priv, ICMAR, i2c_8bit_addr_from_msg(priv->msg)); + if (!priv->atomic_xfer) + rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND); + /* * We don't have a test case but the HW engineers say that the write order * of ICMSR and ICMCR depends on whether we issue START or REP_START. Since @@ -354,9 +357,6 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv) rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START); rcar_i2c_write(priv, ICMSR, 0); } - - if (!priv->atomic_xfer) - rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND); } static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv) From ed2f85115a8e3423b68d8ac39aa7751c0779ce30 Mon Sep 17 00:00:00 2001 From: zhaoxiao Date: Mon, 6 Sep 2021 13:27:30 +0800 Subject: [PATCH 15/43] i2c: bcm-kona: Fix return value in probe() When call function devm_platform_ioremap_resource(), we should use IS_ERR() to check the return value and return PTR_ERR() if failed. Signed-off-by: zhaoxiao Acked-by: Florian Fainelli Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm-kona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index ed5e1275ae46..8e350f20cde0 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -763,7 +763,7 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev) /* Map hardware registers */ dev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dev->base)) - return -ENOMEM; + return PTR_ERR(dev->base); /* Get and enable external clock */ dev->external_clk = devm_clk_get(dev->device, NULL); From 647d908816a78d604d47ea925c934fd88375b4fd Mon Sep 17 00:00:00 2001 From: Michael Brunner Date: Tue, 31 Aug 2021 10:29:36 +0000 Subject: [PATCH 16/43] i2c: kempld: deprecate class based instantiation Warn users that class based instantiation is going away soon in favour of more robust probing and faster bootup times. Class based instantiation has already been removed for other controllers and it makes absolutely sense to do it for this one too. Signed-off-by: Michael Brunner Acked-by: Ingmar Klein Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-kempld.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index 2d60be086b1a..5bbb7f0d7852 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c @@ -283,7 +283,8 @@ static const struct i2c_algorithm kempld_i2c_algorithm = { static const struct i2c_adapter kempld_i2c_adapter = { .owner = THIS_MODULE, .name = "i2c-kempld", - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD | + I2C_CLASS_DEPRECATED, .algo = &kempld_i2c_algorithm, }; From b8228aea5a19d5111a7bf44f7de6749d1f5d487a Mon Sep 17 00:00:00 2001 From: Kewei Xu Date: Fri, 17 Sep 2021 18:14:10 +0800 Subject: [PATCH 17/43] i2c: mediatek: fixing the incorrect register offset The reason for the modification here is that the previous offset information is incorrect, OFFSET_DEBUGSTAT = 0xE4 is the correct value. Fixes: 25708278f810 ("i2c: mediatek: Add i2c support for MediaTek MT8183") Signed-off-by: Kewei Xu Reviewed-by: Chen-Yu Tsai Reviewed-by: Qii Wang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mt65xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 477480d1de6b..32518081b5a4 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -193,7 +193,7 @@ static const u16 mt_i2c_regs_v2[] = { [OFFSET_CLOCK_DIV] = 0x48, [OFFSET_SOFTRESET] = 0x50, [OFFSET_SCL_MIS_COMP_POINT] = 0x90, - [OFFSET_DEBUGSTAT] = 0xe0, + [OFFSET_DEBUGSTAT] = 0xe4, [OFFSET_DEBUGCTRL] = 0xe8, [OFFSET_FIFO_STAT] = 0xf4, [OFFSET_FIFO_THRESH] = 0xf8, From 511899ec34b605af5f8577f0f53866a8a60939f6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Sep 2021 19:05:17 +0200 Subject: [PATCH 18/43] i2c: pxa: drop unneeded MODULE_ALIAS The MODULE_DEVICE_TABLE already creates proper alias for platform driver. Having another MODULE_ALIAS causes the alias to be duplicated. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pxa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index a636ea0eb50a..690188a9ffff 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1547,7 +1547,6 @@ static void __exit i2c_adap_pxa_exit(void) } MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pxa2xx-i2c"); subsys_initcall(i2c_adap_pxa_init); module_exit(i2c_adap_pxa_exit); From cf9ae42c435c4a434b7c3d248f010699d43d684e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Sep 2021 15:35:49 +0200 Subject: [PATCH 19/43] i2c: exynos: describe drivers in KConfig Describe better which driver applies to which SoC, to make configuring kernel for Samsung SoC easier. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e17790fe35a7..1df19ccc310b 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -615,7 +615,10 @@ config I2C_EXYNOS5 depends on ARCH_EXYNOS || COMPILE_TEST default y if ARCH_EXYNOS help - High-speed I2C controller on Exynos5 and newer Samsung SoCs. + High-speed I2C controller on Samsung Exynos5 and newer Samsung SoCs: + Exynos5250, Exynos5260, Exynos5410, Exynos542x, Exynos5800, + Exynos5433 and Exynos7. + Choose Y here only if you build for such Samsung SoC. config I2C_GPIO tristate "GPIO-based bitbanging I2C" From d56baf6efaf14e2910610216c581ca71d6940012 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 22 Aug 2021 21:38:12 +0200 Subject: [PATCH 20/43] i2c: switch from 'pci_' to 'dma_' API The wrappers in include/linux/pci-dma-compat.h should go away. The patch has been generated with the coccinelle script below. It has been hand modified to use 'dma_set_mask_and_coherent()' instead of 'pci_set_dma_mask()/pci_set_consistent_dma_mask()' when applicable. This is less verbose. While at it a 'dev_err()' message has been slightly simplified. It has been compile tested. @@ @@ - PCI_DMA_BIDIRECTIONAL + DMA_BIDIRECTIONAL @@ @@ - PCI_DMA_TODEVICE + DMA_TO_DEVICE @@ @@ - PCI_DMA_FROMDEVICE + DMA_FROM_DEVICE @@ @@ - PCI_DMA_NONE + DMA_NONE @@ expression e1, e2, e3; @@ - pci_alloc_consistent(e1, e2, e3) + dma_alloc_coherent(&e1->dev, e2, e3, GFP_) @@ expression e1, e2, e3; @@ - pci_zalloc_consistent(e1, e2, e3) + dma_alloc_coherent(&e1->dev, e2, e3, GFP_) @@ expression e1, e2, e3, e4; @@ - pci_free_consistent(e1, e2, e3, e4) + dma_free_coherent(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_map_single(e1, e2, e3, e4) + dma_map_single(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_unmap_single(e1, e2, e3, e4) + dma_unmap_single(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4, e5; @@ - pci_map_page(e1, e2, e3, e4, e5) + dma_map_page(&e1->dev, e2, e3, e4, e5) @@ expression e1, e2, e3, e4; @@ - pci_unmap_page(e1, e2, e3, e4) + dma_unmap_page(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_map_sg(e1, e2, e3, e4) + dma_map_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_unmap_sg(e1, e2, e3, e4) + dma_unmap_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_single_for_cpu(e1, e2, e3, e4) + dma_sync_single_for_cpu(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_single_for_device(e1, e2, e3, e4) + dma_sync_single_for_device(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_sg_for_cpu(e1, e2, e3, e4) + dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_sg_for_device(e1, e2, e3, e4) + dma_sync_sg_for_device(&e1->dev, e2, e3, e4) @@ expression e1, e2; @@ - pci_dma_mapping_error(e1, e2) + dma_mapping_error(&e1->dev, e2) @@ expression e1, e2; @@ - pci_set_dma_mask(e1, e2) + dma_set_mask(&e1->dev, e2) @@ expression e1, e2; @@ - pci_set_consistent_dma_mask(e1, e2) + dma_set_coherent_mask(&e1->dev, e2) Signed-off-by: Christophe JAILLET Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-amd-mp2-pci.c | 4 ++-- drivers/i2c/busses/i2c-ismt.c | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c index ce130a821ea5..adf0e8c1ec01 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-pci.c +++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c @@ -307,9 +307,9 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata, pci_set_master(pci_dev); - rc = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64)); + rc = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32)); if (rc) goto err_dma_mask; } diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index a6187cbec2c9..f4820fd3dc13 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -918,13 +918,11 @@ 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); + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (err) { + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, "dma_set_mask fail\n"); return -ENODEV; } } From 669b2e4aa1a869def4dc207ea084fdd77366d646 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 23 Aug 2021 17:45:03 +0300 Subject: [PATCH 21/43] i2c: mlxcpld: Reduce polling time for performance improvement Decrease polling time 'MLXCPLD_I2C_POLL_TIME' from 400 usec to 200 usec. It improves performance of I2C transactions. Reliability of setting polling time to 200 usec has been validated across all the supported systems. Signed-off-by: Vadim Pasternak Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mlxcpld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index 4e0b7c2882ce..520db32ad467 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -27,7 +27,7 @@ #define MLXCPLD_I2C_MAX_ADDR_LEN 4 #define MLXCPLD_I2C_RETR_NUM 2 #define MLXCPLD_I2C_XFER_TO 500000 /* usec */ -#define MLXCPLD_I2C_POLL_TIME 400 /* usec */ +#define MLXCPLD_I2C_POLL_TIME 200 /* usec */ /* LPC I2C registers */ #define MLXCPLD_LPCI2C_CPBLTY_REG 0x0 From df7c4a8c1b47dc250d5525e68e785d9e65705e10 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:22 +0200 Subject: [PATCH 22/43] dt-bindings: i2c: Add Apple I2C controller bindings The Apple I2C controller is based on the PASemi I2C controller. It is present on Apple SoCs such as the M1. Reviewed-by: Arnd Bergmann Reviewed-by: Rob Herring Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- .../devicetree/bindings/i2c/apple,i2c.yaml | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/apple,i2c.yaml diff --git a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml new file mode 100644 index 000000000000..22fc8483256f --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/i2c/apple,i2c.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Apple/PASemi I2C controller + +maintainers: + - Sven Peter + +description: | + Apple SoCs such as the M1 come with a I2C controller based on the one found + in machines with P. A. Semi's PWRficient processors. + The bus is used to communicate with e.g. USB PD chips or the speaker + amp. + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + enum: + - apple,t8103-i2c + - apple,i2c + + reg: + maxItems: 1 + + clocks: + items: + - description: I2C bus reference clock + + interrupts: + maxItems: 1 + + clock-frequency: + description: | + Desired I2C bus clock frequency in Hz. If not specified, 100 kHz will be + used. This frequency is generated by dividing the reference clock. + Allowed values are between ref_clk/(16*4) and ref_clk/(16*255). + +required: + - compatible + - reg + - clocks + - interrupts + +unevaluatedProperties: false + +examples: + - | + i2c@35010000 { + compatible = "apple,t8103-i2c"; + reg = <0x35010000 0x4000>; + interrupt-parent = <&aic>; + interrupts = <0 627 4>; + clocks = <&ref_clk>; + #address-cells = <1>; + #size-cells = <0>; + }; From 3a7442ac1d1bfbe17f7c6cbc69756c529d7dda14 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:23 +0200 Subject: [PATCH 23/43] i2c: pasemi: Use io{read,write}32 In preparation for splitting this driver up into a platform_driver and a pci_driver, replace outl/inl usage with pci_iomap and ioread32/iowrite32. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 20f2772c0e79..39fcc584264a 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -20,6 +20,7 @@ static struct pci_driver pasemi_smb_driver; struct pasemi_smbus { struct pci_dev *dev; struct i2c_adapter adapter; + void __iomem *ioaddr; unsigned long base; int size; }; @@ -53,13 +54,13 @@ static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n", smbus->base + reg, val); - outl(val, smbus->base + reg); + iowrite32(val, smbus->ioaddr + reg); } static inline int reg_read(struct pasemi_smbus *smbus, int reg) { int ret; - ret = inl(smbus->base + reg); + ret = ioread32(smbus->ioaddr + reg); dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n", smbus->base + reg, ret); return ret; @@ -351,6 +352,12 @@ static int pasemi_smb_probe(struct pci_dev *dev, goto out_kfree; } + smbus->ioaddr = pci_iomap(dev, 0, 0); + if (!smbus->ioaddr) { + error = -EBUSY; + goto out_release_region; + } + smbus->adapter.owner = THIS_MODULE; snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), "PA Semi SMBus adapter at 0x%lx", smbus->base); @@ -366,12 +373,14 @@ static int pasemi_smb_probe(struct pci_dev *dev, error = i2c_add_adapter(&smbus->adapter); if (error) - goto out_release_region; + goto out_ioport_unmap; pci_set_drvdata(dev, smbus); return 0; + out_ioport_unmap: + pci_iounmap(dev, smbus->ioaddr); out_release_region: release_region(smbus->base, smbus->size); out_kfree: @@ -384,6 +393,7 @@ static void pasemi_smb_remove(struct pci_dev *dev) struct pasemi_smbus *smbus = pci_get_drvdata(dev); i2c_del_adapter(&smbus->adapter); + pci_iounmap(dev, smbus->ioaddr); release_region(smbus->base, smbus->size); kfree(smbus); } From 07e820d4fcb000d5dd72218f4334f2a210f75a81 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:24 +0200 Subject: [PATCH 24/43] i2c: pasemi: Use dev_name instead of port number Right now the i2c adapter name includes the port number which can indirectly be used to identify the device. Replace that with dev_name to directly identify the device and to also allow this to work correctly once we add platform support. Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 39fcc584264a..ca5a86cf53f1 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -360,7 +360,7 @@ static int pasemi_smb_probe(struct pci_dev *dev, smbus->adapter.owner = THIS_MODULE; snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), - "PA Semi SMBus adapter at 0x%lx", smbus->base); + "PA Semi SMBus adapter (%s)", dev_name(smbus->dev)); smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; From c06f50ed36cc0aeaf124bee0d676a21315aea5e7 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:25 +0200 Subject: [PATCH 25/43] i2c: pasemi: Remove usage of pci_dev Prepare to create a platform driver by removing all usages of pci_dev we can. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index ca5a86cf53f1..a018e9376023 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -18,7 +18,7 @@ static struct pci_driver pasemi_smb_driver; struct pasemi_smbus { - struct pci_dev *dev; + struct device *dev; struct i2c_adapter adapter; void __iomem *ioaddr; unsigned long base; @@ -52,7 +52,7 @@ struct pasemi_smbus { static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { - dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n", + dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n", smbus->base + reg, val); iowrite32(val, smbus->ioaddr + reg); } @@ -61,7 +61,7 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) { int ret; ret = ioread32(smbus->ioaddr + reg); - dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n", + dev_dbg(smbus->dev, "smbus read reg %lx val %08x\n", smbus->base + reg, ret); return ret; } @@ -94,7 +94,7 @@ static int pasemi_smb_waitready(struct pasemi_smbus *smbus) return -ENXIO; if (timeout < 0) { - dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status); + dev_warn(smbus->dev, "Timeout, status 0x%08x\n", status); reg_write(smbus, REG_SMSTA, status); return -ETIME; } @@ -342,7 +342,7 @@ static int pasemi_smb_probe(struct pci_dev *dev, if (!smbus) return -ENOMEM; - smbus->dev = dev; + smbus->dev = &dev->dev; smbus->base = pci_resource_start(dev, 0); smbus->size = pci_resource_len(dev, 0); @@ -366,7 +366,7 @@ static int pasemi_smb_probe(struct pci_dev *dev, smbus->adapter.algo_data = smbus; /* set up the sysfs linkage to our parent device */ - smbus->adapter.dev.parent = &dev->dev; + smbus->adapter.dev.parent = smbus->dev; reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | (CLK_100K_DIV & CTL_CLK_M))); From 6adb00c7f0edc081f21e0abd4d7eebe99589a287 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:26 +0200 Subject: [PATCH 26/43] i2c: pasemi: Split off common probing code Split off common probing code that will be used by both the PCI and the platform device. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi.c | 39 +++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index a018e9376023..baf338149673 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -329,6 +329,30 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = pasemi_smb_func, }; +static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) +{ + int error; + + smbus->adapter.owner = THIS_MODULE; + snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), + "PA Semi SMBus adapter (%s)", dev_name(smbus->dev)); + smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + smbus->adapter.algo = &smbus_algorithm; + smbus->adapter.algo_data = smbus; + + /* set up the sysfs linkage to our parent device */ + smbus->adapter.dev.parent = smbus->dev; + + reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | + (CLK_100K_DIV & CTL_CLK_M))); + + error = i2c_add_adapter(&smbus->adapter); + if (error) + return error; + + return 0; +} + static int pasemi_smb_probe(struct pci_dev *dev, const struct pci_device_id *id) { @@ -358,20 +382,7 @@ static int pasemi_smb_probe(struct pci_dev *dev, goto out_release_region; } - smbus->adapter.owner = THIS_MODULE; - snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), - "PA Semi SMBus adapter (%s)", dev_name(smbus->dev)); - smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - smbus->adapter.algo = &smbus_algorithm; - smbus->adapter.algo_data = smbus; - - /* set up the sysfs linkage to our parent device */ - smbus->adapter.dev.parent = smbus->dev; - - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); - - error = i2c_add_adapter(&smbus->adapter); + int error = pasemi_i2c_common_probe(smbus); if (error) goto out_ioport_unmap; From 9bc5f4f660ff3e37113847d749d43fafbadec629 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:27 +0200 Subject: [PATCH 27/43] i2c: pasemi: Split pci driver to its own file Split off the PCI driver so that we can reuse common code for the platform driver. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Makefile | 1 + .../{i2c-pasemi.c => i2c-pasemi-core.c} | 88 +---------------- drivers/i2c/busses/i2c-pasemi-core.h | 19 ++++ drivers/i2c/busses/i2c-pasemi-pci.c | 96 +++++++++++++++++++ 4 files changed, 118 insertions(+), 86 deletions(-) rename drivers/i2c/busses/{i2c-pasemi.c => i2c-pasemi-core.c} (81%) create mode 100644 drivers/i2c/busses/i2c-pasemi-core.h create mode 100644 drivers/i2c/busses/i2c-pasemi-pci.c diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 1336b04f40e2..0ab1b4cb2228 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_NPCM7XX) += i2c-npcm7xx.o obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o obj-$(CONFIG_I2C_OWL) += i2c-owl.o +i2c-pasemi-objs := i2c-pasemi-core.o i2c-pasemi-pci.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi-core.c similarity index 81% rename from drivers/i2c/busses/i2c-pasemi.c rename to drivers/i2c/busses/i2c-pasemi-core.c index baf338149673..d1cab11a4d50 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -15,15 +15,7 @@ #include #include -static struct pci_driver pasemi_smb_driver; - -struct pasemi_smbus { - struct device *dev; - struct i2c_adapter adapter; - void __iomem *ioaddr; - unsigned long base; - int size; -}; +#include "i2c-pasemi-core.h" /* Register offsets */ #define REG_MTXFIFO 0x00 @@ -329,7 +321,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = pasemi_smb_func, }; -static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) +int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) { int error; @@ -352,79 +344,3 @@ static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) return 0; } - -static int pasemi_smb_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - struct pasemi_smbus *smbus; - int error; - - if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) - return -ENODEV; - - smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL); - if (!smbus) - return -ENOMEM; - - smbus->dev = &dev->dev; - smbus->base = pci_resource_start(dev, 0); - smbus->size = pci_resource_len(dev, 0); - - if (!request_region(smbus->base, smbus->size, - pasemi_smb_driver.name)) { - error = -EBUSY; - goto out_kfree; - } - - smbus->ioaddr = pci_iomap(dev, 0, 0); - if (!smbus->ioaddr) { - error = -EBUSY; - goto out_release_region; - } - - int error = pasemi_i2c_common_probe(smbus); - if (error) - goto out_ioport_unmap; - - pci_set_drvdata(dev, smbus); - - return 0; - - out_ioport_unmap: - pci_iounmap(dev, smbus->ioaddr); - out_release_region: - release_region(smbus->base, smbus->size); - out_kfree: - kfree(smbus); - return error; -} - -static void pasemi_smb_remove(struct pci_dev *dev) -{ - struct pasemi_smbus *smbus = pci_get_drvdata(dev); - - i2c_del_adapter(&smbus->adapter); - pci_iounmap(dev, smbus->ioaddr); - release_region(smbus->base, smbus->size); - kfree(smbus); -} - -static const struct pci_device_id pasemi_smb_ids[] = { - { PCI_DEVICE(0x1959, 0xa003) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, pasemi_smb_ids); - -static struct pci_driver pasemi_smb_driver = { - .name = "i2c-pasemi", - .id_table = pasemi_smb_ids, - .probe = pasemi_smb_probe, - .remove = pasemi_smb_remove, -}; - -module_pci_driver(pasemi_smb_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Olof Johansson "); -MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver"); diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h new file mode 100644 index 000000000000..7acc33de6ce1 --- /dev/null +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct pasemi_smbus { + struct device *dev; + struct i2c_adapter adapter; + void __iomem *ioaddr; + unsigned long base; + int size; +}; + +int pasemi_i2c_common_probe(struct pasemi_smbus *smbus); diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c new file mode 100644 index 000000000000..644656e28012 --- /dev/null +++ b/drivers/i2c/busses/i2c-pasemi-pci.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2006-2007 PA Semi, Inc + * + * SMBus host driver for PA Semi PWRficient + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-pasemi-core.h" + +static struct pci_driver pasemi_smb_pci_driver; + +static int pasemi_smb_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct pasemi_smbus *smbus; + int error; + + if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) + return -ENODEV; + + smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL); + if (!smbus) + return -ENOMEM; + + smbus->dev = &dev->dev; + smbus->base = pci_resource_start(dev, 0); + smbus->size = pci_resource_len(dev, 0); + + if (!request_region(smbus->base, smbus->size, + pasemi_smb_pci_driver.name)) { + error = -EBUSY; + goto out_kfree; + } + + smbus->ioaddr = pci_iomap(dev, 0, 0); + if (!smbus->ioaddr) { + error = -EBUSY; + goto out_release_region; + } + + error = pasemi_i2c_common_probe(smbus); + if (error) + goto out_ioport_unmap; + + pci_set_drvdata(dev, smbus); + + return 0; + + out_ioport_unmap: + pci_iounmap(dev, smbus->ioaddr); + out_release_region: + release_region(smbus->base, smbus->size); + out_kfree: + kfree(smbus); + return error; +} + +static void pasemi_smb_pci_remove(struct pci_dev *dev) +{ + struct pasemi_smbus *smbus = pci_get_drvdata(dev); + + i2c_del_adapter(&smbus->adapter); + pci_iounmap(dev, smbus->ioaddr); + release_region(smbus->base, smbus->size); + kfree(smbus); +} + +static const struct pci_device_id pasemi_smb_pci_ids[] = { + { PCI_DEVICE(0x1959, 0xa003) }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, pasemi_smb_pci_ids); + +static struct pci_driver pasemi_smb_pci_driver = { + .name = "i2c-pasemi", + .id_table = pasemi_smb_pci_ids, + .probe = pasemi_smb_pci_probe, + .remove = pasemi_smb_pci_remove, +}; + +module_pci_driver(pasemi_smb_pci_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Olof Johansson "); +MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver"); From 1a62668cefdb0f8930e5ac47196abe51365ad76f Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:28 +0200 Subject: [PATCH 28/43] i2c: pasemi: Move common reset code to own function Split out common reset call to its own function so that we can later add support for selecting the clock frequency and an additional enable bit found in newer revisions. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi-core.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index d1cab11a4d50..232587c70a38 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -61,6 +61,12 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) #define TXFIFO_WR(smbus, reg) reg_write((smbus), REG_MTXFIFO, (reg)) #define RXFIFO_RD(smbus) reg_read((smbus), REG_MRXFIFO) +static void pasemi_reset(struct pasemi_smbus *smbus) +{ + reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | + (CLK_100K_DIV & CTL_CLK_M))); +} + static void pasemi_smb_clear(struct pasemi_smbus *smbus) { unsigned int status; @@ -135,8 +141,7 @@ static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter, return 0; reset_out: - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + pasemi_reset(smbus); return err; } @@ -302,8 +307,7 @@ static int pasemi_smb_xfer(struct i2c_adapter *adapter, return 0; reset_out: - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + pasemi_reset(smbus); return err; } @@ -335,8 +339,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) /* set up the sysfs linkage to our parent device */ smbus->adapter.dev.parent = smbus->dev; - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + pasemi_reset(smbus); error = i2c_add_adapter(&smbus->adapter); if (error) From fd664ab2319fb89cba5a522995e806eb26748af6 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:29 +0200 Subject: [PATCH 29/43] i2c: pasemi: Allow to configure bus frequency Right now the bus frequency has always been hardcoded as 100 KHz with the specific reference clock used in the PASemi PCI controllers. Make this configurable to prepare for the platform driver. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi-core.c | 8 +++----- drivers/i2c/busses/i2c-pasemi-core.h | 1 + drivers/i2c/busses/i2c-pasemi-pci.c | 4 ++++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index 232587c70a38..9fb8fac53f2b 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -39,9 +39,6 @@ #define CTL_MTR 0x00000200 #define CTL_CLK_M 0x000000ff -#define CLK_100K_DIV 84 -#define CLK_400K_DIV 21 - static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n", @@ -63,8 +60,9 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) static void pasemi_reset(struct pasemi_smbus *smbus) { - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M)); + + reg_write(smbus, REG_CTL, val); } static void pasemi_smb_clear(struct pasemi_smbus *smbus) diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h index 7acc33de6ce1..30a7990825ef 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.h +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -14,6 +14,7 @@ struct pasemi_smbus { void __iomem *ioaddr; unsigned long base; int size; + unsigned int clk_div; }; int pasemi_i2c_common_probe(struct pasemi_smbus *smbus); diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c index 644656e28012..96585bbf8c24 100644 --- a/drivers/i2c/busses/i2c-pasemi-pci.c +++ b/drivers/i2c/busses/i2c-pasemi-pci.c @@ -17,6 +17,9 @@ #include "i2c-pasemi-core.h" +#define CLK_100K_DIV 84 +#define CLK_400K_DIV 21 + static struct pci_driver pasemi_smb_pci_driver; static int pasemi_smb_pci_probe(struct pci_dev *dev, @@ -35,6 +38,7 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev, smbus->dev = &dev->dev; smbus->base = pci_resource_start(dev, 0); smbus->size = pci_resource_len(dev, 0); + smbus->clk_div = CLK_100K_DIV; if (!request_region(smbus->base, smbus->size, pasemi_smb_pci_driver.name)) { From a2c34bfd2c580f1732fc60e2af4aa439dde285be Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:30 +0200 Subject: [PATCH 30/43] i2c: pasemi: Refactor _probe to use devm_* Using managed device resources means there's nothing left to be done in pasemi_smb_pci_remove and also allows to remove base and size from struct pasemi_smbus. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi-core.c | 8 ++--- drivers/i2c/busses/i2c-pasemi-core.h | 2 -- drivers/i2c/busses/i2c-pasemi-pci.c | 45 ++++++++-------------------- 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index 9fb8fac53f2b..3d87b64dd9f7 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -41,8 +41,7 @@ static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { - dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n", - smbus->base + reg, val); + dev_dbg(smbus->dev, "smbus write reg %x val %08x\n", reg, val); iowrite32(val, smbus->ioaddr + reg); } @@ -50,8 +49,7 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) { int ret; ret = ioread32(smbus->ioaddr + reg); - dev_dbg(smbus->dev, "smbus read reg %lx val %08x\n", - smbus->base + reg, ret); + dev_dbg(smbus->dev, "smbus read reg %x val %08x\n", reg, ret); return ret; } @@ -339,7 +337,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) pasemi_reset(smbus); - error = i2c_add_adapter(&smbus->adapter); + error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter); if (error) return error; diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h index 30a7990825ef..aca4e2da9089 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.h +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -12,8 +12,6 @@ struct pasemi_smbus { struct device *dev; struct i2c_adapter adapter; void __iomem *ioaddr; - unsigned long base; - int size; unsigned int clk_div; }; diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c index 96585bbf8c24..4251e7b9f177 100644 --- a/drivers/i2c/busses/i2c-pasemi-pci.c +++ b/drivers/i2c/busses/i2c-pasemi-pci.c @@ -26,57 +26,37 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct pasemi_smbus *smbus; + unsigned long base; + int size; int error; if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) return -ENODEV; - smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL); + smbus = devm_kzalloc(&dev->dev, sizeof(*smbus), GFP_KERNEL); if (!smbus) return -ENOMEM; smbus->dev = &dev->dev; - smbus->base = pci_resource_start(dev, 0); - smbus->size = pci_resource_len(dev, 0); + base = pci_resource_start(dev, 0); + size = pci_resource_len(dev, 0); smbus->clk_div = CLK_100K_DIV; - if (!request_region(smbus->base, smbus->size, - pasemi_smb_pci_driver.name)) { - error = -EBUSY; - goto out_kfree; - } + if (!devm_request_region(&dev->dev, base, size, + pasemi_smb_pci_driver.name)) + return -EBUSY; - smbus->ioaddr = pci_iomap(dev, 0, 0); - if (!smbus->ioaddr) { - error = -EBUSY; - goto out_release_region; - } + smbus->ioaddr = pcim_iomap(dev, 0, 0); + if (!smbus->ioaddr) + return -EBUSY; error = pasemi_i2c_common_probe(smbus); if (error) - goto out_ioport_unmap; + return error; pci_set_drvdata(dev, smbus); return 0; - - out_ioport_unmap: - pci_iounmap(dev, smbus->ioaddr); - out_release_region: - release_region(smbus->base, smbus->size); - out_kfree: - kfree(smbus); - return error; -} - -static void pasemi_smb_pci_remove(struct pci_dev *dev) -{ - struct pasemi_smbus *smbus = pci_get_drvdata(dev); - - i2c_del_adapter(&smbus->adapter); - pci_iounmap(dev, smbus->ioaddr); - release_region(smbus->base, smbus->size); - kfree(smbus); } static const struct pci_device_id pasemi_smb_pci_ids[] = { @@ -90,7 +70,6 @@ static struct pci_driver pasemi_smb_pci_driver = { .name = "i2c-pasemi", .id_table = pasemi_smb_pci_ids, .probe = pasemi_smb_pci_probe, - .remove = pasemi_smb_pci_remove, }; module_pci_driver(pasemi_smb_pci_driver); From d88ae2932df0e670610cb741fec442ad12466c03 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:31 +0200 Subject: [PATCH 31/43] i2c: pasemi: Add Apple platform driver With all the previous preparations we can now finally add the platform driver to support the PASemi-based controllers in Apple SoCs. This does not work on the M1 yet but should work on the early iPhones already. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 11 ++ drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-pasemi-platform.c | 122 +++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 drivers/i2c/busses/i2c-pasemi-platform.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 1df19ccc310b..dce392839017 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -859,6 +859,17 @@ config I2C_PASEMI help Supports the PA Semi PWRficient on-chip SMBus interfaces. +config I2C_APPLE + tristate "Apple SMBus platform driver" + depends on ARCH_APPLE || COMPILE_TEST + default ARCH_APPLE + help + Say Y here if you want to use the I2C controller present on Apple + Silicon chips such as the M1. + + This driver can also be built as a module. If so, the module + will be called i2c-apple. + config I2C_PCA_PLATFORM tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 0ab1b4cb2228..d85899fef8c7 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -86,6 +86,8 @@ obj-$(CONFIG_I2C_OMAP) += i2c-omap.o obj-$(CONFIG_I2C_OWL) += i2c-owl.o i2c-pasemi-objs := i2c-pasemi-core.o i2c-pasemi-pci.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o +i2c-apple-objs := i2c-pasemi-core.o i2c-pasemi-platform.o +obj-$(CONFIG_I2C_APPLE) += i2c-apple.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o diff --git a/drivers/i2c/busses/i2c-pasemi-platform.c b/drivers/i2c/busses/i2c-pasemi-platform.c new file mode 100644 index 000000000000..88a54aaf7e3c --- /dev/null +++ b/drivers/i2c/busses/i2c-pasemi-platform.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 The Asahi Linux Contributors + * + * PA Semi PWRficient SMBus host driver for Apple SoCs + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-pasemi-core.h" + +struct pasemi_platform_i2c_data { + struct pasemi_smbus smbus; + struct clk *clk_ref; +}; + +static int +pasemi_platform_i2c_calc_clk_div(struct pasemi_platform_i2c_data *data, + u32 frequency) +{ + unsigned long clk_rate = clk_get_rate(data->clk_ref); + + if (!clk_rate) + return -EINVAL; + + data->smbus.clk_div = DIV_ROUND_UP(clk_rate, 16 * frequency); + if (data->smbus.clk_div < 4) + return dev_err_probe(data->smbus.dev, -EINVAL, + "Bus frequency %d is too fast.\n", + frequency); + if (data->smbus.clk_div > 0xff) + return dev_err_probe(data->smbus.dev, -EINVAL, + "Bus frequency %d is too slow.\n", + frequency); + + return 0; +} + +static int pasemi_platform_i2c_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pasemi_platform_i2c_data *data; + struct pasemi_smbus *smbus; + u32 frequency; + int error; + + data = devm_kzalloc(dev, sizeof(struct pasemi_platform_i2c_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + smbus = &data->smbus; + smbus->dev = dev; + + smbus->ioaddr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(smbus->ioaddr)) + return PTR_ERR(smbus->ioaddr); + + if (of_property_read_u32(dev->of_node, "clock-frequency", &frequency)) + frequency = I2C_MAX_STANDARD_MODE_FREQ; + + data->clk_ref = devm_clk_get(dev, NULL); + if (IS_ERR(data->clk_ref)) + return PTR_ERR(data->clk_ref); + + error = clk_prepare_enable(data->clk_ref); + if (error) + return error; + + error = pasemi_platform_i2c_calc_clk_div(data, frequency); + if (error) + goto out_clk_disable; + + smbus->adapter.dev.of_node = pdev->dev.of_node; + error = pasemi_i2c_common_probe(smbus); + if (error) + goto out_clk_disable; + + platform_set_drvdata(pdev, data); + + return 0; + +out_clk_disable: + clk_disable_unprepare(data->clk_ref); + + return error; +} + +static int pasemi_platform_i2c_remove(struct platform_device *pdev) +{ + struct pasemi_platform_i2c_data *data = platform_get_drvdata(pdev); + + clk_disable_unprepare(data->clk_ref); + return 0; +} + +static const struct of_device_id pasemi_platform_i2c_of_match[] = { + { .compatible = "apple,t8103-i2c" }, + { .compatible = "apple,i2c" }, + {}, +}; +MODULE_DEVICE_TABLE(of, pasemi_platform_i2c_of_match); + +static struct platform_driver pasemi_platform_i2c_driver = { + .driver = { + .name = "i2c-apple", + .of_match_table = pasemi_platform_i2c_of_match, + }, + .probe = pasemi_platform_i2c_probe, + .remove = pasemi_platform_i2c_remove, +}; +module_platform_driver(pasemi_platform_i2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sven Peter "); +MODULE_DESCRIPTION("Apple/PASemi SMBus platform driver"); From 3abdc89b5e309c63fa631de38cbec0755e5b2ee7 Mon Sep 17 00:00:00 2001 From: Sven Peter Date: Fri, 8 Oct 2021 18:35:32 +0200 Subject: [PATCH 32/43] i2c: pasemi: Set enable bit for Apple variant Some later revisions after the original PASemi I2C controller introduce what likely is an enable bit to the CTL register. Without setting it the actual i2c transmission is never started. Reviewed-by: Arnd Bergmann Signed-off-by: Sven Peter Acked-by: Olof Johansson Tested-by: Christian Zigotzky Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pasemi-core.c | 8 ++++++++ drivers/i2c/busses/i2c-pasemi-core.h | 3 +++ drivers/i2c/busses/i2c-pasemi-pci.c | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index 3d87b64dd9f7..4e161a4089d8 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -22,6 +22,7 @@ #define REG_MRXFIFO 0x04 #define REG_SMSTA 0x14 #define REG_CTL 0x1c +#define REG_REV 0x28 /* Register defs */ #define MTXFIFO_READ 0x00000400 @@ -37,6 +38,7 @@ #define CTL_MRR 0x00000400 #define CTL_MTR 0x00000200 +#define CTL_EN 0x00000800 #define CTL_CLK_M 0x000000ff static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) @@ -60,6 +62,9 @@ static void pasemi_reset(struct pasemi_smbus *smbus) { u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M)); + if (smbus->hw_rev >= 6) + val |= CTL_EN; + reg_write(smbus, REG_CTL, val); } @@ -335,6 +340,9 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) /* set up the sysfs linkage to our parent device */ smbus->adapter.dev.parent = smbus->dev; + if (smbus->hw_rev != PASEMI_HW_REV_PCI) + smbus->hw_rev = reg_read(smbus, REG_REV); + pasemi_reset(smbus); error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter); diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h index aca4e2da9089..4655124a37f3 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.h +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -8,11 +8,14 @@ #include #include +#define PASEMI_HW_REV_PCI -1 + struct pasemi_smbus { struct device *dev; struct i2c_adapter adapter; void __iomem *ioaddr; unsigned int clk_div; + int hw_rev; }; int pasemi_i2c_common_probe(struct pasemi_smbus *smbus); diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c index 4251e7b9f177..1ab1f28744fb 100644 --- a/drivers/i2c/busses/i2c-pasemi-pci.c +++ b/drivers/i2c/busses/i2c-pasemi-pci.c @@ -42,6 +42,12 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev, size = pci_resource_len(dev, 0); smbus->clk_div = CLK_100K_DIV; + /* + * The original PASemi PCI controllers don't have a register for + * their HW revision. + */ + smbus->hw_rev = PASEMI_HW_REV_PCI; + if (!devm_request_region(&dev->dev, base, size, pasemi_smb_pci_driver.name)) return -EBUSY; From 712d6617d0a29dc4d4da361247720cdf156ae7bb Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 23 Aug 2021 17:45:04 +0300 Subject: [PATCH 33/43] i2c: mlxcpld: Allow flexible polling time setting for I2C transactions Allow polling time setting according to I2C frequency supported across the system. For base frequency 400 KHz and 1 MHz set polling time is set four times less than for system with base frequency 100KHz. Signed-off-by: Vadim Pasternak Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mlxcpld.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index 615f0a98640e..56aa424fd71d 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -73,6 +73,7 @@ struct mlxcpld_i2c_priv { struct mlxcpld_i2c_curr_xfer xfer; struct device *dev; bool smbus_block; + int polling_time; }; static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr) @@ -267,8 +268,8 @@ static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv) do { if (!mlxcpld_i2c_check_busy(priv)) break; - usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME); - timeout += MLXCPLD_I2C_POLL_TIME; + usleep_range(priv->polling_time / 2, priv->polling_time); + timeout += priv->polling_time; } while (timeout <= MLXCPLD_I2C_XFER_TO); if (timeout > MLXCPLD_I2C_XFER_TO) @@ -288,10 +289,10 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv) u8 datalen, val; do { - usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME); + usleep_range(priv->polling_time / 2, priv->polling_time); if (!mlxcpld_i2c_check_status(priv, &status)) break; - timeout += MLXCPLD_I2C_POLL_TIME; + timeout += priv->polling_time; } while (status == 0 && timeout < MLXCPLD_I2C_XFER_TO); switch (status) { @@ -498,9 +499,11 @@ mlxcpld_i2c_set_frequency(struct mlxcpld_i2c_priv *priv, switch ((regval & data->mask) >> data->bit) { case MLXCPLD_I2C_FREQ_1000KHZ: freq = MLXCPLD_I2C_FREQ_1000KHZ_SET; + priv->polling_time /= 4; break; case MLXCPLD_I2C_FREQ_400KHZ: freq = MLXCPLD_I2C_FREQ_400KHZ_SET; + priv->polling_time /= 4; break; default: return 0; @@ -527,6 +530,7 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev) priv->dev = &pdev->dev; priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR; + priv->polling_time = MLXCPLD_I2C_POLL_TIME; /* Set I2C bus frequency if platform data provides this info. */ pdata = dev_get_platdata(&pdev->dev); From e3e4949e637d39321cc379ff73a60c26df6410bc Mon Sep 17 00:00:00 2001 From: Kewei Xu Date: Sun, 10 Oct 2021 15:05:12 +0800 Subject: [PATCH 34/43] i2c: mediatek: Reset the handshake signal between i2c and dma Due to changes in the hardware design of the handshaking signal between i2c and dma, it is necessary to reset the handshaking signal before each transfer to ensure that the multi-msgs can be transferred correctly. Signed-off-by: Kewei Xu Reviewed-by: Qii Wang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mt65xx.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 72acda59eb39..c06dbbf73f93 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,8 @@ #define I2C_RD_TRANAC_VALUE 0x0001 #define I2C_SCL_MIS_COMP_VALUE 0x0000 #define I2C_CHN_CLR_FLAG 0x0000 +#define I2C_RELIABILITY 0x0010 +#define I2C_DMAACK_ENABLE 0x0008 #define I2C_DMA_CON_TX 0x0000 #define I2C_DMA_CON_RX 0x0001 @@ -851,6 +854,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, u16 restart_flag = 0; u16 dma_sync = 0; u32 reg_4g_mode; + u32 reg_dma_reset; u8 *dma_rd_buf = NULL; u8 *dma_wr_buf = NULL; dma_addr_t rpaddr = 0; @@ -864,6 +868,28 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, reinit_completion(&i2c->msg_complete); + if (i2c->dev_comp->apdma_sync && + i2c->op != I2C_MASTER_WRRD && num > 1) { + mtk_i2c_writew(i2c, 0x00, OFFSET_DEBUGCTRL); + writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST, + i2c->pdmabase + OFFSET_RST); + + ret = readw_poll_timeout(i2c->pdmabase + OFFSET_RST, + reg_dma_reset, + !(reg_dma_reset & I2C_DMA_WARM_RST), + 0, 100); + if (ret) { + dev_err(i2c->dev, "DMA warm reset timeout\n"); + return -ETIMEDOUT; + } + + writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST); + mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST, OFFSET_SOFTRESET); + mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET); + mtk_i2c_writew(i2c, I2C_RELIABILITY | I2C_DMAACK_ENABLE, + OFFSET_DEBUGCTRL); + } + control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) & ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS); if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1)) From cc28e578f515f068cd8ee280706b8d8e31c472f9 Mon Sep 17 00:00:00 2001 From: Kewei Xu Date: Sun, 10 Oct 2021 15:05:13 +0800 Subject: [PATCH 35/43] i2c: mediatek: Dump i2c/dma register when a timeout occurs When a timeout error occurs in i2c transter, it is usually related to the i2c/dma IP hardware configuration. Therefore, the purpose of this patch is to dump the key register values of i2c/dma when a timeout occurs in i2c for debugging. Signed-off-by: Kewei Xu Reviewed-by: Qii Wang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mt65xx.c | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index c06dbbf73f93..9ea427f53083 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -130,6 +130,7 @@ enum I2C_REGS_OFFSET { OFFSET_HS, OFFSET_SOFTRESET, OFFSET_DCM_EN, + OFFSET_MULTI_DMA, OFFSET_PATH_DIR, OFFSET_DEBUGSTAT, OFFSET_DEBUGCTRL, @@ -197,6 +198,7 @@ static const u16 mt_i2c_regs_v2[] = { [OFFSET_TRANSFER_LEN_AUX] = 0x44, [OFFSET_CLOCK_DIV] = 0x48, [OFFSET_SOFTRESET] = 0x50, + [OFFSET_MULTI_DMA] = 0x8c, [OFFSET_SCL_MIS_COMP_POINT] = 0x90, [OFFSET_DEBUGSTAT] = 0xe4, [OFFSET_DEBUGCTRL] = 0xe8, @@ -845,6 +847,57 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk) return 0; } +static void i2c_dump_register(struct mtk_i2c *i2c) +{ + dev_dbg(i2c->dev, "SLAVE_ADDR: 0x%x, INTR_MASK: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_SLAVE_ADDR), + mtk_i2c_readw(i2c, OFFSET_INTR_MASK)); + dev_dbg(i2c->dev, "INTR_STAT: 0x%x, CONTROL: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_INTR_STAT), + mtk_i2c_readw(i2c, OFFSET_CONTROL)); + dev_dbg(i2c->dev, "TRANSFER_LEN: 0x%x, TRANSAC_LEN: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_TRANSFER_LEN), + mtk_i2c_readw(i2c, OFFSET_TRANSAC_LEN)); + dev_dbg(i2c->dev, "DELAY_LEN: 0x%x, HTIMING: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_DELAY_LEN), + mtk_i2c_readw(i2c, OFFSET_TIMING)); + dev_dbg(i2c->dev, "START: 0x%x, EXT_CONF: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_START), + mtk_i2c_readw(i2c, OFFSET_EXT_CONF)); + dev_dbg(i2c->dev, "HS: 0x%x, IO_CONFIG: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_HS), + mtk_i2c_readw(i2c, OFFSET_IO_CONFIG)); + dev_dbg(i2c->dev, "DCM_EN: 0x%x, TRANSFER_LEN_AUX: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_DCM_EN), + mtk_i2c_readw(i2c, OFFSET_TRANSFER_LEN_AUX)); + dev_dbg(i2c->dev, "CLOCK_DIV: 0x%x, FIFO_STAT: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_CLOCK_DIV), + mtk_i2c_readw(i2c, OFFSET_FIFO_STAT)); + dev_dbg(i2c->dev, "DEBUGCTRL : 0x%x, DEBUGSTAT: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_DEBUGCTRL), + mtk_i2c_readw(i2c, OFFSET_DEBUGSTAT)); + if (i2c->dev_comp->regs == mt_i2c_regs_v2) { + dev_dbg(i2c->dev, "LTIMING: 0x%x, MULTI_DMA: 0x%x\n", + mtk_i2c_readw(i2c, OFFSET_LTIMING), + mtk_i2c_readw(i2c, OFFSET_MULTI_DMA)); + } + dev_dbg(i2c->dev, "\nDMA_INT_FLAG: 0x%x, DMA_INT_EN: 0x%x\n", + readl(i2c->pdmabase + OFFSET_INT_FLAG), + readl(i2c->pdmabase + OFFSET_INT_EN)); + dev_dbg(i2c->dev, "DMA_EN: 0x%x, DMA_CON: 0x%x\n", + readl(i2c->pdmabase + OFFSET_EN), + readl(i2c->pdmabase + OFFSET_CON)); + dev_dbg(i2c->dev, "DMA_TX_MEM_ADDR: 0x%x, DMA_RX_MEM_ADDR: 0x%x\n", + readl(i2c->pdmabase + OFFSET_TX_MEM_ADDR), + readl(i2c->pdmabase + OFFSET_RX_MEM_ADDR)); + dev_dbg(i2c->dev, "DMA_TX_LEN: 0x%x, DMA_RX_LEN: 0x%x\n", + readl(i2c->pdmabase + OFFSET_TX_LEN), + readl(i2c->pdmabase + OFFSET_RX_LEN)); + dev_dbg(i2c->dev, "DMA_TX_4G_MODE: 0x%x, DMA_RX_4G_MODE: 0x%x", + readl(i2c->pdmabase + OFFSET_TX_4G_MODE), + readl(i2c->pdmabase + OFFSET_RX_4G_MODE)); +} + static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, int num, int left_num) { @@ -1075,6 +1128,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, if (ret == 0) { dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr); + i2c_dump_register(i2c); mtk_i2c_init_hw(i2c); return -ETIMEDOUT; } From 1ad5dc3540d8c621d1e15a6bff9c0ac30fba2857 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 26 Oct 2021 17:39:16 +0300 Subject: [PATCH 36/43] i2c: i801: Fix incorrect and needless software PEC disabling Commit a6b8bb6a813a ("i2c: i801: Fix handling SMBHSTCNT_PEC_EN") attempts to disable software PEC by clearing the SMBHSTCNT_PEC_EN (bit 7) in the SMBus Host Control register (I/O SMBHSTCNT) but incorrectly clears it in the PCI Host Configuration register (PCI SMBHSTCFG). This clearing is actually needless since after above commit the SMBHSTCNT_PEC_EN is never set and the register is initialized with known values. Signed-off-by: Jarkko Nikula Acked-by: Heiner Kallweit Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 115660dce722..b6048a571543 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1657,7 +1657,6 @@ static void i801_setup_hstcfg(struct i801_priv *priv) unsigned char hstcfg = priv->original_hstcfg; hstcfg &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ - hstcfg &= ~SMBHSTCNT_PEC_EN; /* Disable software PEC */ hstcfg |= SMBHSTCFG_HST_EN; pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg); } From ef3fe574d49eda31e1d13bfbd19da64b46fb004e Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Oct 2021 02:29:19 +0300 Subject: [PATCH 37/43] i2c: tegra: Ensure that device is suspended before driver is removed Tegra I2C device isn't guaranteed to be suspended after removal of the driver since driver uses pm_runtime_put() that is asynchronous and pm_runtime_disable() cancels pending power-change requests. This means that potentially refcount of the clocks may become unbalanced after removal of the driver. This a very minor problem which unlikely to happen in practice and won't cause any visible problems, nevertheless let's replace pm_runtime_disable() with pm_runtime_force_suspend() and use pm_runtime_put_sync() which disables RPM of the device and puts it into suspend before driver is removed. Signed-off-by: Dmitry Osipenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c883044715f3..b3184c422826 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -1700,7 +1700,7 @@ static int tegra_i2c_init_hardware(struct tegra_i2c_dev *i2c_dev) else ret = tegra_i2c_init(i2c_dev); - pm_runtime_put(i2c_dev->dev); + pm_runtime_put_sync(i2c_dev->dev); return ret; } @@ -1819,7 +1819,7 @@ static int tegra_i2c_remove(struct platform_device *pdev) struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adapter); - pm_runtime_disable(i2c_dev->dev); + pm_runtime_force_suspend(i2c_dev->dev); tegra_i2c_release_dma(i2c_dev); tegra_i2c_release_clocks(i2c_dev); From 8e98c4f5c38b253adeefc3dc62d447f1fb973c77 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 24 Oct 2021 22:03:13 -0700 Subject: [PATCH 38/43] i2c: qup: fix a trivial typo Correct the typo of "reamining" to "remaining". Signed-off-by: Randy Dunlap Suggested-by: Matthew Wilcox Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-qup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index fcd35e8de83c..95e7c4491f09 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1290,7 +1290,7 @@ static void qup_i2c_write_rx_tags_v2(struct qup_i2c_dev *qup) * 1. Check if tx_tags_sent is false i.e. the start of QUP block so write the * tags to TX FIFO and set tx_tags_sent to true. * 2. Check if send_last_word is true. It will be set when last few data bytes - * (less than 4 bytes) are reamining to be written in FIFO because of no FIFO + * (less than 4 bytes) are remaining to be written in FIFO because of no FIFO * space. All this data bytes are available in tx_fifo_data so write this * in FIFO. * 3. Write the data to TX FIFO and check for cur_blk_len. If it is non zero From 5fe058b04d017a91cd1fa9281c57d0c3d3a34f58 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Fri, 19 Mar 2021 11:29:31 +0800 Subject: [PATCH 39/43] i2c: qup: move to use request_irq by IRQF_NO_AUTOEN flag disable_irq() after request_irq() still has a time gap in which interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will disable IRQ auto-enable because of requesting. Signed-off-by: Tian Tao Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-qup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 95e7c4491f09..69e9f3ecf87d 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1797,12 +1797,12 @@ nodma: goto fail; ret = devm_request_irq(qup->dev, qup->irq, qup_i2c_interrupt, - IRQF_TRIGGER_HIGH, "i2c_qup", qup); + IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, + "i2c_qup", qup); if (ret) { dev_err(qup->dev, "Request %d IRQ failed\n", qup->irq); goto fail; } - disable_irq(qup->irq); hw_ver = readl(qup->base + QUP_HW_VERSION); dev_dbg(qup->dev, "Revision %x\n", hw_ver); From 7f98960c046ee1136e7096aee168eda03aef8a5d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 19 Aug 2021 22:48:08 +0200 Subject: [PATCH 40/43] i2c: xlr: Fix a resource leak in the error handling path of 'xlr_i2c_probe()' A successful 'clk_prepare()' call should be balanced by a corresponding 'clk_unprepare()' call in the error handling path of the probe, as already done in the remove function. More specifically, 'clk_prepare_enable()' is used, but 'clk_disable()' is also already called. So just the unprepare step has still to be done. Update the error handling path accordingly. Fixes: 75d31c2372e4 ("i2c: xlr: add support for Sigma Designs controller variant") Signed-off-by: Christophe JAILLET Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-xlr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c index 126d1393e548..9ce20652d494 100644 --- a/drivers/i2c/busses/i2c-xlr.c +++ b/drivers/i2c/busses/i2c-xlr.c @@ -431,11 +431,15 @@ static int xlr_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&priv->adap, priv); ret = i2c_add_numbered_adapter(&priv->adap); if (ret < 0) - return ret; + goto err_unprepare_clk; platform_set_drvdata(pdev, priv); dev_info(&priv->adap.dev, "Added I2C Bus.\n"); return 0; + +err_unprepare_clk: + clk_unprepare(clk); + return ret; } static int xlr_i2c_remove(struct platform_device *pdev) From 408ef353e1f96fbd2582cb94756711ea87537386 Mon Sep 17 00:00:00 2001 From: Jie Deng Date: Mon, 1 Nov 2021 13:24:50 +0800 Subject: [PATCH 41/43] i2c: virtio: update the maintainer to Conghui Due to changes in my work, I'm passing the virtio-i2c driver maintenance to Conghui. Signed-off-by: Jie Deng Acked-by: Michael S. Tsirkin Acked-by: Viresh Kumar Signed-off-by: Wolfram Sang --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a4a0c2baaf27..d5ca02ef2a74 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19932,7 +19932,7 @@ F: include/uapi/linux/virtio_snd.h F: sound/virtio/* VIRTIO I2C DRIVER -M: Jie Deng +M: Conghui Chen M: Viresh Kumar L: linux-i2c@vger.kernel.org L: virtualization@lists.linux-foundation.org From 76eb4db611e1012cbdc2461540fe6bb9d40a0f27 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 1 Oct 2021 20:21:54 +0300 Subject: [PATCH 42/43] i2c: i801: Add support for Intel Ice Lake PCH-N Add PCI ID of SMBus controller on Intel Ice Lake PCH-N. The device can be found on MacBookPro16,2 [1]. [1]: https://linux-hardware.org/?probe=f1c5cf0c43 Signed-off-by: Andy Shevchenko Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index b6048a571543..05187457f88a 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -64,6 +64,7 @@ * Cannon Lake-LP (PCH) 0x9da3 32 hard yes yes yes * Cedar Fork (PCH) 0x18df 32 hard yes yes yes * Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes + * Ice Lake-N (PCH) 0x38a3 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 @@ -218,6 +219,7 @@ #define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0 #define PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS 0x31d4 #define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS 0x34a3 +#define PCI_DEVICE_ID_INTEL_ICELAKE_N_SMBUS 0x38a3 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS 0x43a3 #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 @@ -1042,6 +1044,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS) }, { 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_ICELAKE_N_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_COMETLAKE_V_SMBUS) }, @@ -1701,6 +1704,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) case PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_CDF_SMBUS: case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: + case PCI_DEVICE_ID_INTEL_ICELAKE_N_SMBUS: case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS: case PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS: case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS: From c6f49acb52c79f8e84af2eda4fc002a2068a6c9e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 13 Oct 2021 18:09:39 +0200 Subject: [PATCH 43/43] i2c: amd-mp2-plat: ACPI: Use ACPI_COMPANION() directly The ACPI_HANDLE() macro is a wrapper arond the ACPI_COMPANION() macro and the ACPI handle produced by the former comes from the ACPI device object produced by the latter, so it is way more straightforward to evaluate the latter directly instead of passing the handle produced by the former to acpi_bus_get_device(). Modify i2c_amd_probe() accordingly (no intentional functional impact). Signed-off-by: Rafael J. Wysocki Acked-by: Shyam Sundar S K Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-amd-mp2-plat.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c index de058671f9b8..84b7e6cbc67b 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-plat.c +++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c @@ -246,12 +246,11 @@ static int i2c_amd_probe(struct platform_device *pdev) { int ret; struct amd_i2c_dev *i2c_dev; - acpi_handle handle = ACPI_HANDLE(&pdev->dev); - struct acpi_device *adev; + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); struct amd_mp2_dev *mp2_dev; const char *uid; - if (acpi_bus_get_device(handle, &adev)) + if (!adev) return -ENODEV; /* The ACPI namespace doesn't contain information about which MP2 PCI