summaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-04-27 11:15:36 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-04-27 11:15:36 -0700
commit89555eebb9fb603ad43c0def8ab35e76c210002f (patch)
treeb4a344051eae119c94d0f85e27a93f936c980f62 /drivers/i2c/busses
parentd91f6a7307d27eae7b954c82bebf55071914c3f2 (diff)
parent38c87827ffd3c7e1dd61eee9a7dea13d487dc2ed (diff)
downloadlinux-89555eebb9fb603ad43c0def8ab35e76c210002f.tar.gz
linux-89555eebb9fb603ad43c0def8ab35e76c210002f.tar.bz2
linux-89555eebb9fb603ad43c0def8ab35e76c210002f.zip
Merge tag 'i2c-for-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: "Mostly fixes for DTs or DT handling this time. And a few driver bugfixes" * tag 'i2c-for-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (28 commits) i2c: xiic: xiic_xfer(): Fix runtime PM leak on error path i2c: cadence: cdns_i2c_master_xfer(): Fix runtime PM leak on error path i2c: omap: Improve error reporting for problems during .remove() i2c: cadence: Add reset controller support dt-bindings: i2c: cadence: Document `resets` property i2c: mediatek: add support for MT7981 SoC dt-bindings: i2c: i2c-mt65xx: add MediaTek MT7981 SoC dt-bindings: i2c: Drop unneeded quotes i2c: brcmstb: use devm_platform_ioremap_resource_byname() i2c: cadence: Detect maximum transfer size i2c: cadence: Allow to specify the FIFO depth dt-bindings: i2c: cadence: Document `fifo-depth` property i2c: xiic: Use devm_platform_get_and_ioremap_resource() i2c: mpc: Use i2c-scl-clk-low-timeout-us i2c property i2c: mpc: Use of_property_read_u32 instead of of_get_property dt-bindings: i2c: mpc: Mark "fsl,timeout" as deprecated i2c: xiic: hide OF related data for COMPILE_TEST i2c: synquacer: mark OF related data as maybe unused dt-bindings: i2c: i2c-mt65xx: Add compatible for MT6795 Helio X10 i2c: imx: Simplify using devm_clk_get_enabled() ...
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r--drivers/i2c/busses/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c4
-rw-r--r--drivers/i2c/busses/i2c-cadence.c117
-rw-r--r--drivers/i2c/busses/i2c-cros-ec-tunnel.c4
-rw-r--r--drivers/i2c/busses/i2c-davinci.c5
-rw-r--r--drivers/i2c/busses/i2c-imx.c12
-rw-r--r--drivers/i2c/busses/i2c-mpc.c37
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c15
-rw-r--r--drivers/i2c/busses/i2c-omap.c9
-rw-r--r--drivers/i2c/busses/i2c-owl.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c6
-rw-r--r--drivers/i2c/busses/i2c-synquacer.c2
-rw-r--r--drivers/i2c/busses/i2c-xiic.c9
13 files changed, 147 insertions, 77 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4b4323bbf268..87600b4aacb3 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -807,7 +807,7 @@ config I2C_MESON
config I2C_MICROCHIP_CORE
tristate "Microchip FPGA I2C controller"
- depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST
+ depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
depends on OF
help
If you say yes to this option, support will be included for the
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 69383be47905..ef942714642a 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -575,12 +575,10 @@ static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev)
static int bcm2711_release_bsc(struct brcmstb_i2c_dev *dev)
{
struct platform_device *pdev = to_platform_device(dev->device);
- struct resource *iomem;
void __iomem *autoi2c;
/* Map hardware registers */
- iomem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "auto-i2c");
- autoi2c = devm_ioremap_resource(&pdev->dev, iomem);
+ autoi2c = devm_platform_ioremap_resource_byname(pdev, "auto-i2c");
if (IS_ERR(autoi2c))
return PTR_ERR(autoi2c);
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index b5d22e7282c2..3a4edf7e75f9 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -16,6 +16,7 @@
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/reset.h>
/* Register offsets for the I2C device. */
#define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */
@@ -114,10 +115,10 @@
/* timeout for pm runtime autosuspend */
#define CNDS_I2C_PM_TIMEOUT 1000 /* ms */
-#define CDNS_I2C_FIFO_DEPTH 16
+#define CDNS_I2C_FIFO_DEPTH_DEFAULT 16
#define CDNS_I2C_MAX_TRANSFER_SIZE 255
/* Transfer size in multiples of data interrupt depth */
-#define CDNS_I2C_TRANSFER_SIZE (CDNS_I2C_MAX_TRANSFER_SIZE - 3)
+#define CDNS_I2C_TRANSFER_SIZE(max) ((max) - 3)
#define DRIVER_NAME "cdns-i2c"
@@ -178,12 +179,15 @@ enum cdns_i2c_slave_state {
* @bus_hold_flag: Flag used in repeated start for clearing HOLD bit
* @clk: Pointer to struct clk
* @clk_rate_change_nb: Notifier block for clock rate changes
+ * @reset: Reset control for the device
* @quirks: flag for broken hold bit usage in r1p10
* @ctrl_reg: Cached value of the control register.
* @ctrl_reg_diva_divb: value of fields DIV_A and DIV_B from CR register
* @slave: Registered slave instance.
* @dev_mode: I2C operating role(master/slave).
* @slave_state: I2C Slave state(idle/read/write).
+ * @fifo_depth: The depth of the transfer FIFO
+ * @transfer_size: The maximum number of bytes in one transfer
*/
struct cdns_i2c {
struct device *dev;
@@ -202,6 +206,7 @@ struct cdns_i2c {
unsigned int bus_hold_flag;
struct clk *clk;
struct notifier_block clk_rate_change_nb;
+ struct reset_control *reset;
u32 quirks;
u32 ctrl_reg;
struct i2c_bus_recovery_info rinfo;
@@ -211,6 +216,8 @@ struct cdns_i2c {
enum cdns_i2c_mode dev_mode;
enum cdns_i2c_slave_state slave_state;
#endif
+ u32 fifo_depth;
+ unsigned int transfer_size;
};
struct cdns_platform_data {
@@ -236,7 +243,7 @@ static void cdns_i2c_clear_bus_hold(struct cdns_i2c *id)
static inline bool cdns_is_holdquirk(struct cdns_i2c *id, bool hold_wrkaround)
{
return (hold_wrkaround &&
- (id->curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1));
+ (id->curr_recv_count == id->fifo_depth + 1));
}
#if IS_ENABLED(CONFIG_I2C_SLAVE)
@@ -431,7 +438,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
* if RX data left is less than or equal to
* FIFO DEPTH unless repeated start is selected
*/
- if (id->recv_count <= CDNS_I2C_FIFO_DEPTH &&
+ if (id->recv_count <= id->fifo_depth &&
!id->bus_hold_flag)
cdns_i2c_clear_bus_hold(id);
@@ -456,22 +463,22 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
if (cdns_is_holdquirk(id, updatetx)) {
/* wait while fifo is full */
while (cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET) !=
- (id->curr_recv_count - CDNS_I2C_FIFO_DEPTH))
+ (id->curr_recv_count - id->fifo_depth))
;
/*
* Check number of bytes to be received against maximum
* transfer size and update register accordingly.
*/
- if (((int)(id->recv_count) - CDNS_I2C_FIFO_DEPTH) >
- CDNS_I2C_TRANSFER_SIZE) {
- cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE,
+ if (((int)(id->recv_count) - id->fifo_depth) >
+ id->transfer_size) {
+ cdns_i2c_writereg(id->transfer_size,
CDNS_I2C_XFER_SIZE_OFFSET);
- id->curr_recv_count = CDNS_I2C_TRANSFER_SIZE +
- CDNS_I2C_FIFO_DEPTH;
+ id->curr_recv_count = id->transfer_size +
+ id->fifo_depth;
} else {
cdns_i2c_writereg(id->recv_count -
- CDNS_I2C_FIFO_DEPTH,
+ id->fifo_depth,
CDNS_I2C_XFER_SIZE_OFFSET);
id->curr_recv_count = id->recv_count;
}
@@ -494,7 +501,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
* space available in FIFO and fill with that many bytes.
*/
if (id->send_count) {
- avail_bytes = CDNS_I2C_FIFO_DEPTH -
+ avail_bytes = id->fifo_depth -
cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET);
if (id->send_count > avail_bytes)
bytes_to_send = avail_bytes;
@@ -588,7 +595,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
* Check for the message size against FIFO depth and set the
* 'hold bus' bit if it is greater than FIFO depth.
*/
- if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
+ if (id->recv_count > id->fifo_depth)
ctrl_reg |= CDNS_I2C_CR_HOLD;
cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
@@ -603,17 +610,17 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
* receive if it is less than transfer size and transfer size if
* it is more. Enable the interrupts.
*/
- if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) {
- cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE,
+ if (id->recv_count > id->transfer_size) {
+ cdns_i2c_writereg(id->transfer_size,
CDNS_I2C_XFER_SIZE_OFFSET);
- id->curr_recv_count = CDNS_I2C_TRANSFER_SIZE;
+ id->curr_recv_count = id->transfer_size;
} else {
cdns_i2c_writereg(id->recv_count, CDNS_I2C_XFER_SIZE_OFFSET);
}
/* Determine hold_clear based on number of bytes to receive and hold flag */
- if (!id->bus_hold_flag && id->recv_count <= CDNS_I2C_FIFO_DEPTH) {
- if (cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & CDNS_I2C_CR_HOLD) {
+ if (!id->bus_hold_flag && id->recv_count <= id->fifo_depth) {
+ if (ctrl_reg & CDNS_I2C_CR_HOLD) {
hold_clear = true;
if (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT)
irq_save = true;
@@ -624,7 +631,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
addr &= CDNS_I2C_ADDR_MASK;
if (hold_clear) {
- ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & ~CDNS_I2C_CR_HOLD;
+ ctrl_reg &= ~CDNS_I2C_CR_HOLD;
/*
* In case of Xilinx Zynq SOC, clear the HOLD bit before transfer size
* register reaches '0'. This is an IP bug which causes transfer size
@@ -673,7 +680,7 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
* Check for the message size against FIFO depth and set the
* 'hold bus' bit if it is greater than FIFO depth.
*/
- if (id->send_count > CDNS_I2C_FIFO_DEPTH)
+ if (id->send_count > id->fifo_depth)
ctrl_reg |= CDNS_I2C_CR_HOLD;
cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
@@ -686,7 +693,7 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
* against the space available, and fill the FIFO accordingly.
* Enable the interrupts.
*/
- avail_bytes = CDNS_I2C_FIFO_DEPTH -
+ avail_bytes = id->fifo_depth -
cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET);
if (id->send_count > avail_bytes)
@@ -827,8 +834,10 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
#if IS_ENABLED(CONFIG_I2C_SLAVE)
/* Check i2c operating mode and switch if possible */
if (id->dev_mode == CDNS_I2C_MODE_SLAVE) {
- if (id->slave_state != CDNS_I2C_SLAVE_STATE_IDLE)
- return -EAGAIN;
+ if (id->slave_state != CDNS_I2C_SLAVE_STATE_IDLE) {
+ ret = -EAGAIN;
+ goto out;
+ }
/* Set mode to master */
cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id);
@@ -1030,8 +1039,7 @@ static int cdns_i2c_calc_divs(unsigned long *f, unsigned long input_clk,
if (actual_fscl > fscl)
continue;
- current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) :
- (fscl - actual_fscl));
+ current_error = fscl - actual_fscl;
if (last_error > current_error) {
calc_div_a = div_a;
@@ -1227,6 +1235,37 @@ static const struct of_device_id cdns_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, cdns_i2c_of_match);
/**
+ * cdns_i2c_detect_transfer_size - Detect the maximum transfer size supported
+ * @id: Device private data structure
+ *
+ * Detect the maximum transfer size that is supported by this instance of the
+ * Cadence I2C controller.
+ */
+static void cdns_i2c_detect_transfer_size(struct cdns_i2c *id)
+{
+ u32 val;
+
+ /*
+ * Writing to the transfer size register is only possible if these two bits
+ * are set in the control register.
+ */
+ cdns_i2c_writereg(CDNS_I2C_CR_MS | CDNS_I2C_CR_RW, CDNS_I2C_CR_OFFSET);
+
+ /*
+ * The number of writable bits of the transfer size register can be between
+ * 4 and 8. This is a controlled through a synthesis parameter of the IP
+ * core and can vary from instance to instance. The unused MSBs always read
+ * back as 0. Writing 0xff and then reading the value back will report the
+ * maximum supported transfer size.
+ */
+ cdns_i2c_writereg(CDNS_I2C_MAX_TRANSFER_SIZE, CDNS_I2C_XFER_SIZE_OFFSET);
+ val = cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET);
+ id->transfer_size = CDNS_I2C_TRANSFER_SIZE(val);
+ cdns_i2c_writereg(0, CDNS_I2C_XFER_SIZE_OFFSET);
+ cdns_i2c_writereg(0, CDNS_I2C_CR_OFFSET);
+}
+
+/**
* cdns_i2c_probe - Platform registration call
* @pdev: Handle to the platform device structure
*
@@ -1291,10 +1330,22 @@ static int cdns_i2c_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(id->clk),
"input clock not found.\n");
+ id->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
+ if (IS_ERR(id->reset))
+ return dev_err_probe(&pdev->dev, PTR_ERR(id->reset),
+ "Failed to request reset.\n");
+
ret = clk_prepare_enable(id->clk);
if (ret)
dev_err(&pdev->dev, "Unable to enable clock.\n");
+ ret = reset_control_deassert(id->reset);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret,
+ "Failed to de-assert reset.\n");
+ goto err_clk_dis;
+ }
+
pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(id->dev);
pm_runtime_set_active(id->dev);
@@ -1317,32 +1368,39 @@ static int cdns_i2c_probe(struct platform_device *pdev)
#endif
id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS;
+ id->fifo_depth = CDNS_I2C_FIFO_DEPTH_DEFAULT;
+ of_property_read_u32(pdev->dev.of_node, "fifo-depth", &id->fifo_depth);
+
+ cdns_i2c_detect_transfer_size(id);
+
ret = cdns_i2c_setclk(id->input_clk, id);
if (ret) {
dev_err(&pdev->dev, "invalid SCL clock: %u Hz\n", id->i2c_clk);
ret = -EINVAL;
- goto err_clk_dis;
+ goto err_clk_notifier_unregister;
}
ret = devm_request_irq(&pdev->dev, irq, cdns_i2c_isr, 0,
DRIVER_NAME, id);
if (ret) {
dev_err(&pdev->dev, "cannot get irq %d\n", irq);
- goto err_clk_dis;
+ goto err_clk_notifier_unregister;
}
cdns_i2c_init(id);
ret = i2c_add_adapter(&id->adap);
if (ret < 0)
- goto err_clk_dis;
+ goto err_clk_notifier_unregister;
dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n",
id->i2c_clk / 1000, (unsigned long)r_mem->start, irq);
return 0;
-err_clk_dis:
+err_clk_notifier_unregister:
clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
+ reset_control_assert(id->reset);
+err_clk_dis:
clk_disable_unprepare(id->clk);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
@@ -1367,6 +1425,7 @@ static int cdns_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&id->adap);
clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
+ reset_control_assert(id->reset);
clk_disable_unprepare(id->clk);
return 0;
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index 4e787dc709f9..8b3ff5bb14d8 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -292,13 +292,13 @@ static int ec_i2c_remove(struct platform_device *dev)
return 0;
}
-static const struct of_device_id cros_ec_i2c_of_match[] = {
+static const struct of_device_id cros_ec_i2c_of_match[] __maybe_unused = {
{ .compatible = "google,cros-ec-i2c-tunnel" },
{},
};
MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
-static const struct acpi_device_id cros_ec_i2c_tunnel_acpi_id[] = {
+static const struct acpi_device_id cros_ec_i2c_tunnel_acpi_id[] __maybe_unused = {
{ "GOOG0012", 0 },
{ }
};
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index c836cf884185..9750310f2c96 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -764,11 +764,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
int r, irq;
irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- if (!irq)
- irq = -ENXIO;
+ if (irq < 0)
return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n");
- }
dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev),
GFP_KERNEL);
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index cf5bacf3a488..42189a5f2905 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1482,17 +1482,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
ACPI_COMPANION_SET(&i2c_imx->adapter.dev, ACPI_COMPANION(&pdev->dev));
/* Get I2C clock */
- i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
+ i2c_imx->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(i2c_imx->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(i2c_imx->clk),
"can't get I2C clock\n");
- ret = clk_prepare_enable(i2c_imx->clk);
- if (ret) {
- dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret);
- return ret;
- }
-
/* Init queue */
init_waitqueue_head(&i2c_imx->queue);
@@ -1564,7 +1558,6 @@ rpm_disable:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
- clk_disable_unprepare(i2c_imx->clk);
return ret;
}
@@ -1590,7 +1583,6 @@ static int i2c_imx_remove(struct platform_device *pdev)
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IFDR);
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
- clk_disable(i2c_imx->clk);
}
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
@@ -1598,8 +1590,6 @@ static int i2c_imx_remove(struct platform_device *pdev)
if (irq >= 0)
free_irq(irq, i2c_imx);
- clk_unprepare(i2c_imx->clk);
-
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 81ac92bb4f6f..cfd074ee6d54 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -770,7 +770,6 @@ static const struct i2c_algorithm mpc_algo = {
static struct i2c_adapter mpc_ops = {
.owner = THIS_MODULE,
.algo = &mpc_algo,
- .timeout = HZ,
};
static struct i2c_bus_recovery_info fsl_i2c_recovery_info = {
@@ -781,11 +780,9 @@ static int fsl_i2c_probe(struct platform_device *op)
{
const struct mpc_i2c_data *data;
struct mpc_i2c *i2c;
- const u32 *prop;
- u32 clock = MPC_I2C_CLOCK_LEGACY;
- int result = 0;
- int plen;
struct clk *clk;
+ int result;
+ u32 clock;
int err;
i2c = devm_kzalloc(&op->dev, sizeof(*i2c), GFP_KERNEL);
@@ -831,10 +828,10 @@ static int fsl_i2c_probe(struct platform_device *op)
if (of_property_read_bool(op->dev.of_node, "fsl,preserve-clocking")) {
clock = MPC_I2C_CLOCK_PRESERVE;
} else {
- prop = of_get_property(op->dev.of_node, "clock-frequency",
- &plen);
- if (prop && plen == sizeof(u32))
- clock = *prop;
+ result = of_property_read_u32(op->dev.of_node,
+ "clock-frequency", &clock);
+ if (result)
+ clock = MPC_I2C_CLOCK_LEGACY;
}
data = device_get_match_data(&op->dev);
@@ -842,16 +839,30 @@ static int fsl_i2c_probe(struct platform_device *op)
data->setup(op->dev.of_node, i2c, clock);
} else {
/* Backwards compatibility */
- if (of_get_property(op->dev.of_node, "dfsrr", NULL))
+ if (of_property_read_bool(op->dev.of_node, "dfsrr"))
mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock);
}
- prop = of_get_property(op->dev.of_node, "fsl,timeout", &plen);
- if (prop && plen == sizeof(u32)) {
- mpc_ops.timeout = *prop * HZ / 1000000;
+ /*
+ * "fsl,timeout" has been marked as deprecated and, to maintain
+ * backward compatibility, we will only look for it if
+ * "i2c-scl-clk-low-timeout-us" is not present.
+ */
+ result = of_property_read_u32(op->dev.of_node,
+ "i2c-scl-clk-low-timeout-us",
+ &mpc_ops.timeout);
+ if (result == -EINVAL)
+ result = of_property_read_u32(op->dev.of_node,
+ "fsl,timeout", &mpc_ops.timeout);
+
+ if (!result) {
+ mpc_ops.timeout *= HZ / 1000000;
if (mpc_ops.timeout < 5)
mpc_ops.timeout = 5;
+ } else {
+ mpc_ops.timeout = HZ;
}
+
dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ);
if (of_property_read_bool(op->dev.of_node, "fsl,i2c-erratum-a004447"))
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 43dd966d5ef5..a43c4d77739a 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -431,6 +431,18 @@ static const struct mtk_i2c_compatible mt8168_compat = {
.max_dma_support = 33,
};
+static const struct mtk_i2c_compatible mt7981_compat = {
+ .regs = mt_i2c_regs_v3,
+ .pmic_i2c = 0,
+ .dcm = 0,
+ .auto_restart = 1,
+ .aux_len_reg = 1,
+ .timing_adjust = 1,
+ .dma_sync = 1,
+ .ltiming_adjust = 1,
+ .max_dma_support = 33
+};
+
static const struct mtk_i2c_compatible mt7986_compat = {
.quirks = &mt7622_i2c_quirks,
.regs = mt_i2c_regs_v1,
@@ -516,6 +528,7 @@ static const struct of_device_id mtk_i2c_of_match[] = {
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
+ { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat },
{ .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat },
{ .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
@@ -1546,7 +1559,7 @@ static struct platform_driver mtk_i2c_driver = {
.driver = {
.name = I2C_DRV_NAME,
.pm = &mtk_i2c_pm,
- .of_match_table = of_match_ptr(mtk_i2c_of_match),
+ .of_match_table = mtk_i2c_of_match,
},
};
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index f9ae520aed22..2b4e2be51318 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1525,14 +1525,17 @@ static int omap_i2c_remove(struct platform_device *pdev)
int ret;
i2c_del_adapter(&omap->adapter);
- ret = pm_runtime_resume_and_get(&pdev->dev);
+
+ ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0)
- return ret;
+ dev_err(omap->dev, "Failed to resume hardware, skip disable\n");
+ else
+ omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0);
- omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+
return 0;
}
diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c
index 98882fe4e965..99ddd8894964 100644
--- a/drivers/i2c/busses/i2c-owl.c
+++ b/drivers/i2c/busses/i2c-owl.c
@@ -519,7 +519,7 @@ static struct platform_driver owl_i2c_driver = {
.probe = owl_i2c_probe,
.driver = {
.name = "owl-i2c",
- .of_match_table = of_match_ptr(owl_i2c_of_match),
+ .of_match_table = owl_i2c_of_match,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index b605b6e43cb9..f9fa5308556b 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1261,10 +1261,8 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
/* For device tree we always use the dynamic or alias-assigned ID */
i2c->adap.nr = -1;
- if (of_get_property(np, "mrvl,i2c-polling", NULL))
- i2c->use_pio = 1;
- if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
- i2c->fast_mode = 1;
+ i2c->use_pio = of_property_read_bool(np, "mrvl,i2c-polling");
+ i2c->fast_mode = of_property_read_bool(np, "mrvl,i2c-fast-mode");
*i2c_types = (enum pxa_i2c_types)(of_id->data);
diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c
index e4026c5416b1..50d19cf99a03 100644
--- a/drivers/i2c/busses/i2c-synquacer.c
+++ b/drivers/i2c/busses/i2c-synquacer.c
@@ -629,7 +629,7 @@ static int synquacer_i2c_remove(struct platform_device *pdev)
return 0;
};
-static const struct of_device_id synquacer_i2c_dt_ids[] = {
+static const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = {
{ .compatible = "socionext,synquacer-i2c" },
{ /* sentinel */ }
};
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index dbb792fc197e..8a3d9817cb41 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -1164,7 +1164,7 @@ 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");
- return err;
+ goto out;
}
err = wait_for_completion_timeout(&i2c->completion, XIIC_XFER_TIMEOUT);
@@ -1178,6 +1178,8 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
err = (i2c->state == STATE_DONE) ? num : -EIO;
}
mutex_unlock(&i2c->lock);
+
+out:
pm_runtime_mark_last_busy(i2c->dev);
pm_runtime_put_autosuspend(i2c->dev);
return err;
@@ -1199,11 +1201,11 @@ static const struct i2c_adapter xiic_adapter = {
.algo = &xiic_algorithm,
};
+#if defined(CONFIG_OF)
static const struct xiic_version_data xiic_2_00 = {
.quirks = DYNAMIC_MODE_READ_BROKEN_BIT,
};
-#if defined(CONFIG_OF)
static const struct of_device_id xiic_of_match[] = {
{ .compatible = "xlnx,xps-iic-2.00.a", .data = &xiic_2_00 },
{ .compatible = "xlnx,axi-iic-2.1", },
@@ -1233,8 +1235,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
i2c->quirks = data->quirks;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- i2c->base = devm_ioremap_resource(&pdev->dev, res);
+ i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(i2c->base))
return PTR_ERR(i2c->base);