i2c: designware: Add doorbell support for Mendocino
authorMario Limonciello <mario.limonciello@amd.com>
Fri, 14 Apr 2023 14:40:08 +0000 (09:40 -0500)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 20 Apr 2023 10:20:05 +0000 (18:20 +0800)
Mendocino and later platform don't use the platform feature mailbox for
communication for I2C arbitration, they rely upon ringing a doorbell.

Detect the platform by the device ID of the root port and choose the
appropriate method.

Link: https://lore.kernel.org/linux-i2c/20220916131854.687371-3-jsd@semihalf.com/
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Reviewed-by: Mark Hasemeyer <markhas@chromium.org>
Tested-by: Mark Hasemeyer <markhas@chromium.org>
Acked-by: Wolfram Sang <wsa@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-designware-amdpsp.c

index 89f8b75043d0ab52a6b9a86e2e2618b20e185501..4b4323bbf268d5f1991c5178d058b5ffe428a865 100644 (file)
@@ -568,6 +568,7 @@ config I2C_DESIGNWARE_AMDPSP
        bool "AMD PSP I2C semaphore support"
        depends on ACPI
        depends on CRYPTO_DEV_SP_PSP
+       depends on PCI
        depends on I2C_DESIGNWARE_PLATFORM
        depends on (I2C_DESIGNWARE_PLATFORM=y && CRYPTO_DEV_CCP_DD=y) || \
                   (I2C_DESIGNWARE_PLATFORM=m && CRYPTO_DEV_CCP_DD)
index 12870dc44bdbd0e469baff664c14dfceb5319e1a..63454b06e5da17b648c6db3e28d4a6b76b2977f0 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include <linux/i2c.h>
+#include <linux/pci.h>
 #include <linux/psp-platform-access.h>
 #include <linux/psp.h>
 #include <linux/workqueue.h>
@@ -32,6 +33,8 @@ static u32 psp_i2c_access_count;
 static bool psp_i2c_mbox_fail;
 static struct device *psp_i2c_dev;
 
+static int (*_psp_send_i2c_req)(struct psp_i2c_req *req);
+
 /* Helper to verify status returned by PSP */
 static int check_i2c_req_sts(struct psp_i2c_req *req)
 {
@@ -72,6 +75,17 @@ static int psp_send_i2c_req_cezanne(struct psp_i2c_req *req)
        return ret;
 }
 
+static int psp_send_i2c_req_doorbell(struct psp_i2c_req *req)
+{
+       int ret;
+
+       ret = psp_ring_platform_doorbell(req->type, &req->hdr.status);
+       if (ret == -EIO)
+               return check_i2c_req_sts(req);
+
+       return ret;
+}
+
 static int psp_send_i2c_req(enum psp_i2c_req_type i2c_req_type)
 {
        struct psp_i2c_req *req;
@@ -87,7 +101,7 @@ static int psp_send_i2c_req(enum psp_i2c_req_type i2c_req_type)
        req->type = i2c_req_type;
 
        start = jiffies;
-       ret = read_poll_timeout(psp_send_i2c_req_cezanne, status,
+       ret = read_poll_timeout(_psp_send_i2c_req, status,
                                (status != -EBUSY),
                                PSP_I2C_REQ_RETRY_DELAY_US,
                                PSP_I2C_REQ_RETRY_CNT * PSP_I2C_REQ_RETRY_DELAY_US,
@@ -262,6 +276,8 @@ static const struct i2c_lock_operations i2c_dw_psp_lock_ops = {
 
 int i2c_dw_amdpsp_probe_lock_support(struct dw_i2c_dev *dev)
 {
+       struct pci_dev *rdev;
+
        if (!IS_REACHABLE(CONFIG_CRYPTO_DEV_CCP_DD))
                return -ENODEV;
 
@@ -275,6 +291,14 @@ int i2c_dw_amdpsp_probe_lock_support(struct dw_i2c_dev *dev)
        if (psp_i2c_dev)
                return -EEXIST;
 
+       /* Cezanne uses platform mailbox, Mendocino and later use doorbell */
+       rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
+       if (rdev->device == 0x1630)
+               _psp_send_i2c_req = psp_send_i2c_req_cezanne;
+       else
+               _psp_send_i2c_req = psp_send_i2c_req_doorbell;
+       pci_dev_put(rdev);
+
        if (psp_check_platform_access_status())
                return -EPROBE_DEFER;