--- zzzz-none-000/linux-5.15.111/drivers/i2c/busses/i2c-designware-common.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/drivers/i2c/busses/i2c-designware-common.c 2024-02-07 10:23:01.000000000 +0000 @@ -144,10 +144,20 @@ if (dev->map) return 0; - ret = i2c_dw_acquire_lock(dev); - if (ret) - return ret; - + /* + * acquire_ownership may disable local irq. + * So release it first and do operations that might sleep. + */ + if (dev->shared_host && dev->release_ownership) + dev->release_ownership(); + if (dev->shared_host && dev->acquire_ownership) { + ret = dev->acquire_ownership(); + if (ret < 0) { + dev_WARN(dev->dev, "%s couldn't acquire ownership\n", + __func__); + return ret; + } + } reg = readl(dev->base + DW_IC_COMP_TYPE); i2c_dw_release_lock(dev); @@ -213,6 +223,22 @@ #ifdef CONFIG_ACPI #include +#include + +int dw_i2c_acquire_ownership(void) +{ +#ifdef CONFIG_GMIN_INTEL_MID + return intel_mid_dw_i2c_acquire_ownership(); +#endif + return 0; +} +int dw_i2c_release_ownership(void) +{ +#ifdef CONFIG_GMIN_INTEL_MID + return intel_mid_dw_i2c_release_ownership(); +#endif + return 0; +} /* * The HCNT/LCNT information coming from ACPI should be the most accurate @@ -260,6 +286,9 @@ struct dw_i2c_dev *dev = dev_get_drvdata(device); struct i2c_timings *t = &dev->timings; u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0; + acpi_status status; + acpi_handle handle = ACPI_HANDLE(device); + unsigned long long shared_host = 0; /* * Try to get SDA hold time and *CNT values from an ACPI method for @@ -286,6 +315,18 @@ break; } + status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host); + if (ACPI_SUCCESS(status)) + dev_info(device, "_SEM=%llu\n", shared_host); + if (shared_host != 0) { + dev_info(device, "Share controller with PUNIT\n"); + dev->shared_host = 1; + dev->polling = 1; + dev->acquire_ownership = dw_i2c_acquire_ownership; + dev->release_ownership = dw_i2c_release_ownership; + dev->shared_with_punit = true; + } + return 0; } EXPORT_SYMBOL_GPL(i2c_dw_acpi_configure); @@ -394,10 +435,14 @@ u32 reg; int ret; - ret = i2c_dw_acquire_lock(dev); - if (ret) - return ret; - + /* if the host is shared between other units on the SoC */ + if (dev->shared_host && dev->acquire_ownership) { + ret = dev->acquire_ownership(); + if (ret < 0) { + dev_WARN(dev->dev, "couldnt acquire ownership\n"); + return ret; + } + } /* Configure SDA Hold Time if required */ ret = regmap_read(dev->map, DW_IC_COMP_VERSION, ®); if (ret) @@ -459,7 +504,10 @@ * transfer supported by the driver (for 400KHz this is * 25us) as described in the DesignWare I2C databook. */ - usleep_range(25, 250); + if (dev->polling) + udelay(25); + else + usleep_range(25, 250); } while (timeout--); dev_warn(dev->dev, "timeout in disabling adapter\n"); @@ -500,6 +548,7 @@ } EXPORT_SYMBOL_GPL(i2c_dw_prepare_clk); +#if 0 int i2c_dw_acquire_lock(struct dw_i2c_dev *dev) { int ret; @@ -515,6 +564,7 @@ return ret; } +#endif void i2c_dw_release_lock(struct dw_i2c_dev *dev) {