mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 11:06:41 -05:00
Merge tag 'i2c-for-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"Mostly DT bindings additions this time because Andi was super busy and
I also could only partly cover it.
- new ids for qcom-cci, mt65xx, exynos5, apple, tegra20, k1, i801
- drop support for already removed S3C2410
- introduce and use fwnode_for_each_child_node_scoped()
- mmt65xx: improve write-then-read transactions
- k1: various fixes around bus errors and resets
- usual share of cleanups, minor improvements, PM fixes...
at24 updates:
- add the compatible for Giantec GT24C256C to the device-tree
bindings"
* tag 'i2c-for-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (33 commits)
i2c: i801: Add support for Intel Wildcat Lake-U
dt-bindings: i2c: i2c-mt65xx: Add MediaTek MT8196/6991 compatibles
i2c: designware: Add disabling clocks when probe fails
i2c: designware: Fix clock issue when PM is disabled
i2c: busses: Fix some spelling errors
i2c: mux: Simplify boolean assignment in i2c_mux_alloc
i2c: designware: use dev_err_probe() when probing platform device
i2c: designware: convert to dev_err_probe() on request IRQ error
i2c: spacemit: ensure SDA is released after bus reset
i2c: spacemit: check SDA instead of SCL after bus reset
i2c: spacemit: disable SDA glitch fix to avoid restart delay
i2c: spacemit: remove stop function to avoid bus error
i2c: spacemit: ensure bus release check runs when wait_bus_idle() fails
i2c: mediatek: fix potential incorrect use of I2C_MASTER_WRRD
i2c: boardinfo: Annotate code used in init phase only
dt-bindings: i2c: i2c-mt65xx: Document MediaTek MT6878 I2C
dt-bindings: i2c: samsung,s3c2410-i2c: Drop S3C2410
i2c: s3c2410: Drop S3C2410 OF support
dt-bindings: i2c: spacemit,k1-i2c: Minor whitespace cleanup in example
dt-bindings: i2c: exynos5: add samsung,exynos8890-hsi2c compatible
...
This commit is contained in:
@@ -143,6 +143,7 @@ properties:
|
||||
- const: atmel,24c128
|
||||
- items:
|
||||
- enum:
|
||||
- giantec,gt24c256c
|
||||
- puya,p24c256c
|
||||
- const: atmel,24c256
|
||||
- items:
|
||||
|
||||
@@ -20,17 +20,22 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- apple,s5l8960x-i2c
|
||||
- apple,t7000-i2c
|
||||
- apple,s8000-i2c
|
||||
- apple,t8010-i2c
|
||||
- apple,t8015-i2c
|
||||
- apple,t8103-i2c
|
||||
- apple,t8112-i2c
|
||||
- apple,t6000-i2c
|
||||
- const: apple,i2c
|
||||
oneOf:
|
||||
- items:
|
||||
- const: apple,t6020-i2c
|
||||
- const: apple,t8103-i2c
|
||||
- items:
|
||||
- enum:
|
||||
# Do not add additional SoC to this list.
|
||||
- apple,s5l8960x-i2c
|
||||
- apple,t7000-i2c
|
||||
- apple,s8000-i2c
|
||||
- apple,t8010-i2c
|
||||
- apple,t8015-i2c
|
||||
- apple,t8103-i2c
|
||||
- apple,t8112-i2c
|
||||
- apple,t6000-i2c
|
||||
- const: apple,i2c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -33,11 +33,16 @@ properties:
|
||||
- samsung,exynos7870-hsi2c
|
||||
- tesla,fsd-hsi2c
|
||||
- const: samsung,exynos7-hsi2c
|
||||
- items:
|
||||
- enum:
|
||||
- samsung,exynos8890-hsi2c
|
||||
- const: samsung,exynos8895-hsi2c
|
||||
- items:
|
||||
- enum:
|
||||
- google,gs101-hsi2c
|
||||
- samsung,exynos2200-hsi2c
|
||||
- samsung,exynos850-hsi2c
|
||||
- samsung,exynos990-hsi2c
|
||||
- const: samsung,exynosautov9-hsi2c
|
||||
- const: samsung,exynos5-hsi2c # Exynos5250 and Exynos5420
|
||||
deprecated: true
|
||||
|
||||
@@ -50,6 +50,12 @@ properties:
|
||||
- enum:
|
||||
- mediatek,mt6795-i2c
|
||||
- const: mediatek,mt8173-i2c
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt6878-i2c
|
||||
- mediatek,mt6991-i2c
|
||||
- mediatek,mt8196-i2c
|
||||
- const: mediatek,mt8188-i2c
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt6893-i2c
|
||||
|
||||
@@ -80,6 +80,11 @@ properties:
|
||||
support for 64 KiB transactions whereas earlier chips supported no
|
||||
more than 4 KiB per transactions.
|
||||
const: nvidia,tegra194-i2c
|
||||
- description: |
|
||||
Tegra256 has 8 generic I2C controllers. The controllers are similar to
|
||||
the previous generations, but have a different parent clock and hence
|
||||
the timing parameters are configured differently.
|
||||
const: nvidia,tegra256-i2c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -186,6 +191,7 @@ allOf:
|
||||
contains:
|
||||
enum:
|
||||
- nvidia,tegra194-i2c
|
||||
- nvidia,tegra256-i2c
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
|
||||
@@ -25,6 +25,8 @@ properties:
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,qcm2290-cci
|
||||
- qcom,sa8775p-cci
|
||||
- qcom,sc7280-cci
|
||||
- qcom,sc8280xp-cci
|
||||
- qcom,sdm670-cci
|
||||
@@ -44,11 +46,11 @@ properties:
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
minItems: 2
|
||||
maxItems: 6
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
minItems: 2
|
||||
maxItems: 6
|
||||
|
||||
interrupts:
|
||||
@@ -113,6 +115,7 @@ allOf:
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
@@ -120,6 +123,22 @@ allOf:
|
||||
- const: cci_ahb
|
||||
- const: cci
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,qcm2290-cci
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
items:
|
||||
- const: ahb
|
||||
- const: cci
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@@ -223,6 +242,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sa8775p-cci
|
||||
- qcom,sm8550-cci
|
||||
- qcom,sm8650-cci
|
||||
- qcom,x1e80100-cci
|
||||
|
||||
@@ -13,7 +13,6 @@ properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- samsung,s3c2410-i2c
|
||||
- samsung,s3c2440-i2c
|
||||
# For s3c2440-like I2C used inside HDMIPHY block found on several SoCs:
|
||||
- samsung,s3c2440-hdmiphy-i2c
|
||||
@@ -93,7 +92,6 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- samsung,s3c2410-i2c
|
||||
- samsung,s3c2440-i2c
|
||||
- samsung,s3c2440-hdmiphy-i2c
|
||||
then:
|
||||
|
||||
@@ -56,7 +56,7 @@ examples:
|
||||
reg = <0xd4010800 0x38>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <36>;
|
||||
clocks =<&ccu 32>, <&ccu 84>;
|
||||
clocks = <&ccu 32>, <&ccu 84>;
|
||||
clock-names = "func", "bus";
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
||||
@@ -50,6 +50,7 @@ Supported adapters:
|
||||
* Intel Birch Stream (SOC)
|
||||
* Intel Arrow Lake (SOC)
|
||||
* Intel Panther Lake (SOC)
|
||||
* Intel Wildcat Lake (SOC)
|
||||
|
||||
Datasheets: Publicly available at the Intel website
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ config I2C_I801
|
||||
Birch Stream (SOC)
|
||||
Arrow Lake (SOC)
|
||||
Panther Lake (SOC)
|
||||
Wildcat Lake (SOC)
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-i801.
|
||||
|
||||
@@ -1068,11 +1068,10 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
|
||||
if (!(dev->flags & ACCESS_POLLING)) {
|
||||
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr,
|
||||
irq_flags, dev_name(dev->dev), dev);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "failure requesting irq %i: %d\n",
|
||||
dev->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev->dev, ret,
|
||||
"failure requesting irq %i: %d\n",
|
||||
dev->irq, ret);
|
||||
}
|
||||
|
||||
ret = i2c_dw_init_recovery_info(dev);
|
||||
|
||||
@@ -238,7 +238,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
||||
|
||||
dev->rst = devm_reset_control_get_optional_exclusive(device, NULL);
|
||||
if (IS_ERR(dev->rst))
|
||||
return PTR_ERR(dev->rst);
|
||||
return dev_err_probe(device, PTR_ERR(dev->rst), "failed to acquire reset\n");
|
||||
|
||||
reset_control_deassert(dev->rst);
|
||||
|
||||
@@ -247,21 +247,23 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
||||
goto exit_reset;
|
||||
|
||||
ret = i2c_dw_probe_lock_support(dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
ret = dev_err_probe(device, ret, "failed to probe lock support\n");
|
||||
goto exit_reset;
|
||||
}
|
||||
|
||||
i2c_dw_configure(dev);
|
||||
|
||||
/* Optional interface clock */
|
||||
dev->pclk = devm_clk_get_optional(device, "pclk");
|
||||
if (IS_ERR(dev->pclk)) {
|
||||
ret = PTR_ERR(dev->pclk);
|
||||
ret = dev_err_probe(device, PTR_ERR(dev->pclk), "failed to acquire pclk\n");
|
||||
goto exit_reset;
|
||||
}
|
||||
|
||||
dev->clk = devm_clk_get_optional(device, NULL);
|
||||
if (IS_ERR(dev->clk)) {
|
||||
ret = PTR_ERR(dev->clk);
|
||||
ret = dev_err_probe(device, PTR_ERR(dev->clk), "failed to acquire clock\n");
|
||||
goto exit_reset;
|
||||
}
|
||||
|
||||
@@ -314,6 +316,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
||||
|
||||
exit_probe:
|
||||
dw_i2c_plat_pm_cleanup(dev);
|
||||
i2c_dw_prepare_clk(dev, false);
|
||||
exit_reset:
|
||||
reset_control_assert(dev->rst);
|
||||
return ret;
|
||||
@@ -331,9 +334,11 @@ static void dw_i2c_plat_remove(struct platform_device *pdev)
|
||||
i2c_dw_disable(dev);
|
||||
|
||||
pm_runtime_dont_use_autosuspend(device);
|
||||
pm_runtime_put_sync(device);
|
||||
pm_runtime_put_noidle(device);
|
||||
dw_i2c_plat_pm_cleanup(dev);
|
||||
|
||||
i2c_dw_prepare_clk(dev, false);
|
||||
|
||||
i2c_dw_remove_lock_support(dev);
|
||||
|
||||
reset_control_assert(dev->rst);
|
||||
|
||||
@@ -266,11 +266,10 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
|
||||
|
||||
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr_slave,
|
||||
IRQF_SHARED, dev_name(dev->dev), dev);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "failure requesting IRQ %i: %d\n",
|
||||
dev->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev->dev, ret,
|
||||
"failure requesting IRQ %i: %d\n",
|
||||
dev->irq, ret);
|
||||
|
||||
ret = i2c_add_numbered_adapter(adap);
|
||||
if (ret)
|
||||
|
||||
@@ -339,7 +339,7 @@ static int hix5hd2_i2c_xfer_msg(struct hix5hd2_i2c_priv *priv,
|
||||
ret = priv->state;
|
||||
|
||||
/*
|
||||
* If this is the last message to be transfered (stop == 1)
|
||||
* If this is the last message to be transferred (stop == 1)
|
||||
* Then check if the bus can be brought back to idle.
|
||||
*/
|
||||
if (priv->state == HIX5I2C_STAT_RW_SUCCESS && stop)
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
* Arrow Lake-H (SOC) 0x7722 32 hard yes yes yes
|
||||
* Panther Lake-H (SOC) 0xe322 32 hard yes yes yes
|
||||
* Panther Lake-P (SOC) 0xe422 32 hard yes yes yes
|
||||
* Wildcat Lake-U (SOC) 0x4d22 32 hard yes yes yes
|
||||
*
|
||||
* Features supported by this driver:
|
||||
* Software PEC no
|
||||
@@ -236,6 +237,7 @@
|
||||
#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
|
||||
#define PCI_DEVICE_ID_INTEL_WILDCAT_LAKE_U_SMBUS 0x4d22
|
||||
#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3
|
||||
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3
|
||||
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3
|
||||
@@ -1056,6 +1058,7 @@ static const struct pci_device_id i801_ids[] = {
|
||||
{ PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, WILDCAT_LAKE_U_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Copyright (C) 2024-2025 Troy Mitchell <troymitchell988@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iopoll.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
#define SPACEMIT_ICR 0x0 /* Control register */
|
||||
#define SPACEMIT_ISR 0x4 /* Status register */
|
||||
#define SPACEMIT_IDBR 0xc /* Data buffer register */
|
||||
#define SPACEMIT_IRCR 0x18 /* Reset cycle counter */
|
||||
#define SPACEMIT_IBMR 0x1c /* Bus monitor register */
|
||||
|
||||
/* SPACEMIT_ICR register fields */
|
||||
@@ -25,7 +27,8 @@
|
||||
#define SPACEMIT_CR_MODE_FAST BIT(8) /* bus mode (master operation) */
|
||||
/* Bit 9 is reserved */
|
||||
#define SPACEMIT_CR_UR BIT(10) /* unit reset */
|
||||
/* Bits 11-12 are reserved */
|
||||
#define SPACEMIT_CR_RSTREQ BIT(11) /* i2c bus reset request */
|
||||
/* Bit 12 is reserved */
|
||||
#define SPACEMIT_CR_SCLE BIT(13) /* master clock enable */
|
||||
#define SPACEMIT_CR_IUE BIT(14) /* unit enable */
|
||||
/* Bits 15-17 are reserved */
|
||||
@@ -76,6 +79,10 @@
|
||||
SPACEMIT_SR_GCAD | SPACEMIT_SR_IRF | SPACEMIT_SR_ITE | \
|
||||
SPACEMIT_SR_ALD)
|
||||
|
||||
#define SPACEMIT_RCR_SDA_GLITCH_NOFIX BIT(7) /* bypass the SDA glitch fix */
|
||||
/* the cycles of SCL during bus reset */
|
||||
#define SPACEMIT_RCR_FIELD_RST_CYC GENMASK(3, 0)
|
||||
|
||||
/* SPACEMIT_IBMR register fields */
|
||||
#define SPACEMIT_BMR_SDA BIT(0) /* SDA line level */
|
||||
#define SPACEMIT_BMR_SCL BIT(1) /* SCL line level */
|
||||
@@ -88,6 +95,8 @@
|
||||
|
||||
#define SPACEMIT_SR_ERR (SPACEMIT_SR_BED | SPACEMIT_SR_RXOV | SPACEMIT_SR_ALD)
|
||||
|
||||
#define SPACEMIT_BUS_RESET_CLK_CNT_MAX 9
|
||||
|
||||
enum spacemit_i2c_state {
|
||||
SPACEMIT_STATE_IDLE,
|
||||
SPACEMIT_STATE_START,
|
||||
@@ -160,6 +169,7 @@ static int spacemit_i2c_handle_err(struct spacemit_i2c_dev *i2c)
|
||||
static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
|
||||
{
|
||||
u32 status;
|
||||
u8 clk_cnt;
|
||||
|
||||
/* if bus is locked, reset unit. 0: locked */
|
||||
status = readl(i2c->base + SPACEMIT_IBMR);
|
||||
@@ -169,9 +179,21 @@ static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
|
||||
spacemit_i2c_reset(i2c);
|
||||
usleep_range(10, 20);
|
||||
|
||||
/* check scl status again */
|
||||
for (clk_cnt = 0; clk_cnt < SPACEMIT_BUS_RESET_CLK_CNT_MAX; clk_cnt++) {
|
||||
status = readl(i2c->base + SPACEMIT_IBMR);
|
||||
if (status & SPACEMIT_BMR_SDA)
|
||||
return;
|
||||
|
||||
/* There's nothing left to save here, we are about to exit */
|
||||
writel(FIELD_PREP(SPACEMIT_RCR_FIELD_RST_CYC, 1),
|
||||
i2c->base + SPACEMIT_IRCR);
|
||||
writel(SPACEMIT_CR_RSTREQ, i2c->base + SPACEMIT_ICR);
|
||||
usleep_range(20, 30);
|
||||
}
|
||||
|
||||
/* check sda again here */
|
||||
status = readl(i2c->base + SPACEMIT_IBMR);
|
||||
if (!(status & SPACEMIT_BMR_SCL))
|
||||
if (!(status & SPACEMIT_BMR_SDA))
|
||||
dev_warn_ratelimited(i2c->dev, "unit reset failed\n");
|
||||
}
|
||||
|
||||
@@ -237,6 +259,14 @@ static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c)
|
||||
val |= SPACEMIT_CR_MSDE | SPACEMIT_CR_MSDIE;
|
||||
|
||||
writel(val, i2c->base + SPACEMIT_ICR);
|
||||
|
||||
/*
|
||||
* The glitch fix in the K1 I2C controller introduces a delay
|
||||
* on restart signals, so we disable the fix here.
|
||||
*/
|
||||
val = readl(i2c->base + SPACEMIT_IRCR);
|
||||
val |= SPACEMIT_RCR_SDA_GLITCH_NOFIX;
|
||||
writel(val, i2c->base + SPACEMIT_IRCR);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -267,19 +297,6 @@ static void spacemit_i2c_start(struct spacemit_i2c_dev *i2c)
|
||||
writel(val, i2c->base + SPACEMIT_ICR);
|
||||
}
|
||||
|
||||
static void spacemit_i2c_stop(struct spacemit_i2c_dev *i2c)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(i2c->base + SPACEMIT_ICR);
|
||||
val |= SPACEMIT_CR_STOP | SPACEMIT_CR_ALDIE | SPACEMIT_CR_TB;
|
||||
|
||||
if (i2c->read)
|
||||
val |= SPACEMIT_CR_ACKNAK;
|
||||
|
||||
writel(val, i2c->base + SPACEMIT_ICR);
|
||||
}
|
||||
|
||||
static int spacemit_i2c_xfer_msg(struct spacemit_i2c_dev *i2c)
|
||||
{
|
||||
unsigned long time_left;
|
||||
@@ -412,7 +429,6 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
|
||||
|
||||
val = readl(i2c->base + SPACEMIT_ICR);
|
||||
val &= ~(SPACEMIT_CR_TB | SPACEMIT_CR_ACKNAK | SPACEMIT_CR_STOP | SPACEMIT_CR_START);
|
||||
writel(val, i2c->base + SPACEMIT_ICR);
|
||||
|
||||
switch (i2c->state) {
|
||||
case SPACEMIT_STATE_START:
|
||||
@@ -429,14 +445,16 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
|
||||
}
|
||||
|
||||
if (i2c->state != SPACEMIT_STATE_IDLE) {
|
||||
val |= SPACEMIT_CR_TB | SPACEMIT_CR_ALDIE;
|
||||
|
||||
if (spacemit_i2c_is_last_msg(i2c)) {
|
||||
/* trigger next byte with stop */
|
||||
spacemit_i2c_stop(i2c);
|
||||
} else {
|
||||
/* trigger next byte */
|
||||
val |= SPACEMIT_CR_ALDIE | SPACEMIT_CR_TB;
|
||||
writel(val, i2c->base + SPACEMIT_ICR);
|
||||
val |= SPACEMIT_CR_STOP;
|
||||
|
||||
if (i2c->read)
|
||||
val |= SPACEMIT_CR_ACKNAK;
|
||||
}
|
||||
writel(val, i2c->base + SPACEMIT_ICR);
|
||||
}
|
||||
|
||||
err_out:
|
||||
@@ -476,12 +494,13 @@ static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, in
|
||||
spacemit_i2c_enable(i2c);
|
||||
|
||||
ret = spacemit_i2c_wait_bus_idle(i2c);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
ret = spacemit_i2c_xfer_msg(i2c);
|
||||
else if (ret < 0)
|
||||
dev_dbg(i2c->dev, "i2c transfer error: %d\n", ret);
|
||||
else
|
||||
if (ret < 0)
|
||||
dev_dbg(i2c->dev, "i2c transfer error: %d\n", ret);
|
||||
} else {
|
||||
spacemit_i2c_check_bus_release(i2c);
|
||||
}
|
||||
|
||||
spacemit_i2c_disable(i2c);
|
||||
|
||||
|
||||
@@ -1243,6 +1243,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
|
||||
{
|
||||
int ret;
|
||||
int left_num = num;
|
||||
bool write_then_read_en = false;
|
||||
struct mtk_i2c *i2c = i2c_get_adapdata(adap);
|
||||
|
||||
ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
|
||||
@@ -1256,6 +1257,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
|
||||
if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) &&
|
||||
msgs[0].addr == msgs[1].addr) {
|
||||
i2c->auto_restart = 0;
|
||||
write_then_read_en = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1280,12 +1282,10 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
|
||||
else
|
||||
i2c->op = I2C_MASTER_WR;
|
||||
|
||||
if (!i2c->auto_restart) {
|
||||
if (num > 1) {
|
||||
/* combined two messages into one transaction */
|
||||
i2c->op = I2C_MASTER_WRRD;
|
||||
left_num--;
|
||||
}
|
||||
if (write_then_read_en) {
|
||||
/* combined two messages into one transaction */
|
||||
i2c->op = I2C_MASTER_WRRD;
|
||||
left_num--;
|
||||
}
|
||||
|
||||
/* always use DMA mode. */
|
||||
@@ -1293,7 +1293,10 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
|
||||
if (ret < 0)
|
||||
goto err_exit;
|
||||
|
||||
msgs++;
|
||||
if (i2c->op == I2C_MASTER_WRRD)
|
||||
msgs += 2;
|
||||
else
|
||||
msgs++;
|
||||
}
|
||||
/* the return value is number of executed messages */
|
||||
ret = num;
|
||||
|
||||
@@ -138,7 +138,6 @@ static void i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id s3c24xx_i2c_match[] = {
|
||||
{ .compatible = "samsung,s3c2410-i2c", .data = (void *)0 },
|
||||
{ .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 },
|
||||
{ .compatible = "samsung,s3c2440-hdmiphy-i2c",
|
||||
.data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
|
||||
|
||||
@@ -425,7 +425,7 @@ static irqreturn_t sprd_i2c_isr(int irq, void *dev_id)
|
||||
* If we did not get one ACK from target when writing data, then we
|
||||
* should finish this transmission since we got some errors.
|
||||
*
|
||||
* When writing data, if i2c_tran == 0 which means we have writen
|
||||
* When writing data, if i2c_tran == 0 which means we have written
|
||||
* done all data, then we can finish this transmission.
|
||||
*
|
||||
* When reading data, if conut < rx fifo full threshold, which
|
||||
|
||||
@@ -152,7 +152,7 @@ struct st_i2c_timings {
|
||||
/**
|
||||
* struct st_i2c_client - client specific data
|
||||
* @addr: 8-bit target addr, including r/w bit
|
||||
* @count: number of bytes to be transfered
|
||||
* @count: number of bytes to be transferred
|
||||
* @xfered: number of bytes already transferred
|
||||
* @buf: data buffer
|
||||
* @result: result of the transfer
|
||||
|
||||
@@ -1649,7 +1649,33 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
|
||||
.has_interface_timing_reg = true,
|
||||
};
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra256_i2c_hw = {
|
||||
.has_continue_xfer_support = true,
|
||||
.has_per_pkt_xfer_complete_irq = true,
|
||||
.clk_divisor_hs_mode = 7,
|
||||
.clk_divisor_std_mode = 0x7a,
|
||||
.clk_divisor_fast_mode = 0x40,
|
||||
.clk_divisor_fast_plus_mode = 0x19,
|
||||
.has_config_load_reg = true,
|
||||
.has_multi_master_mode = true,
|
||||
.has_slcg_override_reg = true,
|
||||
.has_mst_fifo = true,
|
||||
.has_mst_reset = true,
|
||||
.quirks = &tegra194_i2c_quirks,
|
||||
.supports_bus_clear = true,
|
||||
.has_apb_dma = false,
|
||||
.tlow_std_mode = 0x8,
|
||||
.thigh_std_mode = 0x7,
|
||||
.tlow_fast_fastplus_mode = 0x3,
|
||||
.thigh_fast_fastplus_mode = 0x3,
|
||||
.setup_hold_time_std_mode = 0x08080808,
|
||||
.setup_hold_time_fast_fast_plus_mode = 0x02020202,
|
||||
.setup_hold_time_hs_mode = 0x090909,
|
||||
.has_interface_timing_reg = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_i2c_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra256-i2c", .data = &tegra256_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, },
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
|
||||
@@ -204,7 +204,7 @@ static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg)
|
||||
/* copy the received data */
|
||||
memcpy(msg->buf + start, rmsg, len1);
|
||||
|
||||
/* second read transfer if neccessary */
|
||||
/* second read transfer if necessary */
|
||||
if (len2 > 0) {
|
||||
ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len2);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -22,7 +22,7 @@ EXPORT_SYMBOL_GPL(__i2c_board_lock);
|
||||
LIST_HEAD(__i2c_board_list);
|
||||
EXPORT_SYMBOL_GPL(__i2c_board_list);
|
||||
|
||||
int __i2c_first_dynamic_bus_num;
|
||||
int __i2c_first_dynamic_bus_num __ro_after_init;
|
||||
EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
|
||||
* The board info passed can safely be __initdata, but be careful of embedded
|
||||
* pointers (for platform_data, functions, etc) since that won't be copied.
|
||||
*/
|
||||
int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
|
||||
int __init i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
||||
@@ -573,7 +573,8 @@ static int i2c_device_probe(struct device *dev)
|
||||
goto err_clear_wakeup_irq;
|
||||
|
||||
do_power_on = !i2c_acpi_waive_d0_probe(dev);
|
||||
status = dev_pm_domain_attach(&client->dev, do_power_on ? PD_FLAG_ATTACH_POWER_ON : 0);
|
||||
status = dev_pm_domain_attach(&client->dev, PD_FLAG_DETACH_POWER_OFF |
|
||||
(do_power_on ? PD_FLAG_ATTACH_POWER_ON : 0));
|
||||
if (status)
|
||||
goto err_clear_wakeup_irq;
|
||||
|
||||
@@ -581,7 +582,7 @@ static int i2c_device_probe(struct device *dev)
|
||||
GFP_KERNEL);
|
||||
if (!client->devres_group_id) {
|
||||
status = -ENOMEM;
|
||||
goto err_detach_pm_domain;
|
||||
goto err_clear_wakeup_irq;
|
||||
}
|
||||
|
||||
client->debugfs = debugfs_create_dir(dev_name(&client->dev),
|
||||
@@ -608,8 +609,6 @@ static int i2c_device_probe(struct device *dev)
|
||||
err_release_driver_resources:
|
||||
debugfs_remove_recursive(client->debugfs);
|
||||
devres_release_group(&client->dev, client->devres_group_id);
|
||||
err_detach_pm_domain:
|
||||
dev_pm_domain_detach(&client->dev, do_power_on);
|
||||
err_clear_wakeup_irq:
|
||||
dev_pm_clear_wake_irq(&client->dev);
|
||||
device_init_wakeup(&client->dev, false);
|
||||
@@ -636,8 +635,6 @@ static void i2c_device_remove(struct device *dev)
|
||||
|
||||
devres_release_group(&client->dev, client->devres_group_id);
|
||||
|
||||
dev_pm_domain_detach(&client->dev, true);
|
||||
|
||||
dev_pm_clear_wake_irq(&client->dev);
|
||||
device_init_wakeup(&client->dev, false);
|
||||
|
||||
|
||||
@@ -112,10 +112,9 @@ bool i2c_detect_slave_mode(struct device *dev)
|
||||
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
||||
|
||||
if (is_of_node(fwnode)) {
|
||||
struct fwnode_handle *child __free(fwnode_handle) = NULL;
|
||||
u32 reg;
|
||||
|
||||
fwnode_for_each_child_node(fwnode, child) {
|
||||
fwnode_for_each_child_node_scoped(fwnode, child) {
|
||||
fwnode_property_read_u32(child, "reg", ®);
|
||||
if (reg & I2C_OWN_SLAVE_ADDRESS)
|
||||
return true;
|
||||
|
||||
@@ -241,12 +241,9 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
|
||||
|
||||
muxc->parent = parent;
|
||||
muxc->dev = dev;
|
||||
if (flags & I2C_MUX_LOCKED)
|
||||
muxc->mux_locked = true;
|
||||
if (flags & I2C_MUX_ARBITRATOR)
|
||||
muxc->arbitrator = true;
|
||||
if (flags & I2C_MUX_GATE)
|
||||
muxc->gate = true;
|
||||
muxc->mux_locked = !!(flags & I2C_MUX_LOCKED);
|
||||
muxc->arbitrator = !!(flags & I2C_MUX_ARBITRATOR);
|
||||
muxc->gate = !!(flags & I2C_MUX_GATE);
|
||||
muxc->select = select;
|
||||
muxc->deselect = deselect;
|
||||
muxc->max_adapters = max_adapters;
|
||||
|
||||
@@ -63,10 +63,6 @@
|
||||
#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS)
|
||||
#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON)
|
||||
|
||||
/* arbitration timeouts, in jiffies */
|
||||
#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */
|
||||
#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */
|
||||
|
||||
/* arbitration retry delays, in us */
|
||||
#define SELECT_DELAY_SHORT 50
|
||||
#define SELECT_DELAY_LONG 1000
|
||||
@@ -229,6 +225,9 @@ static int pca9541_arbitrate(struct i2c_client *client)
|
||||
*/
|
||||
data->select_timeout = SELECT_DELAY_LONG;
|
||||
if (time_is_before_eq_jiffies(data->arb_timeout)) {
|
||||
dev_warn(&client->dev,
|
||||
"Arbitration timeout on I2C bus, forcing bus ownership\n");
|
||||
|
||||
/* Time is up, take the bus and reset it. */
|
||||
pca9541_reg_write(client,
|
||||
PCA9541_CONTROL,
|
||||
@@ -251,10 +250,10 @@ static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
int ret;
|
||||
unsigned long timeout = jiffies + ARB2_TIMEOUT;
|
||||
unsigned long timeout = jiffies + (2 * client->adapter->timeout);
|
||||
/* give up after this time */
|
||||
|
||||
data->arb_timeout = jiffies + ARB_TIMEOUT;
|
||||
data->arb_timeout = jiffies + client->adapter->timeout;
|
||||
/* force bus ownership after this time */
|
||||
|
||||
do {
|
||||
@@ -267,6 +266,7 @@ static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
else
|
||||
msleep(data->select_timeout / 1000);
|
||||
} while (time_is_after_eq_jiffies(timeout));
|
||||
dev_warn(&client->dev, "Failed to acquire I2C bus, timed out\n");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,6 @@ struct pca954x {
|
||||
raw_spinlock_t lock;
|
||||
struct regulator *supply;
|
||||
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct reset_control *reset_cont;
|
||||
};
|
||||
|
||||
@@ -316,6 +315,25 @@ static u8 pca954x_regval(struct pca954x *data, u8 chan)
|
||||
return 1 << chan;
|
||||
}
|
||||
|
||||
static void pca954x_reset_assert(struct pca954x *data)
|
||||
{
|
||||
if (data->reset_cont)
|
||||
reset_control_assert(data->reset_cont);
|
||||
}
|
||||
|
||||
static void pca954x_reset_deassert(struct pca954x *data)
|
||||
{
|
||||
if (data->reset_cont)
|
||||
reset_control_deassert(data->reset_cont);
|
||||
}
|
||||
|
||||
static void pca954x_reset_mux(struct pca954x *data)
|
||||
{
|
||||
pca954x_reset_assert(data);
|
||||
udelay(1);
|
||||
pca954x_reset_deassert(data);
|
||||
}
|
||||
|
||||
static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct pca954x *data = i2c_mux_priv(muxc);
|
||||
@@ -329,6 +347,8 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
ret = pca954x_reg_write(muxc->parent, client, regval);
|
||||
data->last_chan = ret < 0 ? 0 : regval;
|
||||
}
|
||||
if (ret == -ETIMEDOUT && data->reset_cont)
|
||||
pca954x_reset_mux(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -338,6 +358,7 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
|
||||
struct pca954x *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
s32 idle_state;
|
||||
int ret = 0;
|
||||
|
||||
idle_state = READ_ONCE(data->idle_state);
|
||||
if (idle_state >= 0)
|
||||
@@ -347,8 +368,10 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
|
||||
if (idle_state == MUX_IDLE_DISCONNECT) {
|
||||
/* Deselect active channel */
|
||||
data->last_chan = 0;
|
||||
return pca954x_reg_write(muxc->parent, client,
|
||||
data->last_chan);
|
||||
ret = pca954x_reg_write(muxc->parent, client,
|
||||
data->last_chan);
|
||||
if (ret == -ETIMEDOUT && data->reset_cont)
|
||||
pca954x_reset_mux(data);
|
||||
}
|
||||
|
||||
/* otherwise leave as-is */
|
||||
@@ -527,29 +550,10 @@ static int pca954x_get_reset(struct device *dev, struct pca954x *data)
|
||||
if (IS_ERR(data->reset_cont))
|
||||
return dev_err_probe(dev, PTR_ERR(data->reset_cont),
|
||||
"Failed to get reset\n");
|
||||
else if (data->reset_cont)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* fallback to legacy reset-gpios
|
||||
*/
|
||||
data->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(data->reset_gpio)) {
|
||||
return dev_err_probe(dev, PTR_ERR(data->reset_gpio),
|
||||
"Failed to get reset gpio");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pca954x_reset_deassert(struct pca954x *data)
|
||||
{
|
||||
if (data->reset_cont)
|
||||
reset_control_deassert(data->reset_cont);
|
||||
else
|
||||
gpiod_set_value_cansleep(data->reset_gpio, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C init/probing/exit functions
|
||||
*/
|
||||
@@ -589,7 +593,7 @@ static int pca954x_probe(struct i2c_client *client)
|
||||
if (ret)
|
||||
goto fail_cleanup;
|
||||
|
||||
if (data->reset_cont || data->reset_gpio) {
|
||||
if (data->reset_cont) {
|
||||
udelay(1);
|
||||
pca954x_reset_deassert(data);
|
||||
/* Give the chip some time to recover. */
|
||||
|
||||
@@ -499,7 +499,7 @@ static inline struct i2c_client *i2c_verify_client(struct device *dev)
|
||||
* Modules for add-on boards must use other calls.
|
||||
*/
|
||||
#ifdef CONFIG_I2C_BOARDINFO
|
||||
int
|
||||
int __init
|
||||
i2c_register_board_info(int busnum, struct i2c_board_info const *info,
|
||||
unsigned n);
|
||||
#else
|
||||
|
||||
@@ -176,6 +176,16 @@ struct fwnode_handle *fwnode_get_next_available_child_node(
|
||||
for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
|
||||
child = fwnode_get_next_available_child_node(fwnode, child))
|
||||
|
||||
#define fwnode_for_each_child_node_scoped(fwnode, child) \
|
||||
for (struct fwnode_handle *child __free(fwnode_handle) = \
|
||||
fwnode_get_next_child_node(fwnode, NULL); \
|
||||
child; child = fwnode_get_next_child_node(fwnode, child))
|
||||
|
||||
#define fwnode_for_each_available_child_node_scoped(fwnode, child) \
|
||||
for (struct fwnode_handle *child __free(fwnode_handle) = \
|
||||
fwnode_get_next_available_child_node(fwnode, NULL); \
|
||||
child; child = fwnode_get_next_available_child_node(fwnode, child))
|
||||
|
||||
struct fwnode_handle *device_get_next_child_node(const struct device *dev,
|
||||
struct fwnode_handle *child);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user