diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-04 11:47:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-04 11:47:18 -0700 |
commit | 855ff900b8605df2b9ea309534cd2f02dc0c4cb8 (patch) | |
tree | c6f38bbb17d8702c7a692b383be94a59d451922b | |
parent | d2500a0c0e73d4387cde9185edcdf397f52e428b (diff) | |
parent | 9d6336831bdc78e5207eaf147cc17228b5e984c3 (diff) |
Merge branch 'i2c/for-mergewindow' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
- core supports now bus regulators controlling power for SCL/SDA
- quite some DT binding conversions to YAML
- added a seperate DT binding for the optional SMBus Alert feature
- documentation with examples how to deal with I2C sysfs files
- some bigger rework for the i801 driver
- and a few usual driver updates
* 'i2c/for-mergewindow' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (42 commits)
i2c: ali1535: mention that the device should not be disabled
i2c: mpc: Restore reread of I2C status register
i2c: core-smbus: Expose PEC calculate function for generic use
Documentation: i2c: Add doc for I2C sysfs
i2c: core: Disable client irq on reboot/shutdown
dt-bindings: i2c: update bindings for MT8195 SoC
i2c: imx: Fix some checkpatch warnings
i2c: davinci: Simplify with dev_err_probe()
i2c: cadence: Simplify with dev_err_probe()
i2c: xiic: Simplify with dev_err_probe()
i2c: cadence: Clear HOLD bit before xfer_size register rolls over
dt-bindings: i2c: ce4100: Replace "ti,pcf8575" by "nxp,pcf8575"
i2c: i801: Improve i801_setup_hstcfg
i2c: i801: Use driver name constant instead of function dev_driver_string
i2c: i801: Simplify initialization of i2c_board_info in i801_probe_optional_slaves
i2c: i801: Improve status polling
i2c: cht-wc: Replace of_node by NULL
i2c: riic: Add RZ/G2L support
dt-bindings: i2c: renesas,riic: Document RZ/G2L I2C controller
dt-bindings: i2c: renesas,iic: Convert to json-schema
...
35 files changed, 1316 insertions, 376 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt index 7f0194fdd0cc..5ea216ae7084 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt @@ -15,6 +15,7 @@ Required properties: "mediatek,mt8173-i2c": for MediaTek MT8173 "mediatek,mt8183-i2c": for MediaTek MT8183 "mediatek,mt8192-i2c": for MediaTek MT8192 + "mediatek,mt8195-i2c", "mediatek,mt8192-i2c": for MediaTek MT8195 "mediatek,mt8516-i2c", "mediatek,mt2712-i2c": for MediaTek MT8516 - reg: physical base address of the controller and dma base, length of memory mapped region. @@ -32,6 +33,7 @@ Optional properties: - mediatek,have-pmic: platform can control i2c form special pmic side. Only mt6589 and mt8135 support this feature. - mediatek,use-push-pull: IO config use push-pull mode. + - vbus-supply: phandle to the regulator that provides power to SCL/SDA. Example: diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt index e00d2b9e957a..d4cf10582a26 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt @@ -62,7 +62,6 @@ Example: reg = <0x3c>; pwms = <&pwm 4 3000>; reset-gpios = <&gpio2 7 1>; - reset-active-low; }; }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-omap.txt b/Documentation/devicetree/bindings/i2c/i2c-omap.txt deleted file mode 100644 index a425b91af48f..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-omap.txt +++ /dev/null @@ -1,37 +0,0 @@ -I2C for OMAP platforms - -Required properties : -- compatible : Must be - "ti,omap2420-i2c" for OMAP2420 SoCs - "ti,omap2430-i2c" for OMAP2430 SoCs - "ti,omap3-i2c" for OMAP3 SoCs - "ti,omap4-i2c" for OMAP4+ SoCs - "ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs - "ti,j721e-i2c", "ti,omap4-i2c" for J721E SoCs - "ti,am64-i2c", "ti,omap4-i2c" for AM64 SoCs -- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based) -- #address-cells = <1>; -- #size-cells = <0>; - -Recommended properties : -- clock-frequency : Desired I2C bus clock frequency in Hz. Otherwise - the default 100 kHz frequency will be used. - -Optional properties: -- Child nodes conforming to i2c bus binding - -Note: Current implementation will fetch base address, irq and dma -from omap hwmod data base during device registration. -Future plan is to migrate hwmod data base contents into device tree -blob so that, all the required data will be used from device tree dts -file. - -Examples : - -i2c1: i2c@0 { - compatible = "ti,omap3-i2c"; - #address-cells = <1>; - #size-cells = <0>; - ti,hwmods = "i2c1"; - clock-frequency = <400000>; -}; diff --git a/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt index 569b16248514..1ff6f8487a2d 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt @@ -71,7 +71,7 @@ This is an example which is used on FalconFalls: /* This I2C controller has one gpio controller */ gpio@26 { #gpio-cells = <2>; - compatible = "ti,pcf8575"; + compatible = "nxp,pcf8575"; reg = <0x26>; gpio-controller; }; @@ -85,7 +85,7 @@ This is an example which is used on FalconFalls: gpio@26 { #gpio-cells = <2>; - compatible = "ti,pcf8575"; + compatible = "nxp,pcf8575"; reg = <0x26>; gpio-controller; }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt b/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt index c6668b7c66e6..7b9fc0c22eaf 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt @@ -9,6 +9,7 @@ PROPERTIES: "qcom,msm8916-cci" "qcom,msm8996-cci" "qcom,sdm845-cci" + "qcom,sm8250-cci" - reg Usage: required @@ -41,8 +42,8 @@ PROPERTIES: SUBNODES: -The CCI provides I2C masters for one (msm8916) or two i2c busses (msm8996 and -sdm845), described as subdevices named "i2c-bus@0" and "i2c-bus@1". +The CCI provides I2C masters for one (msm8916) or two i2c busses (msm8996, +sdm845 and sm8250), described as subdevices named "i2c-bus@0" and "i2c-bus@1". PROPERTIES: diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml b/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml index 7f254d79558c..5339dd4fc370 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml @@ -36,6 +36,7 @@ properties: - rockchip,px30-i2c - rockchip,rk3308-i2c - rockchip,rk3328-i2c + - rockchip,rk3568-i2c - const: rockchip,rk3399-i2c reg: diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt b/Documentation/devicetree/bindings/i2c/i2c.txt index df41f72afc87..b864916e087f 100644 --- a/Documentation/devicetree/bindings/i2c/i2c.txt +++ b/Documentation/devicetree/bindings/i2c/i2c.txt @@ -89,8 +89,11 @@ wants to support one of the below features, it should adapt these bindings. - smbus states that additional SMBus restrictions and features apply to this bus. - Examples of features are SMBusHostNotify and SMBusAlert. Examples of - restrictions are more reserved addresses and timeout definitions. + An example of feature is SMBusHostNotify. Examples of restrictions are + more reserved addresses and timeout definitions. + +- smbus-alert + states that the optional SMBus-Alert feature apply to this bus. Required properties (per child device) -------------------------------------- diff --git a/Documentation/devicetree/bindings/i2c/renesas,i2c.txt b/Documentation/devicetree/bindings/i2c/renesas,i2c.txt deleted file mode 100644 index 5762d2d1ab9c..000000000000 --- a/Documentation/devicetree/bindings/i2c/renesas,i2c.txt +++ /dev/null @@ -1,67 +0,0 @@ -I2C for R-Car platforms - -Required properties: -- compatible: - "renesas,i2c-r8a7742" if the device is a part of a R8A7742 SoC. - "renesas,i2c-r8a7743" if the device is a part of a R8A7743 SoC. - "renesas,i2c-r8a7744" if the device is a part of a R8A7744 SoC. - "renesas,i2c-r8a7745" if the device is a part of a R8A7745 SoC. - "renesas,i2c-r8a77470" if the device is a part of a R8A77470 SoC. - "renesas,i2c-r8a774a1" if the device is a part of a R8A774A1 SoC. - "renesas,i2c-r8a774b1" if the device is a part of a R8A774B1 SoC. - "renesas,i2c-r8a774c0" if the device is a part of a R8A774C0 SoC. - "renesas,i2c-r8a774e1" if the device is a part of a R8A774E1 SoC. - "renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC. - "renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC. - "renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC. - "renesas,i2c-r8a7791" if the device is a part of a R8A7791 SoC. - "renesas,i2c-r8a7792" if the device is a part of a R8A7792 SoC. - "renesas,i2c-r8a7793" if the device is a part of a R8A7793 SoC. - "renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC. - "renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC. - "renesas,i2c-r8a7796" if the device is a part of a R8A77960 SoC. - "renesas,i2c-r8a77961" if the device is a part of a R8A77961 SoC. - "renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC. - "renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC. - "renesas,i2c-r8a77980" if the device is a part of a R8A77980 SoC. - "renesas,i2c-r8a77990" if the device is a part of a R8A77990 SoC. - "renesas,i2c-r8a77995" if the device is a part of a R8A77995 SoC. - "renesas,i2c-r8a779a0" if the device is a part of a R8A779A0 SoC. - "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device. - "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible - device. - "renesas,rcar-gen3-i2c" for a generic R-Car Gen3 or RZ/G2 compatible - device. - "renesas,i2c-rcar" (deprecated) - - When compatible with the generic version, nodes must list the - SoC-specific version corresponding to the platform first followed - by the generic version. - -- reg: physical base address of the controller and length of memory mapped - region. -- interrupts: interrupt specifier. - -Optional properties: -- clock-frequency: desired I2C bus clock frequency in Hz. The absence of this - property indicates the default frequency 100 kHz. -- clocks: clock specifier. -- dmas: Must contain a list of two references to DMA specifiers, one for - transmission, and one for reception. -- dma-names: Must contain a list of two DMA names, "tx" and "rx". - -- i2c-scl-falling-time-ns: see i2c.txt -- i2c-scl-internal-delay-ns: see i2c.txt -- i2c-scl-rising-time-ns: see i2c.txt - -Examples : - -i2c0: i2c@e6508000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "renesas,i2c-r8a7791", "renesas,rcar-gen2-i2c"; - reg = <0 0xe6508000 0 0x40>; - interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp9_clks R8A7791_CLK_I2C0>; - clock-frequency = <400000>; -}; diff --git a/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.txt b/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.txt deleted file mode 100644 index 5ed1ea1c7e14..000000000000 --- a/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.txt +++ /dev/null @@ -1,22 +0,0 @@ -Device tree configuration for Renesas EMEV2 IIC controller - -Required properties: -- compatible : "renesas,iic-emev2" -- reg : address start and address range size of device -- interrupts : specifier for the IIC controller interrupt -- clocks : phandle to the IP core SCLK -- clock-names : must be "sclk" -- #address-cells : should be <1> -- #size-cells : should be <0> - -Example: - - iic0: i2c@e0070000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "renesas,iic-emev2"; - reg = <0xe0070000 0x28>; - interrupts = <0 32 IRQ_TYPE_EDGE_RISING>; - clocks = <&iic0_sclk>; - clock-names = "sclk"; - }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml b/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml new file mode 100644 index 000000000000..17c1102562be --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/renesas,iic-emev2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas EMMA Mobile EV2 IIC Interface + +maintainers: + - Wolfram Sang <wsa+renesas@sang-engineering.com> + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + const: renesas,iic-emev2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: sclk + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - '#address-cells' + - '#size-cells' + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + + iic0: i2c@e0070000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,iic-emev2"; + reg = <0xe0070000 0x28>; + interrupts = <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>; + clocks = <&iic0_sclk>; + clock-names = "sclk"; + }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,iic.txt b/Documentation/devicetree/bindings/i2c/renesas,iic.txt deleted file mode 100644 index 93d412832e66..000000000000 --- a/Documentation/devicetree/bindings/i2c/renesas,iic.txt +++ /dev/null @@ -1,72 +0,0 @@ -Device tree configuration for Renesas IIC (sh_mobile) driver - -Required properties: -- compatible : - - "renesas,iic-r8a73a4" (R-Mobile APE6) - - "renesas,iic-r8a7740" (R-Mobile A1) - - "renesas,iic-r8a7742" (RZ/G1H) - - "renesas,iic-r8a7743" (RZ/G1M) - - "renesas,iic-r8a7744" (RZ/G1N) - - "renesas,iic-r8a7745" (RZ/G1E) - - "renesas,iic-r8a774a1" (RZ/G2M) - - "renesas,iic-r8a774b1" (RZ/G2N) - - "renesas,iic-r8a774c0" (RZ/G2E) - - "renesas,iic-r8a774e1" (RZ/G2H) - - "renesas,iic-r8a7790" (R-Car H2) - - "renesas,iic-r8a7791" (R-Car M2-W) - - "renesas,iic-r8a7792" (R-Car V2H) - - "renesas,iic-r8a7793" (R-Car M2-N) - - "renesas,iic-r8a7794" (R-Car E2) - - "renesas,iic-r8a7795" (R-Car H3) - - "renesas,iic-r8a7796" (R-Car M3-W) - - "renesas,iic-r8a77961" (R-Car M3-W+) - - "renesas,iic-r8a77965" (R-Car M3-N) - - "renesas,iic-r8a77990" (R-Car E3) - - "renesas,iic-sh73a0" (SH-Mobile AG5) - - "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1 - compatible device) - - "renesas,rcar-gen3-iic" (generic R-Car Gen3 or RZ/G2 - compatible device) - - "renesas,rmobile-iic" (generic device) - - When compatible with a generic R-Car version, nodes - must list the SoC-specific version corresponding to - the platform first followed by the generic R-Car - version. - - When compatible with "renesas,rmobile-iic" it should - be the last compatibility string listed. - - The r8a77990 (R-Car E3) and r8a774c0 (RZ/G2E) - controllers are not considered compatible with - "renesas,rcar-gen3-iic" or "renesas,rmobile-iic" - due to the absence of automatic transmission registers. - -- reg : address start and address range size of device -- interrupts : interrupt of device -- clocks : clock for device -- #address-cells : should be <1> -- #size-cells : should be <0> - -Optional properties: -- clock-frequency : frequency of bus clock in Hz. Default 100kHz if unset. -- dmas : Must contain a list of two references to DMA - specifiers, one for transmission, and one for - reception. -- dma-names : Must contain a list of two DMA names, "tx" and "rx". - - -Pinctrl properties might be needed, too. See there. - -Example: - - iic0: i2c@e6500000 { - compatible = "renesas,iic-r8a7790", "renesas,rcar-gen2-iic", - "renesas,rmobile-iic"; - reg = <0 0xe6500000 0 0x425>; - interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp3_clks R8A7790_CLK_IIC0>; - clock-frequency = <400000>; - #address-cells = <1>; - #size-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml b/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml new file mode 100644 index 000000000000..052aad44e781 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml @@ -0,0 +1,158 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/renesas,rcar-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas R-Car I2C Controller + +maintainers: + - Wolfram Sang <wsa+renesas@sang-engineering.com> + +properties: + compatible: + oneOf: + - items: + - enum: + - renesas,i2c-r8a7778 # R-Car M1A + - renesas,i2c-r8a7779 # R-Car H1 + - const: renesas,rcar-gen1-i2c # R-Car Gen1 + + - items: + - enum: + - renesas,i2c-r8a7742 # RZ/G1H + - renesas,i2c-r8a7743 # RZ/G1M + - renesas,i2c-r8a7744 # RZ/G1N + - renesas,i2c-r8a7745 # RZ/G1E + - renesas,i2c-r8a77470 # RZ/G1C + - renesas,i2c-r8a7790 # R-Car H2 + - renesas,i2c-r8a7791 # R-Car M2-W + - renesas,i2c-r8a7792 # R-Car V2H + - renesas,i2c-r8a7793 # R-Car M2-N + - renesas,i2c-r8a7794 # R-Car E2 + - const: renesas,rcar-gen2-i2c # R-Car Gen2 and RZ/G1 + + - items: + - enum: + - renesas,i2c-r8a774a1 # RZ/G2M + - renesas,i2c-r8a774b1 # RZ/G2N + - renesas,i2c-r8a774c0 # RZ/G2E + - renesas,i2c-r8a774e1 # RZ/G2H + - renesas,i2c-r8a7795 # R-Car H3 + - renesas,i2c-r8a7796 # R-Car M3-W + - renesas,i2c-r8a77961 # R-Car M3-W+ + - renesas,i2c-r8a77965 # R-Car M3-N + - renesas,i2c-r8a77970 # R-Car V3M + - renesas,i2c-r8a77980 # R-Car V3H + - renesas,i2c-r8a77990 # R-Car E3 + - renesas,i2c-r8a77995 # R-Car D3 + - renesas,i2c-r8a779a0 # R-Car V3U + - const: renesas,rcar-gen3-i2c # R-Car Gen3 and RZ/G2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clock-frequency: + description: + Desired I2C bus clock frequency in Hz. The absence of this property + indicates the default frequency 100 kHz. + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + minItems: 2 + maxItems: 4 + description: + Must contain a list of pairs of references to DMA specifiers, one for + transmission, and one for reception. + + dma-names: + minItems: 2 + maxItems: 4 + items: + enum: + - tx + - rx + + i2c-scl-falling-time-ns: + default: 35 + description: + Number of nanoseconds the SCL signal takes to fall; t(f) in the I2C + specification. + + i2c-scl-internal-delay-ns: + default: 50 + description: + Number of nanoseconds the IP core additionally needs to setup SCL. + + i2c-scl-rising-time-ns: + default: 200 + description: + Number of nanoseconds the SCL signal takes to rise; t(r) in the I2C + specification. + +required: + - compatible + - reg + - interrupts + - clocks + - power-domains + - '#address-cells' + - '#size-cells' + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + + - if: + properties: + compatible: + contains: + enum: + - renesas,rcar-gen1-i2c + - renesas,rcar-gen2-i2c + then: + properties: + dmas: false + dma-names: false + + - if: + properties: + compatible: + contains: + enum: + - renesas,rcar-gen2-i2c + - renesas,rcar-gen3-i2c + then: + required: + - resets + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/r8a7791-cpg-mssr.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/r8a7791-sysc.h> + + i2c0: i2c@e6508000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a7791", "renesas,rcar-gen2-i2c"; + reg = <0xe6508000 0x40>; + interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <400000>; + clocks = <&cpg CPG_MOD 931>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; + resets = <&cpg 931>; + i2c-scl-internal-delay-ns = <6>; + }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,riic.txt b/Documentation/devicetree/bindings/i2c/renesas,riic.txt deleted file mode 100644 index e26fe3ad86a9..000000000000 --- a/Documentation/devicetree/bindings/i2c/renesas,riic.txt +++ /dev/null @@ -1,32 +0,0 @@ -Device tree configuration for Renesas RIIC driver - -Required properties: -- compatible : - "renesas,riic-r7s72100" if the device is a part of a R7S72100 SoC. - "renesas,riic-r7s9210" if the device is a part of a R7S9210 SoC. - "renesas,riic-rz" for a generic RZ/A compatible device. -- reg : address start and address range size of device -- interrupts : 8 interrupts (TEI, RI, TI, SPI, STI, NAKI, ALI, TMOI) -- clock-frequency : frequency of bus clock in Hz -- #address-cells : should be <1> -- #size-cells : should be <0> - -Pinctrl properties might be needed, too. See there. - -Example: - - i2c0: i2c@fcfee000 { - compatible = "renesas,riic-r7s72100", "renesas,riic-rz"; - reg = <0xfcfee000 0x44>; - interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>, - <0 158 IRQ_TYPE_EDGE_RISING>, - <0 159 IRQ_TYPE_EDGE_RISING>, - <0 160 IRQ_TYPE_LEVEL_HIGH>, - <0 161 IRQ_TYPE_LEVEL_HIGH>, - <0 162 IRQ_TYPE_LEVEL_HIGH>, - <0 163 IRQ_TYPE_LEVEL_HIGH>, - <0 164 IRQ_TYPE_LEVEL_HIGH>; - clock-frequency = <100000>; - #address-cells = <1>; - #size-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,riic.yaml b/Documentation/devicetree/bindings/i2c/renesas,riic.yaml new file mode 100644 index 000000000000..52d92ec7ec0b --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/renesas,riic.yaml @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/renesas,riic.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/A and RZ/G2L I2C Bus Interface (RIIC) + +maintainers: + - Chris Brandt <chris.brandt@renesas.com> + - Wolfram Sang <wsa+renesas@sang-engineering.com> + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + items: + - enum: + - renesas,riic-r7s72100 # RZ/A1H + - renesas,riic-r7s9210 # RZ/A2M + - renesas,riic-r9a07g044 # RZ/G2{L,LC} + - const: renesas,riic-rz # RZ/A or RZ/G2L + + reg: + maxItems: 1 + + interrupts: + items: + - description: Transmit End Interrupt (TEI) + - description: Receive Data Full Interrupt (RI) + - description: Transmit Data Empty Interrupt (TI) + - description: Stop Condition Detection Interrupt (SPI) + - description: Start Condition Detection Interrupt (STI) + - description: NACK Reception Interrupt (NAKI) + - description: Arbitration-Lost Interrupt (ALI) + - description: Timeout Interrupt (TMOI) + + clock-frequency: + description: + Desired I2C bus clock frequency in Hz. The absence of this property + indicates the default frequency 100 kHz. + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-frequency + - power-domains + - '#address-cells' + - '#size-cells' + +if: + properties: + compatible: + contains: + enum: + - renesas,riic-r9a07g044 +then: + required: + - resets + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/r7s72100-clock.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + i2c0: i2c@fcfee000 { + compatible = "renesas,riic-r7s72100", "renesas,riic-rz"; + reg = <0xfcfee000 0x44>; + interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 159 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp9_clks R7S72100_CLK_I2C0>; + clock-frequency = <100000>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml b/Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml new file mode 100644 index 000000000000..04e4ffd80bc0 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml @@ -0,0 +1,149 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/renesas,rmobile-iic.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas R-Mobile I2C Bus Interface (IIC) + +maintainers: + - Wolfram Sang <wsa+renesas@sang-engineering.com> + +properties: + compatible: + oneOf: + - items: + - enum: + - renesas,iic-r8a73a4 # R-Mobile APE6 + - renesas,iic-r8a7740 # R-Mobile A1 + - renesas,iic-sh73a0 # SH-Mobile AG5 + - const: renesas,rmobile-iic # Generic + + - items: + - enum: + - renesas,iic-r8a7742 # RZ/G1H + - renesas,iic-r8a7743 # RZ/G1M + - renesas,iic-r8a7744 # RZ/G1N + - renesas,iic-r8a7745 # RZ/G1E + - renesas,iic-r8a7790 # R-Car H2 + - renesas,iic-r8a7791 # R-Car M2-W + - renesas,iic-r8a7792 # R-Car V2H + - renesas,iic-r8a7793 # R-Car M2-N + - renesas,iic-r8a7794 # R-Car E2 + - const: renesas,rcar-gen2-iic # R-Car Gen2 and RZ/G1 + - const: renesas,rmobile-iic # Generic + + - items: + - enum: + - renesas,iic-r8a774a1 # RZ/G2M + - renesas,iic-r8a774b1 # RZ/G2N + - renesas,iic-r8a774c0 # RZ/G2E + - renesas,iic-r8a774e1 # RZ/G2H + - renesas,iic-r8a7795 # R-Car H3 + - renesas,iic-r8a7796 # R-Car M3-W + - renesas,iic-r8a77961 # R-Car M3-W+ + - renesas,iic-r8a77965 # R-Car M3-N + - renesas,iic-r8a77990 # R-Car E3 + - const: renesas,rcar-gen3-iic # R-Car Gen3 and RZ/G2 + - const: renesas,rmobile-iic # Generic + + reg: + maxItems: 1 + + interrupts: true + + clock-frequency: + description: + Desired I2C bus clock frequency in Hz. The absence of this property + indicates the default frequency 100 kHz. + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + minItems: 2 + maxItems: 4 + description: + Must contain a list of pairs of references to DMA specifiers, one for + transmission, and one for reception. + + dma-names: + minItems: 2 + maxItems: 4 + items: + enum: + - tx + - rx + +required: + - compatible + - reg + - interrupts + - clocks + - power-domains + - '#address-cells' + - '#size-cells' + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + + - if: + properties: + compatible: + contains: + enum: + - renesas,iic-r8a7740 + - renesas,iic-sh73a0 + then: + properties: + interrupts: + items: + - description: Arbitration Lost Interrupt (ALI) + - description: Non-acknowledge Detection Interrupt (TACKI) + - description: Wait Interrupt (WAITI) + - description: Data Transmit Enable interrupt (DTEI) + else: + properties: + interrupts: + items: + - description: Single combined interrupt + + - if: + properties: + compatible: + contains: + enum: + - renesas,rcar-gen2-iic + - renesas,rcar-gen3-iic + then: + required: + - resets + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/r8a7790-cpg-mssr.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/r8a7790-sysc.h> + + iic0: i2c@e6500000 { + compatible = "renesas,iic-r8a7790", "renesas,rcar-gen2-iic", + "renesas,rmobile-iic"; + reg = <0xe6500000 0x425>; + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 318>; + clock-frequency = <400000>; + dmas = <&dmac0 0x61>, <&dmac0 0x62>, <&dmac1 0x61>, <&dmac1 0x62>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 318>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml b/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml new file mode 100644 index 000000000000..ff165ad1bee8 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/ti,omap4-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bindings for I2C controllers on TI's OMAP and K3 SoCs + +maintainers: + - Vignesh Raghavendra <vigneshr@ti.com> + +properties: + compatible: + oneOf: + - enum: + - ti,omap2420-i2c + - ti,omap2430-i2c + - ti,omap3-i2c + - ti,omap4-i2c + - items: + - enum: + - ti,am4372-i2c + - ti,am64-i2c + - ti,am654-i2c + - ti,j721e-i2c + - const: ti,omap4-i2c + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: fck + + clock-frequency: true + + power-domains: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + ti,hwmods: + description: + Must be "i2c<n>", n being the instance number (1-based). + This property is applicable only on legacy platforms mainly omap2/3 + and ti81xx and should not be used on other platforms. + $ref: /schemas/types.yaml#/definitions/string + deprecated: true + +# subnode's properties +patternProperties: + "@[0-9a-f]+$": + type: object + description: + Flash device uses the below defined properties in the subnode. + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +if: + properties: + compatible: + oneOf: + - const: ti,omap2420-i2c + - const: ti,omap2430-i2c + - const: ti,omap3-i2c + - const: ti,omap4-i2c + +then: + properties: + ti,hwmods: + items: + - pattern: "^i2c([1-9])$" + +else: + properties: + ti,hwmods: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + main_i2c0: i2c@2000000 { + compatible = "ti,j721e-i2c", "ti,omap4-i2c"; + reg = <0x2000000 0x100>; + interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/i2c/i2c-sysfs.rst b/Documentation/i2c/i2c-sysfs.rst new file mode 100644 index 000000000000..6b68b95cd427 --- /dev/null +++ b/Documentation/i2c/i2c-sysfs.rst @@ -0,0 +1,395 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +Linux I2C Sysfs +=============== + +Overview +======== + +I2C topology can be complex because of the existence of I2C MUX +(I2C Multiplexer). The Linux +kernel abstracts the MUX channels into logical I2C bus numbers. However, there +is a gap of knowledge to map from the I2C bus physical number and MUX topology +to logical I2C bus number. This doc is aimed to fill in this gap, so the +audience (hardware engineers and new software developers for example) can learn +the concept of logical I2C buses in the kernel, by knowing the physical I2C +topology and navigating through the I2C sysfs in Linux shell. This knowledge is +useful and essential to use ``i2c-tools`` for the purpose of development and +debugging. + +Target audience +--------------- + +People who need to use Linux shell to interact with I2C subsystem on a system +which the Linux is running on. + +Prerequisites +------------- + +1. Knowledge of general Linux shell file system commands and operations. + +2. General knowledge of I2C, I2C MUX and I2C topology. + +Location of I2C Sysfs +===================== + +Typically, the Linux Sysfs filesystem is mounted at the ``/sys`` directory, +so you can find the I2C Sysfs under ``/sys/bus/i2c/devices`` +where you can directly ``cd`` to it. +There is a list of symbolic links under that directory. The links that +start with ``i2c-`` are I2C buses, which may be either physical or logical. The +other links that begin with numbers and end with numbers are I2C devices, where +the first number is I2C bus number, and the second number is I2C address. + +Google Pixel 3 phone for example:: + + blueline:/sys/bus/i2c/devices $ ls + 0-0008 0-0061 1-0028 3-0043 4-0036 4-0041 i2c-1 i2c-3 + 0-000c 0-0066 2-0049 4-000b 4-0040 i2c-0 i2c-2 i2c-4 + +``i2c-2`` is an I2C bus whose number is 2, and ``2-0049`` is an I2C device +on bus 2 address 0x49 bound with a kernel driver. + +Terminologies +============= + +First, let us define a couple of terminologies to avoid confusions in the later +sections. + +(Physical) I2C Bus Controller +----------------------------- + +The hardware system that the Linux kernel is running on may have multiple +physical I2C bus controllers. The controllers are hardware and physical, and the +system may define multiple registers in the memory space to manipulate the +controllers. Linux kernel has I2C bus drivers under source directory +``drivers/i2c/busses`` to translate kernel I2C API into register +operations for different systems. This terminology is not limited to Linux +kernel only. + +I2C Bus Physical Number +----------------------- + +For each physical I2C bus controller, the system vendor may assign a physical +number to each controller. For example, the first I2C bus controller which has +the lowest register addresses may be called ``I2C-0``. + +Logical I2C Bus +--------------- + +Every I2C bus number you see in Linux I2C Sysfs is a logical I2C bus with a +number assigned. This is similar to the fact that software code is usually +written upon virtual memory space, instead of physical memory space. + +Each logical I2C bus may be an abstraction of a physical I2C bus controller, or +an abstraction of a channel behind an I2C MUX. In case it is an abstraction of a +MUX channel, whenever we access an I2C device via a such logical bus, the kernel +will switch the I2C MUX for you to the proper channel as part of the +abstraction. + +Physical I2C Bus +---------------- + +If the logical I2C bus is a direct abstraction of a physical I2C bus controller, +let us call it a physical I2C bus. + +Caveat +------ + +This may be a confusing part for people who only know about the physical I2C +design of a board. It is actually possible to rename the I2C bus physical number +to a different number in logical I2C bus level in Device Tree Source (DTS) under +section ``aliases``. See +`arch/arm/boot/dts/nuvoton-npcm730-gsj.dts +<../../arch/arm/boot/dts/nuvoton-npcm730-gsj.dts>`_ +for an example of DTS file. + +Best Practice: **(To kernel software developers)** It is better to keep the I2C +bus physical number the same as their corresponding logical I2C bus number, +instead of renaming or mapping them, so that it may be less confusing to other +users. These physical I2C buses can be served as good starting points for I2C +MUX fanouts. For the following examples, we will assume that the physical I2C +bus has a number same as their I2C bus physical number. + +Walk through Logical I2C Bus +============================ + +For the following content, we will use a more complex I2C topology as an +example. Here is a brief graph for the I2C topology. If you do not understand +this graph at the first glance, do not be afraid to continue reading this doc +and review it when you finish reading. + +:: + + i2c-7 (physical I2C bus controller 7) + `-- 7-0071 (4-channel I2C MUX at 0x71) + |-- i2c-60 (channel-0) + |-- i2c-73 (channel-1) + | |-- 73-0040 (I2C sensor device with hwmon directory) + | |-- 73-0070 (I2C MUX at 0x70, exists in DTS, but failed to probe) + | `-- 73-0072 (8-channel I2C MUX at 0x72) + | |-- i2c-78 (channel-0) + | |-- ... (channel-1...6, i2c-79...i2c-84) + | `-- i2c-85 (channel-7) + |-- i2c-86 (channel-2) + `-- i2c-203 (channel-3) + +Distinguish Physical and Logical I2C Bus +---------------------------------------- + +One simple way to distinguish between a physical I2C bus and a logical I2C bus, +is to read the symbolic link ``device`` under the I2C bus directory by using +command ``ls -l`` or ``readlink``. + +An alternative symbolic link to check is ``mux_device``. This link only exists +in logical I2C bus directory which is fanned out from another I2C bus. +Reading this link will also tell you which I2C MUX device created +this logical I2C bus. + +If the symbolic link points to a directory ending with ``.i2c``, it should be a +physical I2C bus, directly abstracting a physical I2C bus controller. For +example:: + + $ readlink /sys/bus/i2c/devices/i2c-7/device + ../../f0087000.i2c + $ ls /sys/bus/i2c/devices/i2c-7/mux_device + ls: /sys/bus/i2c/devices/i2c-7/mux_device: No such file or directory + +In this case, ``i2c-7`` is a physical I2C bus, so it does not have the symbolic +link ``mux_device`` under its directory. And if the kernel software developer +follows the common practice by not renaming physical I2C buses, this should also +mean the physical I2C bus controller 7 of the system. + +On the other hand, if the symbolic link points to another I2C bus, the I2C bus +presented by the current directory has to be a logical bus. The I2C bus pointed +by the link is the parent bus which may be either a physical I2C bus or a +logical one. In this case, the I2C bus presented by the current directory +abstracts an I2C MUX channel under the parent bus. + +For example:: + + $ readlink /sys/bus/i2c/devices/i2c-73/device + ../../i2c-7 + $ readlink /sys/bus/i2c/devices/i2c-73/mux_device + ../7-0071 + +``i2c-73`` is a logical bus fanout by an I2C MUX under ``i2c-7`` +whose I2C address is 0x71. +Whenever we access an I2C device with bus 73, the kernel will always +switch the I2C MUX addressed 0x71 to the proper channel for you as part of the +abstraction. + +Finding out Logical I2C Bus Number +---------------------------------- + +In this section, we will describe how to find out the logical I2C bus number +representing certain I2C MUX channels based on the knowledge of physical +hardware I2C topology. + +In this example, we have a system which has a physical I2C bus 7 and not renamed +in DTS. There is a 4-channel MUX at address 0x71 on that bus. There is another +8-channel MUX at address 0x72 behind the channel 1 of the 0x71 MUX. Let us +navigate through Sysfs and find out the logical I2C bus number of the channel 3 +of the 0x72 MUX. + +First of all, let us go to the directory of ``i2c-7``:: + + ~$ cd /sys/bus/i2c/devices/i2c-7 + /sys/bus/i2c/devices/i2c-7$ ls + 7-0071 i2c-60 name subsystem + delete_device i2c-73 new_device uevent + device i2c-86 of_node + i2c-203 i2c-dev power + +There, we see the 0x71 MUX as ``7-0071``. Go inside it:: + + /sys/bus/i2c/devices/i2c-7$ cd 7-0071/ + /sys/bus/i2c/devices/i2c-7/7-0071$ ls -l + channel-0 channel-3 modalias power + channel-1 driver name subsystem + channel-2 idle_state of_node uevent + +Read the link ``channel-1`` using ``readlink`` or ``ls -l``:: + + /sys/bus/i2c/devices/i2c-7/7-0071$ readlink channel-1 + ../i2c-73 + +We find out that the channel 1 of 0x71 MUX on ``i2c-7`` is assigned +with a logical I2C bus number of 73. +Let us continue the journey to directory ``i2c-73`` in either ways:: + + # cd to i2c-73 under I2C Sysfs root + /sys/bus/i2c/devices/i2c-7/7-0071$ cd /sys/bus/i2c/devices/i2c-73 + /sys/bus/i2c/devices/i2c-73$ + + # cd the channel symbolic link + /sys/bus/i2c/devices/i2c-7/7-0071$ cd channel-1 + /sys/bus/i2c/devices/i2c-7/7-0071/channel-1$ + + # cd the link content + /sys/bus/i2c/devices/i2c-7/7-0071$ cd ../i2c-73 + /sys/bus/i2c/devices/i2c-7/i2c-73$ + +Either ways, you will end up in the directory of ``i2c-73``. Similar to above, +we can now find the 0x72 MUX and what logical I2C bus numbers +that its channels are assigned:: + + /sys/bus/i2c/devices/i2c-73$ ls + 73-0040 device i2c-83 new_device + 73-004e i2c-78 i2c-84 of_node + 73-0050 i2c-79 i2c-85 power + 73-0070 i2c-80 i2c-dev subsystem + 73-0072 i2c-81 mux_device uevent + delete_device i2c-82 name + /sys/bus/i2c/devices/i2c-73$ cd 73-0072 + /sys/bus/i2c/devices/i2c-73/73-0072$ ls + channel-0 channel-4 driver of_node + channel-1 channel-5 idle_state power + channel-2 channel-6 modalias subsystem + channel-3 channel-7 name uevent + /sys/bus/i2c/devices/i2c-73/73-0072$ readlink channel-3 + ../i2c-81 + +There, we find out the logical I2C bus number of the channel 3 of the 0x72 MUX +is 81. We can later use this number to switch to its own I2C Sysfs directory or +issue ``i2c-tools`` commands. + +Tip: Once you understand the I2C topology with MUX, command +`i2cdetect -l +<https://manpages.debian.org/unstable/i2c-tools/i2cdetect.8.en.html>`_ +in +`I2C Tools +<https://i2c.wiki.kernel.org/index.php/I2C_Tools>`_ +can give you +an overview of the I2C topology easily, if it is available on your system. For +example:: + + $ i2cdetect -l | grep -e '\-73' -e _7 | sort -V + i2c-7 i2c npcm_i2c_7 I2C adapter + i2c-73 i2c i2c-7-mux (chan_id 1) I2C adapter + i2c-78 i2c i2c-73-mux (chan_id 0) I2C adapter + i2c-79 i2c i2c-73-mux (chan_id 1) I2C adapter + i2c-80 i2c i2c-73-mux (chan_id 2) I2C adapter + i2c-81 i2c i2c-73-mux (chan_id 3) I2C adapter + i2c-82 i2c i2c-73-mux (chan_id 4) I2C adapter + i2c-83 i2c i2c-73-mux (chan_id 5) I2C adapter + i2c-84 i2c i2c-73-mux (chan_id 6) I2C adapter + i2c-85 i2c i2c-73-mux (chan_id 7) I2C adapter + +Pinned Logical I2C Bus Number +----------------------------- + +If not specified in DTS, when an I2C MUX driver is applied and the MUX device is +successfully probed, the kernel will assign the MUX channels with a logical bus +number based on the current biggest logical bus number incrementally. For +example, if the system has ``i2c-15`` as the highest logical bus number, and a +4-channel MUX is applied successfully, we will have ``i2c-16`` for the +MUX channel 0, and all the way to ``i2c-19`` for the MUX channel 3. + +The kernel software developer is able to pin the fanout MUX channels to a static +logical I2C bus number in the DTS. This doc will not go through the details on +how to implement this in DTS, but we can see an example in: +`arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts +<../../arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts>`_ + +In the above example, there is an 8-channel I2C MUX at address 0x70 on physical +I2C bus 2. The channel 2 of the MUX is defined as ``imux18`` in DTS, +and pinned to logical I2C bus number 18 with the line of ``i2c18 = &imux18;`` +in section ``aliases``. + +Take it further, it is possible to design a logical I2C bus number schema that +can be easily remembered by humans or calculated arithmetically. For example, we +can pin the fanout channels of a MUX on bus 3 to start at 30. So 30 will be the +logical bus number of the channel 0 of the MUX on bus 3, and 37 will be the +logical bus number of the channel 7 of the MUX on bus 3. + +I2C Devices +=========== + +In previous sections, we mostly covered the I2C bus. In this section, let us see +what we can learn from the I2C device directory whose link name is in the format +of ``${bus}-${addr}``. The ``${bus}`` part in the name is a logical I2C bus +decimal number, while the ``${addr}`` part is a hex number of the I2C address +of each device. + +I2C Device Directory Content +---------------------------- + +Inside each I2C device directory, there is a file named ``name``. +This file tells what device name it was used for the kernel driver to +probe this device. Use command ``cat`` to read its content. For example:: + + /sys/bus/i2c/devices/i2c-73$ cat 73-0040/name + ina230 + /sys/bus/i2c/devices/i2c-73$ cat 73-0070/name + pca9546 + /sys/bus/i2c/devices/i2c-73$ cat 73-0072/name + pca9547 + +There is a symbolic link named ``driver`` to tell what Linux kernel driver was +used to probe this device:: + + /sys/bus/i2c/devices/i2c-73$ readlink -f 73-0040/driver + /sys/bus/i2c/drivers/ina2xx + /sys/bus/i2c/devices/i2c-73$ readlink -f 73-0072/driver + /sys/bus/i2c/drivers/pca954x + +But if the link ``driver`` does not exist at the first place, +it may mean that the kernel driver failed to probe this device due to +some errors. The error may be found in ``dmesg``:: + + /sys/bus/i2c/devices/i2c-73$ ls 73-0070/driver + ls: 73-0070/driver: No such file or directory + /sys/bus/i2c/devices/i2c-73$ dmesg | grep 73-0070 + pca954x 73-0070: probe failed + pca954x 73-0070: probe failed + +Depending on what the I2C device is and what kernel driver was used to probe the +device, we may have different content in the device directory. + +I2C MUX Device +-------------- + +While you may be already aware of this in previous sections, an I2C MUX device +will have symbolic link ``channel-*`` inside its device directory. +These symbolic links point to their logical I2C bus directories:: + + /sys/bus/i2c/devices/i2c-73$ ls -l 73-0072/channel-* + lrwxrwxrwx ... 73-0072/channel-0 -> ../i2c-78 + lrwxrwxrwx ... 73-0072/channel-1 -> ../i2c-79 + lrwxrwxrwx ... 73-0072/channel-2 -> ../i2c-80 + lrwxrwxrwx ... 73-0072/channel-3 -> ../i2c-81 + lrwxrwxrwx ... 73-0072/channel-4 -> ../i2c-82 + lrwxrwxrwx ... 73-0072/channel-5 -> ../i2c-83 + lrwxrwxrwx ... 73-0072/channel-6 -> ../i2c-84 + lrwxrwxrwx ... 73-0072/channel-7 -> ../i2c-85 + +I2C Sensor Device / Hwmon +------------------------- + +I2C sensor device is also common to see. If they are bound by a kernel hwmon +(Hardware Monitoring) driver successfully, you will see a ``hwmon`` directory +inside the I2C device directory. Keep digging into it, you will find the Hwmon +Sysfs for the I2C sensor device:: + + /sys/bus/i2c/devices/i2c-73/73-0040/hwmon/hwmon17$ ls + curr1_input in0_lcrit_alarm name subsystem + device in1_crit power uevent + in0_crit in1_crit_alarm power1_crit update_interval + in0_crit_alarm in1_input power1_crit_alarm + in0_input in1_lcrit power1_input + in0_lcrit in1_lcrit_alarm shunt_resistor + +For more info on the Hwmon Sysfs, refer to the doc: + +`Naming and data format standards for sysfs files +<../hwmon/sysfs-interface.rst>`_ + +Instantiate I2C Devices in I2C Sysfs +------------------------------------ + +Refer to the doc: + +`How to instantiate I2C devices, Method 4: Instantiate from user-space +<instantiating-devices.rst#method-4-instantiate-from-user-space>`_ diff --git a/MAINTAINERS b/MAINTAINERS index fe901f384234..3ccd3b0d7832 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13494,7 +13494,7 @@ M: Vignesh R <vigneshr@ti.com> L: linux-omap@vger.kernel.org L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/i2c/i2c-omap.txt +F: Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml F: drivers/i2c/busses/i2c-omap.c OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS) @@ -15722,8 +15722,9 @@ F: drivers/clk/renesas/ RENESAS EMEV2 I2C DRIVER M: Wolfram Sang <wsa+renesas@sang-engineering.com> +L: linux-renesas-soc@vger.kernel.org S: Supported -F: Documentation/devicetree/bindings/i2c/renesas,iic-emev2.txt +F: Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml F: drivers/i2c/busses/i2c-emev2.c RENESAS ETHERNET DRIVERS @@ -15743,9 +15744,10 @@ F: drivers/iio/adc/rcar-gyroadc.c RENESAS R-CAR I2C DRIVERS M: Wolfram Sang <wsa+renesas@sang-engineering.com> +L: linux-renesas-soc@vger.kernel.org S: Supported -F: Documentation/devicetree/bindings/i2c/renesas,i2c.txt -F: Documentation/devicetree/bindings/i2c/renesas,iic.txt +F: Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml +F: Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml F: drivers/i2c/busses/i2c-rcar.c F: drivers/i2c/busses/i2c-sh_mobile.c @@ -15760,8 +15762,9 @@ F: drivers/thermal/rcar_thermal.c RENESAS RIIC DRIVER M: Chris Brandt <chris.brandt@renesas.com> +L: linux-renesas-soc@vger.kernel.org S: Supported -F: Documentation/devicetree/bindings/i2c/renesas,riic.txt +F: Documentation/devicetree/bindings/i2c/renesas,riic.yaml F: drivers/i2c/busses/i2c-riic.c RENESAS USB PHY DRIVER diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index fb93152845f4..ee83c4581bce 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -508,6 +508,11 @@ static void ali1535_remove(struct pci_dev *dev) { i2c_del_adapter(&ali1535_adapter); release_region(ali1535_smba, ALI1535_SMB_IOSIZE); + + /* + * do not call pci_disable_device(dev) since it can cause hard hangs on + * some systems during power-off + */ } static struct pci_driver ali1535_driver = { diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 724bf30600d6..67e8b97c0c95 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -727,10 +727,14 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr) { u32 addr_reg_val, func_ctrl_reg_val; - /* Set slave addr. */ - addr_reg_val = readl(bus->base + ASPEED_I2C_DEV_ADDR_REG); - addr_reg_val &= ~ASPEED_I2CD_DEV_ADDR_MASK; - addr_reg_val |= slave_addr & ASPEED_I2CD_DEV_ADDR_MASK; + /* + * Set slave addr. Reserved bits can all safely be written with zeros + * on all of ast2[456]00, so zero everything else to ensure we only + * enable a single slave address (ast2500 has two, ast2600 has three, + * the enable bits for which are also in this register) so that we don't + * end up with additional phantom devices responding on the bus. + */ + addr_reg_val = slave_addr & ASPEED_I2CD_DEV_ADDR_MASK; writel(addr_reg_val, bus->base + ASPEED_I2C_DEV_ADDR_REG); /* Turn on slave mode. */ diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 66aafa7d1123..20aa3398e642 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -578,6 +578,11 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) { unsigned int ctrl_reg; unsigned int isr_status; + unsigned long flags; + bool hold_clear = false; + bool irq_save = false; + + u32 addr; id->p_recv_buf = id->p_msg->buf; id->recv_count = id->p_msg->len; @@ -618,14 +623,43 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) cdns_i2c_writereg(id->recv_count, CDNS_I2C_XFER_SIZE_OFFSET); } - /* Set the slave address in address register - triggers operation */ - cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, - CDNS_I2C_ADDR_OFFSET); - /* Clear the bus hold flag if bytes to receive is less than FIFO size */ + /* Determine hold_clear based on number of bytes to receive and hold flag */ if (!id->bus_hold_flag && - ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) && - (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) - cdns_i2c_clear_bus_hold(id); + ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) && + (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) { + if (cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & CDNS_I2C_CR_HOLD) { + hold_clear = true; + if (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) + irq_save = true; + } + } + + addr = id->p_msg->addr; + addr &= CDNS_I2C_ADDR_MASK; + + if (hold_clear) { + ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & ~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 + * register overflow to 0xFF. To satisfy this timing requirement, + * disable the interrupts on current processor core between register + * writes to slave address register and control register. + */ + if (irq_save) + local_irq_save(flags); + + cdns_i2c_writereg(addr, CDNS_I2C_ADDR_OFFSET); + cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); + /* Read it back to avoid bufferring and make sure write happens */ + cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + + if (irq_save) + local_irq_restore(flags); + } else { + cdns_i2c_writereg(addr, CDNS_I2C_ADDR_OFFSET); + } + cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET); } @@ -1217,11 +1251,10 @@ static int cdns_i2c_probe(struct platform_device *pdev) "Cadence I2C at %08lx", (unsigned long)r_mem->start); id->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(id->clk)) { - if (PTR_ERR(id->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "input clock not found.\n"); - return PTR_ERR(id->clk); - } + if (IS_ERR(id->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(id->clk), + "input clock not found.\n"); + ret = clk_prepare_enable(id->clk); if (ret) dev_err(&pdev->dev, "Unable to enable clock.\n"); diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 08f491ea21ac..1cf68f85b2e1 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -354,8 +354,7 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) return ret; /* Alloc and register client IRQ */ - adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1, - &irq_domain_simple_ops, NULL); + adap->irq_domain = irq_domain_add_linear(NULL, 1, &irq_domain_simple_ops, NULL); if (!adap->irq_domain) return -ENOMEM; diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 232a7679b69b..e9d07323c604 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -768,10 +768,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) if (irq <= 0) { if (!irq) irq = -ENXIO; - if (irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "can't get irq resource ret=%d\n", irq); - return irq; + return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n"); } dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev), diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 04a1e38f2a6f..aa3f60e69230 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -88,6 +88,8 @@ * See the file Documentation/i2c/busses/i2c-i801.rst for details. */ +#define DRV_NAME "i801_smbus" + #include <linux/interrupt.h> #include <linux/module.h> #include <linux/pci.h> @@ -103,7 +105,7 @@ #include <linux/dmi.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/wait.h> +#include <linux/completion.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/platform_data/itco_wdt.h> @@ -131,8 +133,6 @@ /* PCI Address Constants */ #define SMBBAR 4 -#define SMBPCICTL 0x004 -#define SMBPCISTS 0x006 #define SMBHSTCFG 0x040 #define TCOBASE 0x050 #define TCOCTL 0x054 @@ -141,12 +141,6 @@ #define SBREG_SMBCTRL 0xc6000c #define SBREG_SMBCTRL_DNV 0xcf000c -/* Host status bits for SMBPCISTS */ -#define SMBPCISTS_INTS BIT(3) - -/* Control bits for SMBPCICTL */ -#define SMBPCICTL_INTDIS BIT(10) - /* Host configuration bits for SMBHSTCFG */ #define SMBHSTCFG_HST_EN BIT(0) #define SMBHSTCFG_SMB_SMI_EN BIT(1) @@ -164,9 +158,6 @@ #define SMBAUXCTL_CRC BIT(0) #define SMBAUXCTL_E32B BIT(1) -/* Other settings */ -#define MAX_RETRIES 400 - /* I801 command constants */ #define I801_QUICK 0x00 #define I801_BYTE 0x04 @@ -270,7 +261,7 @@ struct i801_priv { unsigned int features; /* isr processing */ - wait_queue_head_t waitq; + struct completion done; u8 status; /* Command state used by isr for byte-by-byte block transactions */ @@ -453,67 +444,53 @@ static int i801_check_post(struct i801_priv *priv, int status) /* Wait for BUSY being cleared and either INTR or an error flag being set */ static int i801_wait_intr(struct i801_priv *priv) { - int timeout = 0; - int status; + unsigned long timeout = jiffies + priv->adapter.timeout; + int status, busy; - /* We will always wait for a fraction of a second! */ do { usleep_range(250, 500); status = inb_p(SMBHSTSTS(priv)); - } while (((status & SMBHSTSTS_HOST_BUSY) || - !(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) && - (timeout++ < MAX_RETRIES)); + busy = status & SMBHSTSTS_HOST_BUSY; + status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; + if (!busy && status) + return status; + } while (time_is_after_eq_jiffies(timeout)); - if (timeout > MAX_RETRIES) { - dev_dbg(&priv->pci_dev->dev, "INTR Timeout!\n"); - return -ETIMEDOUT; - } - return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR); + return -ETIMEDOUT; } /* Wait for either BYTE_DONE or an error flag being set */ static int i801_wait_byte_done(struct i801_priv *priv) { - int timeout = 0; + unsigned long timeout = jiffies + priv->adapter.timeout; int status; - /* We will always wait for a fraction of a second! */ do { usleep_range(250, 500); status = inb_p(SMBHSTSTS(priv)); - } while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) && - (timeout++ < MAX_RETRIES)); + if (status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) + return status & STATUS_ERROR_FLAGS; + } while (time_is_after_eq_jiffies(timeout)); - if (timeout > MAX_RETRIES) { - dev_dbg(&priv->pci_dev->dev, "BYTE_DONE Timeout!\n"); - return -ETIMEDOUT; - } - return status & STATUS_ERROR_FLAGS; + return -ETIMEDOUT; } static int i801_transaction(struct i801_priv *priv, int xact) { int status; - int result; + unsigned long result; const struct i2c_adapter *adap = &priv->adapter; - result = i801_check_pre(priv); - if (result < 0) - return result; + status = i801_check_pre(priv); + if (status < 0) + return status; if (priv->features & FEATURE_IRQ) { + reinit_completion(&priv->done); outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START, SMBHSTCNT(priv)); - result = wait_event_timeout(priv->waitq, - (status = priv->status), - adap->timeout); - if (!result) { - status = -ETIMEDOUT; - dev_warn(&priv->pci_dev->dev, - "Timeout waiting for interrupt!\n"); - } - priv->status = 0; - return i801_check_post(priv, status); + result = wait_for_completion_timeout(&priv->done, adap->timeout); + return i801_check_post(priv, result ? priv->status : -ETIMEDOUT); } /* the current contents of SMBHSTCNT can be overwritten, since PEC, @@ -638,7 +615,7 @@ static irqreturn_t i801_host_notify_isr(struct i801_priv *priv) * DEV_ERR - Invalid command, NAK or communication timeout * BUS_ERR - SMI# transaction collision * FAILED - transaction was canceled due to a KILL request - * When any of these occur, update ->status and wake up the waitq. + * When any of these occur, update ->status and signal completion. * ->status must be cleared before kicking off the next transaction. * * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt @@ -653,8 +630,8 @@ static irqreturn_t i801_isr(int irq, void *dev_id) u8 status; /* Confirm this is our interrupt */ - pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists); - if (!(pcists & SMBPCISTS_INTS)) + pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); + if (!(pcists & PCI_STATUS_INTERRUPT)) return IRQ_NONE; if (priv->features & FEATURE_HOST_NOTIFY) { @@ -675,7 +652,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id) if (status) { outb_p(status, SMBHSTSTS(priv)); priv->status = status; - wake_up(&priv->waitq); + complete(&priv->done); } return IRQ_HANDLED; @@ -694,15 +671,15 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, int i, len; int smbcmd; int status; - int result; + unsigned long result; const struct i2c_adapter *adap = &priv->adapter; if (command == I2C_SMBUS_BLOCK_PROC_CALL) return -EOPNOTSUPP; - result = i801_check_pre(priv); - if (result < 0) - return result; + status = i801_check_pre(priv); + if (status < 0) + return status; len = data->block[0]; @@ -726,17 +703,10 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, priv->count = 0; priv->data = &data->block[1]; + reinit_completion(&priv->done); outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); - result = wait_event_timeout(priv->waitq, - (status = priv->status), - adap->timeout); - if (!result) { - status = -ETIMEDOUT; - dev_warn(&priv->pci_dev->dev, - "Timeout waiting for interrupt!\n"); - } - priv->status = 0; - return i801_check_post(priv, status); + result = wait_for_completion_timeout(&priv->done, adap->timeout); + return i801_check_post(priv, result ? priv->status : -ETIMEDOUT); } for (i = 1; i <= len; i++) { @@ -1322,11 +1292,11 @@ static void i801_probe_optional_slaves(struct i801_priv *priv) return; if (apanel_addr) { - struct i2c_board_info info; + struct i2c_board_info info = { + .addr = apanel_addr, + .type = "fujitsu_apanel", + }; - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = apanel_addr; - strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE); i2c_new_client_device(&priv->adapter, &info); } @@ -1715,19 +1685,17 @@ static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; } static inline void i801_acpi_remove(struct i801_priv *priv) { } #endif -static unsigned char i801_setup_hstcfg(struct i801_priv *priv) +static void i801_setup_hstcfg(struct i801_priv *priv) { unsigned char hstcfg = priv->original_hstcfg; hstcfg &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ hstcfg |= SMBHSTCFG_HST_EN; pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg); - return hstcfg; } static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { - unsigned char temp; int err, i; struct i801_priv *priv; @@ -1838,8 +1806,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) if (i801_acpi_probe(priv)) return -ENODEV; - err = pcim_iomap_regions(dev, 1 << SMBBAR, - dev_driver_string(&dev->dev)); + err = pcim_iomap_regions(dev, 1 << SMBBAR, DRV_NAME); if (err) { dev_err(&dev->dev, "Failed to request SMBus region 0x%lx-0x%Lx\n", @@ -1850,16 +1817,16 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) } pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &priv->original_hstcfg); - temp = i801_setup_hstcfg(priv); + i801_setup_hstcfg(priv); if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN)) dev_info(&dev->dev, "Enabling SMBus device\n"); - if (temp & SMBHSTCFG_SMB_SMI_EN) { + if (priv->original_hstcfg & SMBHSTCFG_SMB_SMI_EN) { dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); /* Disable SMBus interrupt feature if SMBus using SMI# */ priv->features &= ~FEATURE_IRQ; } - if (temp & SMBHSTCFG_SPD_WD) + if (priv->original_hstcfg & SMBHSTCFG_SPD_WD) dev_info(&dev->dev, "SPD Write Disable is set\n"); /* Clear special mode bits */ @@ -1881,24 +1848,23 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) u16 pcictl, pcists; /* Complain if an interrupt is already pending */ - pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists); - if (pcists & SMBPCISTS_INTS) + pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); + if (pcists & PCI_STATUS_INTERRUPT) dev_warn(&dev->dev, "An interrupt is pending!\n"); /* Check if interrupts have been disabled */ - pci_read_config_word(priv->pci_dev, SMBPCICTL, &pcictl); - if (pcictl & SMBPCICTL_INTDIS) { + pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pcictl); + if (pcictl & PCI_COMMAND_INTX_DISABLE) { dev_info(&dev->dev, "Interrupts are disabled\n"); priv->features &= ~FEATURE_IRQ; } } if (priv->features & FEATURE_IRQ) { - init_waitqueue_head(&priv->waitq); + init_completion(&priv->done); err = devm_request_irq(&dev->dev, dev->irq, i801_isr, - IRQF_SHARED, - dev_driver_string(&dev->dev), priv); + IRQF_SHARED, DRV_NAME, priv); if (err) { dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", dev->irq, err); @@ -1988,7 +1954,7 @@ static int i801_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume); static struct pci_driver i801_driver = { - .name = "i801_smbus", + .name = DRV_NAME, .id_table = i801_ids, .probe = i801_probe, .remove = i801_remove, diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dc5ca71906db..d5b5f084a27d 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -170,11 +170,11 @@ enum imx_i2c_type { struct imx_i2c_hwdata { enum imx_i2c_type devtype; - unsigned regshift; + unsigned int regshift; struct imx_i2c_clk_pair *clk_div; - unsigned ndivs; - unsigned i2sr_clr_opcode; - unsigned i2cr_ien_opcode; + unsigned int ndivs; + unsigned int i2sr_clr_opcode; + unsigned int i2cr_ien_opcode; }; struct imx_i2c_dma { @@ -452,8 +452,6 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a unsigned long orig_jiffies = jiffies; unsigned int temp; - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - while (1) { temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); @@ -599,8 +597,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic) unsigned int temp = 0; int result; - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); /* Enable I2C controller */ imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); @@ -635,7 +631,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic) if (!i2c_imx->stopped) { /* Stop I2C transaction */ - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); if (!(temp & I2CR_MSTA)) i2c_imx->stopped = 1; @@ -1167,8 +1162,6 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter, bool is_lastmsg = false; struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - /* Start I2C transfer */ result = i2c_imx_start(i2c_imx, atomic); if (result) { @@ -1371,8 +1364,6 @@ static int i2c_imx_probe(struct platform_device *pdev) dma_addr_t phy_addr; const struct imx_i2c_hwdata *match; - dev_dbg(&pdev->dev, "<%s>\n", __func__); - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -1395,7 +1386,7 @@ static int i2c_imx_probe(struct platform_device *pdev) platform_get_device_id(pdev)->driver_data; /* Setup i2c_imx driver structure */ - strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); + strscpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); i2c_imx->adapter.owner = THIS_MODULE; i2c_imx->adapter.algo = &i2c_imx_algo; i2c_imx->adapter.dev.parent = &pdev->dev; diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index dcca9c2396db..6d5014ebaab5 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -635,6 +635,8 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) status = readb(i2c->base + MPC_I2C_SR); if (status & CSR_MIF) { + /* Read again to allow register to stabilise */ + status = readb(i2c->base + MPC_I2C_SR); writeb(0, i2c->base + MPC_I2C_SR); mpc_i2c_do_intr(i2c, status); return IRQ_HANDLED; diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 4e9fb6b44436..4ca716e09149 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -1225,6 +1225,13 @@ static int mtk_i2c_probe(struct platform_device *pdev) i2c->adap.quirks = i2c->dev_comp->quirks; i2c->adap.timeout = 2 * HZ; i2c->adap.retries = 1; + i2c->adap.bus_regulator = devm_regulator_get_optional(&pdev->dev, "vbus"); + if (IS_ERR(i2c->adap.bus_regulator)) { + if (PTR_ERR(i2c->adap.bus_regulator) == -ENODEV) + i2c->adap.bus_regulator = NULL; + else + return PTR_ERR(i2c->adap.bus_regulator); + } ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c); if (ret) @@ -1286,7 +1293,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq, IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE, - I2C_DRV_NAME, i2c); + dev_name(&pdev->dev), i2c); if (ret < 0) { dev_err(&pdev->dev, "Request I2C IRQ %d fail\n", irq); diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index c63d5545fc2a..c1de8eb66169 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -769,6 +769,7 @@ static const struct of_device_id cci_dt_match[] = { { .compatible = "qcom,msm8916-cci", .data = &cci_v1_data}, { .compatible = "qcom,msm8996-cci", .data = &cci_v2_data}, { .compatible = "qcom,sdm845-cci", .data = &cci_v2_data}, + { .compatible = "qcom,sm8250-cci", .data = &cci_v2_data}, {} }; MODULE_DEVICE_TABLE(of, cci_dt_match); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 327c092a4130..bff9913c37b8 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -1013,7 +1013,6 @@ static const struct of_device_id rcar_i2c_dt_ids[] = { { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, - { .compatible = "renesas,i2c-rcar", .data = (void *)I2C_RCAR_GEN1 }, /* Deprecated */ { .compatible = "renesas,rcar-gen1-i2c", .data = (void *)I2C_RCAR_GEN1 }, { .compatible = "renesas,rcar-gen2-i2c", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,rcar-gen3-i2c", .data = (void *)I2C_RCAR_GEN3 }, diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 4eccc0f69861..78b84445ee6a 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -42,8 +42,10 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/reset.h> #define RIIC_ICCR1 0x00 #define RIIC_ICCR2 0x04 @@ -86,6 +88,11 @@ #define RIIC_INIT_MSG -1 +enum riic_type { + RIIC_RZ_A, + RIIC_RZ_G2L, +}; + struct riic_dev { void __iomem *base; u8 *buf; @@ -395,7 +402,9 @@ static int riic_i2c_probe(struct platform_device *pdev) struct i2c_adapter *adap; struct resource *res; struct i2c_timings i2c_t; + struct reset_control *rstc; int i, ret; + enum riic_type type; riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); if (!riic) @@ -412,6 +421,17 @@ static int riic_i2c_probe(struct platform_device *pdev) return PTR_ERR(riic->clk); } + type = (enum riic_type)of_device_get_match_data(&pdev->dev); + if (type == RIIC_RZ_G2L) { + rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(rstc)) { + dev_err(&pdev->dev, "Error: missing reset ctrl\n"); + return PTR_ERR(rstc); + } + + reset_control_deassert(rstc); + } + for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { res = platform_get_resource(pdev, IORESOURCE_IRQ, riic_irqs[i].res_num); if (!res) @@ -472,7 +492,8 @@ static int riic_i2c_remove(struct platform_device *pdev) } static const struct of_device_id riic_i2c_dt_ids[] = { - { .compatible = "renesas,riic-rz" }, + { .compatible = "renesas,riic-r9a07g044", .data = (void *)RIIC_RZ_G2L }, + { .compatible = "renesas,riic-rz", .data = (void *)RIIC_RZ_A }, { /* Sentinel */ }, }; diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 0138317ea600..b9b19a2a2ffa 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -51,6 +51,7 @@ /* STM32F7 I2C control 1 */ #define STM32F7_I2C_CR1_PECEN BIT(23) +#define STM32F7_I2C_CR1_ALERTEN BIT(22) #define STM32F7_I2C_CR1_SMBHEN BIT(20) #define STM32F7_I2C_CR1_WUPEN BIT(18) #define STM32F7_I2C_CR1_SBC BIT(16) @@ -125,6 +126,7 @@ (((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17) #define STM32F7_I2C_ISR_DIR BIT(16) #define STM32F7_I2C_ISR_BUSY BIT(15) +#define STM32F7_I2C_ISR_ALERT BIT(13) #define STM32F7_I2C_ISR_PECERR BIT(11) #define STM32F7_I2C_ISR_ARLO BIT(9) #define STM32F7_I2C_ISR_BERR BIT(8) @@ -138,6 +140,7 @@ #define STM32F7_I2C_ISR_TXE BIT(0) /* STM32F7 I2C Interrupt Clear */ +#define STM32F7_I2C_ICR_ALERTCF BIT(13) #define STM32F7_I2C_ICR_PECCF BIT(11) #define STM32F7_I2C_ICR_ARLOCF BIT(9) #define STM32F7_I2C_ICR_BERRCF BIT(8) @@ -279,6 +282,17 @@ struct stm32f7_i2c_msg { }; /** + * struct stm32f7_i2c_alert - SMBus alert specific data + * @setup: platform data for the smbus_alert i2c client + * @ara: I2C slave device used to respond to the SMBus Alert with Alert + * Response Address + */ +struct stm32f7_i2c_alert { + struct i2c_smbus_alert_setup setup; + struct i2c_client *ara; +}; + +/** * struct stm32f7_i2c_dev - private data of the controller * @adap: I2C adapter for this controller * @dev: device for this controller @@ -310,6 +324,7 @@ struct stm32f7_i2c_msg { * @analog_filter: boolean to indicate enabling of the analog filter * @dnf_dt: value of digital filter requested via dt * @dnf: value of digital filter to apply + * @alert: SMBus alert specific data */ struct stm32f7_i2c_dev { struct i2c_adapter adap; @@ -341,6 +356,7 @@ struct stm32f7_i2c_dev { bool analog_filter; u32 dnf_dt; u32 dnf; + struct stm32f7_i2c_alert *alert; }; /* @@ -1624,6 +1640,13 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) f7_msg->result = -EINVAL; } + if (status & STM32F7_I2C_ISR_ALERT) { + dev_dbg(dev, "<%s>: SMBus alert received\n", __func__); + writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR); + i2c_handle_smbus_alert(i2c_dev->alert->ara); + return IRQ_HANDLED; + } + if (!i2c_dev->slave_running) { u32 mask; /* Disable interrupts */ @@ -1990,6 +2013,42 @@ static void stm32f7_i2c_disable_smbus_host(struct stm32f7_i2c_dev *i2c_dev) } } +static int stm32f7_i2c_enable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) +{ + struct stm32f7_i2c_alert *alert; + struct i2c_adapter *adap = &i2c_dev->adap; + struct device *dev = i2c_dev->dev; + void __iomem *base = i2c_dev->base; + + alert = devm_kzalloc(dev, sizeof(*alert), GFP_KERNEL); + if (!alert) + return -ENOMEM; + + alert->ara = i2c_new_smbus_alert_device(adap, &alert->setup); + if (IS_ERR(alert->ara)) + return PTR_ERR(alert->ara); + + i2c_dev->alert = alert; + + /* Enable SMBus Alert */ + stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_ALERTEN); + + return 0; +} + +static void stm32f7_i2c_disable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) +{ + struct stm32f7_i2c_alert *alert = i2c_dev->alert; + void __iomem *base = i2c_dev->base; + + if (alert) { + /* Disable SMBus Alert */ + stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, + STM32F7_I2C_CR1_ALERTEN); + i2c_unregister_device(alert->ara); + } +} + static u32 stm32f7_i2c_func(struct i2c_adapter *adap) { struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adap); @@ -2173,6 +2232,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) } } + if (of_property_read_bool(pdev->dev.of_node, "smbus-alert")) { + ret = stm32f7_i2c_enable_smbus_alert(i2c_dev); + if (ret) { + dev_err(i2c_dev->dev, + "failed to enable SMBus alert protocol (%d)\n", + ret); + goto i2c_disable_smbus_host; + } + } + dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr); pm_runtime_mark_last_busy(i2c_dev->dev); @@ -2180,6 +2249,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) return 0; +i2c_disable_smbus_host: + stm32f7_i2c_disable_smbus_host(i2c_dev); + i2c_adapter_remove: i2c_del_adapter(adap); @@ -2214,6 +2286,7 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) { struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + stm32f7_i2c_disable_smbus_alert(i2c_dev); stm32f7_i2c_disable_smbus_host(i2c_dev); i2c_del_adapter(&i2c_dev->adap); diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 2a8568b97c14..bb93db98404e 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -798,11 +798,10 @@ static int xiic_i2c_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); i2c->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c->clk)) { - if (PTR_ERR(i2c->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "input clock not found.\n"); - return PTR_ERR(i2c->clk); - } + if (IS_ERR(i2c->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), + "input clock not found.\n"); + ret = clk_prepare_enable(i2c->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable clock.\n"); diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 5a97e4a02fa2..84f12bf90644 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -24,6 +24,7 @@ #include <linux/i2c-smbus.h> #include <linux/idr.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/irqflags.h> #include <linux/jump_label.h> #include <linux/kernel.h> @@ -399,7 +400,8 @@ static int i2c_gpio_init_recovery(struct i2c_adapter *adap) static int i2c_init_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - char *err_str, *err_level = KERN_ERR; + bool is_error_level = true; + char *err_str; if (!bri) return 0; @@ -409,7 +411,7 @@ static int i2c_init_recovery(struct i2c_adapter *adap) if (!bri->recover_bus) { err_str = "no suitable method provided"; - err_level = KERN_DEBUG; + is_error_level = false; goto err; } @@ -436,7 +438,10 @@ static int i2c_init_recovery(struct i2c_adapter *adap) return 0; err: - dev_printk(err_level, &adap->dev, "Not using recovery: %s\n", err_str); + if (is_error_level) + dev_err(&adap->dev, "Not using recovery: %s\n", err_str); + else + dev_dbg(&adap->dev, "Not using recovery: %s\n", err_str); adap->bus_recovery_info = NULL; return -EINVAL; @@ -461,12 +466,14 @@ static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client) static int i2c_device_probe(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap; struct i2c_driver *driver; int status; if (!client) return 0; + adap = client->adapter; client->irq = client->init_irq; if (!client->irq) { @@ -532,6 +539,14 @@ static int i2c_device_probe(struct device *dev) dev_dbg(dev, "probe\n"); + if (adap->bus_regulator) { + status = regulator_enable(adap->bus_regulator); + if (status < 0) { + dev_err(&adap->dev, "Failed to enable bus regulator\n"); + goto err_clear_wakeup_irq; + } + } + status = of_clk_set_defaults(dev->of_node, false); if (status < 0) goto err_clear_wakeup_irq; @@ -589,8 +604,10 @@ put_sync_adapter: static int i2c_device_remove(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + struct i2c_adapter *adap; struct i2c_driver *driver; + adap = client->adapter; driver = to_i2c_driver(dev->driver); if (driver->remove) { int status; @@ -605,6 +622,8 @@ static int i2c_device_remove(struct device *dev) devres_release_group(&client->dev, client->devres_group_id); dev_pm_domain_detach(&client->dev, true); + if (!pm_runtime_status_suspended(&client->dev) && adap->bus_regulator) + regulator_disable(adap->bus_regulator); dev_pm_clear_wake_irq(&client->dev); device_init_wakeup(&client->dev, false); @@ -617,6 +636,86 @@ static int i2c_device_remove(struct device *dev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int i2c_resume_early(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + if (pm_runtime_status_suspended(&client->dev) && + client->adapter->bus_regulator) { + err = regulator_enable(client->adapter->bus_regulator); + if (err) + return err; + } + + return pm_generic_resume_early(&client->dev); +} + +static int i2c_suspend_late(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + err = pm_generic_suspend_late(&client->dev); + if (err) + return err; + + if (!pm_runtime_status_suspended(&client->dev) && + client->adapter->bus_regulator) + return regulator_disable(client->adapter->bus_regulator); + + return 0; +} +#endif + +#ifdef CONFIG_PM +static int i2c_runtime_resume(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + if (client->adapter->bus_regulator) { + err = regulator_enable(client->adapter->bus_regulator); + if (err) + return err; + } + + return pm_generic_runtime_resume(&client->dev); +} + +static int i2c_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + err = pm_generic_runtime_suspend(&client->dev); + if (err) + return err; + + if (client->adapter->bus_regulator) + return regulator_disable(client->adapter->bus_regulator); + return 0; +} +#endif + +static const struct dev_pm_ops i2c_device_pm = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_suspend_late, i2c_resume_early) + SET_RUNTIME_PM_OPS(i2c_runtime_suspend, i2c_runtime_resume, NULL) +}; + static void i2c_device_shutdown(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); @@ -627,6 +726,8 @@ static void i2c_device_shutdown(struct device *dev) driver = to_i2c_driver(dev->driver); if (driver->shutdown) driver->shutdown(client); + else if (client->irq > 0) + disable_irq(client->irq); } static void i2c_client_dev_release(struct device *dev) @@ -674,6 +775,7 @@ struct bus_type i2c_bus_type = { .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, + .pm = &i2c_device_pm, }; EXPORT_SYMBOL_GPL(i2c_bus_type); diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index d2d32c0fd8c3..e5b2d1465e7e 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -37,8 +37,15 @@ static u8 crc8(u16 data) return (u8)(data >> 8); } -/* Incremental CRC8 over count bytes in the array pointed to by p */ -static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) +/** + * i2c_smbus_pec - Incremental CRC8 over the given input data array + * @crc: previous return crc8 value + * @p: pointer to data buffer. + * @count: number of bytes in data buffer. + * + * Incremental CRC8 over count bytes in the array pointed to by p + */ +u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) { int i; @@ -46,6 +53,7 @@ static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) crc = crc8((crc ^ p[i]) << 8); return crc; } +EXPORT_SYMBOL(i2c_smbus_pec); /* Assume a 7-bit address, which is reasonable for SMBus */ static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index e8f2ac8c9c3d..685f8c73d99e 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -15,6 +15,7 @@ #include <linux/device.h> /* for struct device */ #include <linux/sched.h> /* for completion */ #include <linux/mutex.h> +#include <linux/regulator/consumer.h> #include <linux/rtmutex.h> #include <linux/irqdomain.h> /* for Host Notify IRQ */ #include <linux/of.h> /* for struct device_node */ @@ -147,6 +148,7 @@ s32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, /* Now follow the 'nice' access routines. These also document the calling conventions of i2c_smbus_xfer. */ +u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count); s32 i2c_smbus_read_byte(const struct i2c_client *client); s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value); s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command); @@ -729,6 +731,7 @@ struct i2c_adapter { const struct i2c_adapter_quirks *quirks; struct irq_domain *host_notify_domain; + struct regulator *bus_regulator; }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) |