diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 11:15:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 11:15:36 -0700 |
commit | 89555eebb9fb603ad43c0def8ab35e76c210002f (patch) | |
tree | b4a344051eae119c94d0f85e27a93f936c980f62 | |
parent | d91f6a7307d27eae7b954c82bebf55071914c3f2 (diff) | |
parent | 38c87827ffd3c7e1dd61eee9a7dea13d487dc2ed (diff) |
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()
...
24 files changed, 181 insertions, 93 deletions
diff --git a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml index 199a354ccb97..26bed558c6b8 100644 --- a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml @@ -2,8 +2,8 @@ # Copyright 2019 BayLibre, SAS %YAML 1.2 --- -$id: "http://devicetree.org/schemas/i2c/amlogic,meson6-i2c.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/i2c/amlogic,meson6-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Amlogic Meson I2C Controller diff --git a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml index 3f0e94189f2d..077d2a539c83 100644 --- a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml @@ -1,8 +1,8 @@ # 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#" +$id: http://devicetree.org/schemas/i2c/apple,i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Apple/PASemi I2C controller diff --git a/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml b/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml index ea2303c0e143..6adedd3ec399 100644 --- a/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml @@ -75,7 +75,7 @@ required: - clocks allOf: - - $ref: "i2c-controller.yaml" + - $ref: i2c-controller.yaml - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml b/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml index 2e95cda7262a..cb24d7b3221c 100644 --- a/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml +++ b/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/i2c/cdns,i2c-r1p10.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/i2c/cdns,i2c-r1p10.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Cadence I2C controller @@ -24,6 +24,9 @@ properties: clocks: minItems: 1 + resets: + maxItems: 1 + interrupts: maxItems: 1 @@ -38,6 +41,13 @@ properties: description: | Input clock name. + fifo-depth: + description: + Size of the data FIFO in bytes. + $ref: /schemas/types.yaml#/definitions/uint32 + default: 16 + enum: [2, 4, 8, 16, 32, 64, 128, 256] + required: - compatible - reg @@ -52,9 +62,11 @@ examples: i2c@e0004000 { compatible = "cdns,i2c-r1p10"; clocks = <&clkc 38>; + resets = <&rstc 288>; interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>; reg = <0xe0004000 0x1000>; clock-frequency = <400000>; #address-cells = <1>; #size-cells = <0>; + fifo-depth = <8>; }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-mpc.yaml b/Documentation/devicetree/bindings/i2c/i2c-mpc.yaml index 018e1b944424..70fb69b923c4 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mpc.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-mpc.yaml @@ -43,6 +43,7 @@ properties: fsl,timeout: $ref: /schemas/types.yaml#/definitions/uint32 + deprecated: true description: | I2C bus timeout in microseconds @@ -95,6 +96,6 @@ examples: interrupts = <43 2>; interrupt-parent = <&mpic>; clock-frequency = <400000>; - fsl,timeout = <10000>; + i2c-scl-clk-low-timeout-us = <10000>; }; ... diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml index 72ae2e01cf22..fda0467cdd95 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml @@ -23,6 +23,7 @@ properties: - const: mediatek,mt6577-i2c - const: mediatek,mt6589-i2c - const: mediatek,mt7622-i2c + - const: mediatek,mt7981-i2c - const: mediatek,mt7986-i2c - const: mediatek,mt8168-i2c - const: mediatek,mt8173-i2c @@ -47,6 +48,10 @@ properties: - const: mediatek,mt8168-i2c - items: - enum: + - mediatek,mt6795-i2c + - const: mediatek,mt8173-i2c + - items: + - enum: - mediatek,mt8195-i2c - const: mediatek,mt8192-i2c diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.yaml b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.yaml index 6e0a5686af04..f34cc7ad5a00 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.yaml @@ -45,7 +45,7 @@ properties: i2c-parent: description: phandle of the I2C bus that this multiplexer's master-side port is connected to - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle mux-gpios: description: list of GPIOs used to control the muxer @@ -55,7 +55,7 @@ properties: idle-state: description: Value to set the muxer to when idle. When no value is given, it defaults to the last value used. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 allOf: - $ref: i2c-mux.yaml diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml index 0e88c85985b5..9f66a3bb1f80 100644 --- a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/i2c/qcom,i2c-geni-qcom.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/i2c/qcom,i2c-geni-qcom.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Geni based QUP I2C Controller diff --git a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml index bf396e9466aa..94b75d9f66cd 100644 --- a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml @@ -90,7 +90,7 @@ properties: st,syscfg-fmp: description: Use to set Fast Mode Plus bit within SYSCFG when Fast Mode Plus speed is selected by slave. - $ref: "/schemas/types.yaml#/definitions/phandle-array" + $ref: /schemas/types.yaml#/definitions/phandle-array items: - items: - description: phandle to syscfg diff --git a/Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml b/Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml index 1b598638d457..658ae92fa86d 100644 --- a/Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml +++ b/Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/i2c/xlnx,xps-iic-2.00.a.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/i2c/xlnx,xps-iic-2.00.a.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx IIC controller 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); diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 545436b7dd53..5c1376386897 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -55,7 +55,7 @@ int of_i2c_get_board_info(struct device *dev, struct device_node *node, if (of_property_read_bool(node, "host-notify")) info->flags |= I2C_CLIENT_HOST_NOTIFY; - if (of_get_property(node, "wakeup-source", NULL)) + if (of_property_read_bool(node, "wakeup-source")) info->flags |= I2C_CLIENT_WAKE; return 0; |