summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/eeprom/at24.yaml4
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt135
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml172
-rw-r--r--Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml2
-rw-r--r--Documentation/i2c/busses/i2c-i801.rst1
-rw-r--r--Documentation/i2c/fault-codes.rst4
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-at91-core.c10
-rw-r--r--drivers/i2c/busses/i2c-axxia.c8
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c23
-rw-r--r--drivers/i2c/busses/i2c-cp2615.c2
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c80
-rw-r--r--drivers/i2c/busses/i2c-gpio.c7
-rw-r--r--drivers/i2c/busses/i2c-i801.c110
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c12
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c11
-rw-r--r--drivers/i2c/busses/i2c-omap.c8
-rw-r--r--drivers/i2c/busses/i2c-powermac.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c7
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c1
-rw-r--r--drivers/i2c/busses/i2c-rcar.c180
-rw-r--r--drivers/i2c/busses/i2c-riic.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c7
-rw-r--r--drivers/i2c/busses/i2c-stm32f4.c32
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c89
-rw-r--r--drivers/i2c/busses/i2c-sun6i-p2wi.c5
-rw-r--r--drivers/i2c/i2c-atr.c2
-rw-r--r--drivers/i2c/i2c-core-base.c19
-rw-r--r--drivers/i2c/i2c-dev.c18
-rw-r--r--drivers/i2c/muxes/i2c-demux-pinctrl.c12
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c7
-rw-r--r--drivers/misc/eeprom/at24.c42
-rw-r--r--include/linux/acpi.h5
34 files changed, 595 insertions, 426 deletions
diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml
index bfff71ff3d6a..b6864d0ee81e 100644
--- a/Documentation/devicetree/bindings/eeprom/at24.yaml
+++ b/Documentation/devicetree/bindings/eeprom/at24.yaml
@@ -69,10 +69,14 @@ properties:
- items:
pattern: c32$
- items:
+ pattern: c32d-wl$
+ - items:
pattern: cs32$
- items:
pattern: c64$
- items:
+ pattern: c64d-wl$
+ - items:
pattern: cs64$
- items:
pattern: c128$
diff --git a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt
deleted file mode 100644
index 86b2e433a969..000000000000
--- a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt
+++ /dev/null
@@ -1,135 +0,0 @@
-Pinctrl-based I2C Bus DeMux
-
-This binding describes an I2C bus demultiplexer that uses pin multiplexing to
-route the I2C signals, and represents the pin multiplexing configuration using
-the pinctrl device tree bindings. This may be used to select one I2C IP core at
-runtime which may have a better feature set for a given task than another I2C
-IP core on the SoC. The most simple example is to fall back to GPIO bitbanging
-if your current runtime configuration hits an errata of the internal IP core.
-
- +-------------------------------+
- | SoC |
- | | +-----+ +-----+
- | +------------+ | | dev | | dev |
- | |I2C IP Core1|--\ | +-----+ +-----+
- | +------------+ \-------+ | | |
- | |Pinctrl|--|------+--------+
- | +------------+ +-------+ |
- | |I2C IP Core2|--/ |
- | +------------+ |
- | |
- +-------------------------------+
-
-Required properties:
-- compatible: "i2c-demux-pinctrl"
-- i2c-parent: List of phandles of I2C masters available for selection. The first
- one will be used as default.
-- i2c-bus-name: The name of this bus. Also needed as pinctrl-name for the I2C
- parents.
-
-Furthermore, I2C mux properties and child nodes. See i2c-mux.yaml in this
-directory.
-
-Example:
-
-Here is a snipplet for a bus to be demuxed. It contains various i2c clients for
-HDMI, so the bus is named "i2c-hdmi":
-
- i2chdmi: i2c@8 {
-
- compatible = "i2c-demux-pinctrl";
- i2c-parent = <&gpioi2c>, <&iic2>, <&i2c2>;
- i2c-bus-name = "i2c-hdmi";
- #address-cells = <1>;
- #size-cells = <0>;
-
- ak4643: sound-codec@12 {
- compatible = "asahi-kasei,ak4643";
-
- #sound-dai-cells = <0>;
- reg = <0x12>;
- };
-
- composite-in@20 {
- compatible = "adi,adv7180";
- reg = <0x20>;
- remote = <&vin1>;
-
- port {
- adv7180: endpoint {
- bus-width = <8>;
- remote-endpoint = <&vin1ep0>;
- };
- };
- };
-
- hdmi@39 {
- compatible = "adi,adv7511w";
- reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
-
- adi,input-depth = <8>;
- adi,input-colorspace = "rgb";
- adi,input-clock = "1x";
- adi,input-style = <1>;
- adi,input-justification = "evenly";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- adv7511_in: endpoint {
- remote-endpoint = <&du_out_lvds0>;
- };
- };
-
- port@1 {
- reg = <1>;
- adv7511_out: endpoint {
- remote-endpoint = <&hdmi_con>;
- };
- };
- };
- };
- };
-
-And for clarification, here are the snipplets for the i2c-parents:
-
- gpioi2c: i2c@9 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "i2c-gpio";
- gpios = <&gpio5 6 GPIO_ACTIVE_HIGH /* sda */
- &gpio5 5 GPIO_ACTIVE_HIGH /* scl */
- >;
- i2c-gpio,delay-us = <5>;
- };
-
-...
-
-&i2c2 {
- pinctrl-0 = <&i2c2_pins>;
- pinctrl-names = "i2c-hdmi";
-
- clock-frequency = <100000>;
-};
-
-...
-
-&iic2 {
- pinctrl-0 = <&iic2_pins>;
- pinctrl-names = "i2c-hdmi";
-
- clock-frequency = <100000>;
-};
-
-Please note:
-
-- pinctrl properties for the parent I2C controllers need a pinctrl state
- with the same name as i2c-bus-name, not "default"!
-
-- the i2c masters must have their status "disabled". This driver will
- enable them at runtime when needed.
diff --git a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
new file mode 100644
index 000000000000..2c08f2a7cf1e
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
@@ -0,0 +1,172 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/i2c-demux-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Pinctrl-based I2C Bus Demultiplexer
+
+maintainers:
+ - Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+description: |
+ This binding describes an I2C bus demultiplexer that uses pin multiplexing to
+ route the I2C signals, and represents the pin multiplexing configuration
+ using the pinctrl device tree bindings. This may be used to select one I2C
+ IP core at runtime which may have a better feature set for a given task than
+ another I2C IP core on the SoC. The most simple example is to fall back to
+ GPIO bitbanging if your current runtime configuration hits an errata of the
+ internal IP core.
+
+ +-------------------------------+
+ | SoC |
+ | | +-----+ +-----+
+ | +------------+ | | dev | | dev |
+ | |I2C IP Core1|--\ | +-----+ +-----+
+ | +------------+ \-------+ | | |
+ | |Pinctrl|--|------+--------+
+ | +------------+ +-------+ |
+ | |I2C IP Core2|--/ |
+ | +------------+ |
+ | |
+ +-------------------------------+
+
+allOf:
+ - $ref: i2c-mux.yaml
+ - $ref: /schemas/i2c/i2c-controller.yaml#
+
+properties:
+ compatible:
+ const: i2c-demux-pinctrl
+
+ i2c-parent:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description:
+ List of phandles of I2C masters available for selection. The first one
+ will be used as default.
+
+ i2c-bus-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ The name of this bus. Also needed as pinctrl-name for the I2C parents.
+
+required:
+ - compatible
+ - i2c-parent
+ - i2c-bus-name
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ gpioi2c2: i2c-9 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "i2c-gpio";
+ scl-gpios = <&gpio5 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ i2c-gpio,delay-us = <5>;
+
+ // The I2C controller must have its status "disabled". The I2C bus
+ // demultiplexer will enable it at runtime when needed.
+ status = "disabled";
+ };
+
+ iic2: i2c@e6520000 {
+ reg = <0xe6520000 0x425>;
+ pinctrl-0 = <&iic2_pins>;
+ // The pinctrl property for the parent I2C controller needs a pinctrl
+ // state with the same name as i2c-bus-name in the I2C bus demultiplexer
+ // node, not "default"!
+ pinctrl-names = "i2c-hdmi";
+
+ clock-frequency = <100000>;
+
+ // The I2C controller must have its status "disabled". The I2C bus
+ // demultiplexer will enable it at runtime when needed.
+ status = "disabled";
+ };
+
+ i2c2: i2c@e6530000 {
+ reg = <0 0xe6530000 0 0x40>;
+ pinctrl-0 = <&i2c2_pins>;
+ // The pinctrl property for the parent I2C controller needs a pinctrl
+ // state with the same name as i2c-bus-name in the I2C bus demultiplexer
+ // node, not "default"!
+ pinctrl-names = "i2c-hdmi";
+
+ clock-frequency = <100000>;
+
+ // The I2C controller must have its status "disabled". The I2C bus
+ // demultiplexer will enable it at runtime when needed.
+ status = "disabled";
+ };
+
+ // Example for a bus to be demuxed. It contains various I2C clients for
+ // HDMI, so the bus is named "i2c-hdmi":
+ i2chdmi: i2c-mux3 {
+ compatible = "i2c-demux-pinctrl";
+ i2c-parent = <&iic2>, <&i2c2>, <&gpioi2c2>;
+ i2c-bus-name = "i2c-hdmi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ak4643: codec@12 {
+ compatible = "asahi-kasei,ak4643";
+ #sound-dai-cells = <0>;
+ reg = <0x12>;
+ };
+
+ composite-in@20 {
+ compatible = "adi,adv7180";
+ reg = <0x20>;
+
+ port {
+ adv7180: endpoint {
+ bus-width = <8>;
+ remote-endpoint = <&vin1ep0>;
+ };
+ };
+ };
+
+ hdmi@39 {
+ compatible = "adi,adv7511w";
+ reg = <0x39>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&cec_clock>;
+ clock-names = "cec";
+
+ avdd-supply = <&fixedregulator1v8>;
+ dvdd-supply = <&fixedregulator1v8>;
+ pvdd-supply = <&fixedregulator1v8>;
+ dvdd-3v-supply = <&fixedregulator3v3>;
+ bgvdd-supply = <&fixedregulator1v8>;
+
+ adi,input-depth = <8>;
+ adi,input-colorspace = "rgb";
+ adi,input-clock = "1x";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ adv7511_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ adv7511_out: endpoint {
+ remote-endpoint = <&hdmi_con_out>;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
index 042d4dc636ee..8386cfe21532 100644
--- a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
+++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
@@ -25,6 +25,7 @@ properties:
- items:
- enum:
+ - qcom,sc7280-cci
- qcom,sdm845-cci
- qcom,sm6350-cci
- qcom,sm8250-cci
@@ -159,6 +160,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,sc7280-cci
- qcom,sm8250-cci
- qcom,sm8450-cci
then:
diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst
index e76e68ccf718..10eced6c2e46 100644
--- a/Documentation/i2c/busses/i2c-i801.rst
+++ b/Documentation/i2c/busses/i2c-i801.rst
@@ -47,6 +47,7 @@ Supported adapters:
* Intel Alder Lake (PCH)
* Intel Raptor Lake (PCH)
* Intel Meteor Lake (SOC and PCH)
+ * Intel Birch Stream (SOC)
Datasheets: Publicly available at the Intel website
diff --git a/Documentation/i2c/fault-codes.rst b/Documentation/i2c/fault-codes.rst
index 80b14e718b52..b0864d1268bd 100644
--- a/Documentation/i2c/fault-codes.rst
+++ b/Documentation/i2c/fault-codes.rst
@@ -39,6 +39,10 @@ Also, codes returned by adapter probe methods follow rules which are
specific to their host bus (such as PCI, or the platform bus).
+EAFNOSUPPORT
+ Returned by I2C adapters not supporting 10 bit addresses when
+ they are requested to use such an address.
+
EAGAIN
Returned by I2C adapters when they lose arbitration in master
transmit mode: some other master was transmitting different
diff --git a/MAINTAINERS b/MAINTAINERS
index 2e93b42f5bd1..2cc111933d98 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8825,6 +8825,7 @@ F: include/linux/phy/
GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
S: Supported
+F: Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml
F: drivers/i2c/muxes/i2c-demux-pinctrl.c
GENERIC PM DOMAINS
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index fd887f767675..28eb48dd5b32 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -158,6 +158,7 @@ config I2C_I801
Alder Lake (PCH)
Raptor Lake (PCH)
Meteor Lake (SOC and PCH)
+ Birch Stream (SOC)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c
index db45554327ae..dc52b3530725 100644
--- a/drivers/i2c/busses/i2c-at91-core.c
+++ b/drivers/i2c/busses/i2c-at91-core.c
@@ -221,11 +221,10 @@ static int at91_twi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
- dev->clk = devm_clk_get(dev->dev, NULL);
+ dev->clk = devm_clk_get_enabled(dev->dev, NULL);
if (IS_ERR(dev->clk))
- return dev_err_probe(dev->dev, PTR_ERR(dev->clk), "no clock defined\n");
-
- clk_prepare_enable(dev->clk);
+ return dev_err_probe(dev->dev, PTR_ERR(dev->clk),
+ "failed to enable clock\n");
snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
i2c_set_adapdata(&dev->adapter, dev);
@@ -254,8 +253,6 @@ static int at91_twi_probe(struct platform_device *pdev)
rc = i2c_add_numbered_adapter(&dev->adapter);
if (rc) {
- clk_disable_unprepare(dev->clk);
-
pm_runtime_disable(dev->dev);
pm_runtime_set_suspended(dev->dev);
@@ -272,7 +269,6 @@ static void at91_twi_remove(struct platform_device *pdev)
struct at91_twi_dev *dev = platform_get_drvdata(pdev);
i2c_del_adapter(&dev->adapter);
- clk_disable_unprepare(dev->clk);
pm_runtime_disable(dev->dev);
pm_runtime_set_suspended(dev->dev);
diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index d7f1e98777ac..a66f7f67b3b8 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -131,6 +131,8 @@
* @i2c_clk: clock reference for i2c input clock
* @bus_clk_rate: current i2c bus clock rate
* @last: a flag indicating is this is last message in transfer
+ * @slave: associated &i2c_client
+ * @irq: platform device IRQ number
*/
struct axxia_i2c_dev {
void __iomem *base;
@@ -165,7 +167,7 @@ static void i2c_int_enable(struct axxia_i2c_dev *idev, u32 mask)
writel(int_en | mask, idev->base + MST_INT_ENABLE);
}
-/**
+/*
* ns_to_clk - Convert time (ns) to clock cycles for the given clock frequency.
*/
static u32 ns_to_clk(u64 ns, u32 clk_mhz)
@@ -263,7 +265,7 @@ static int i2c_m_recv_len(const struct i2c_msg *msg)
return (msg->flags & I2C_M_RECV_LEN) != 0;
}
-/**
+/*
* axxia_i2c_empty_rx_fifo - Fetch data from RX FIFO and update SMBus block
* transfer length if this is the first byte of such a transfer.
*/
@@ -295,7 +297,7 @@ static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev)
return 0;
}
-/**
+/*
* axxia_i2c_fill_tx_fifo - Fill TX FIFO from current message buffer.
* @return: Number of bytes left to transfer.
*/
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index acee76732544..38f276c99193 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -160,6 +160,7 @@ struct brcmstb_i2c_dev {
struct completion done;
u32 clk_freq_hz;
int data_regsz;
+ bool atomic;
};
/* register accessors for both be and le cpu arch */
@@ -240,7 +241,7 @@ static int brcmstb_i2c_wait_for_completion(struct brcmstb_i2c_dev *dev)
int ret = 0;
unsigned long timeout = msecs_to_jiffies(I2C_TIMEOUT);
- if (dev->irq >= 0) {
+ if (dev->irq >= 0 && !dev->atomic) {
if (!wait_for_completion_timeout(&dev->done, timeout))
ret = -ETIMEDOUT;
} else {
@@ -287,7 +288,7 @@ static int brcmstb_send_i2c_cmd(struct brcmstb_i2c_dev *dev,
return rc;
/* only if we are in interrupt mode */
- if (dev->irq >= 0)
+ if (dev->irq >= 0 && !dev->atomic)
reinit_completion(&dev->done);
/* enable BSC CTL interrupt line */
@@ -520,6 +521,23 @@ out:
}
+static int brcmstb_i2c_xfer_atomic(struct i2c_adapter *adapter,
+ struct i2c_msg msgs[], int num)
+{
+ struct brcmstb_i2c_dev *dev = i2c_get_adapdata(adapter);
+ int ret;
+
+ if (dev->irq >= 0)
+ disable_irq(dev->irq);
+ dev->atomic = true;
+ ret = brcmstb_i2c_xfer(adapter, msgs, num);
+ dev->atomic = false;
+ if (dev->irq >= 0)
+ enable_irq(dev->irq);
+
+ return ret;
+}
+
static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR
@@ -528,6 +546,7 @@ static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap)
static const struct i2c_algorithm brcmstb_i2c_algo = {
.master_xfer = brcmstb_i2c_xfer,
+ .master_xfer_atomic = brcmstb_i2c_xfer_atomic,
.functionality = brcmstb_i2c_functionality,
};
diff --git a/drivers/i2c/busses/i2c-cp2615.c b/drivers/i2c/busses/i2c-cp2615.c
index 3ded28632e4c..20f8f7c9a8cd 100644
--- a/drivers/i2c/busses/i2c-cp2615.c
+++ b/drivers/i2c/busses/i2c-cp2615.c
@@ -298,7 +298,7 @@ cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id)
if (!adap)
return -ENOMEM;
- strncpy(adap->name, usbdev->serial, sizeof(adap->name) - 1);
+ strscpy(adap->name, usbdev->serial, sizeof(adap->name));
adap->owner = THIS_MODULE;
adap->dev.parent = &usbif->dev;
adap->dev.of_node = usbif->dev.of_node;
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 2b0b9cdffa86..385ef9d9e4d4 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -194,6 +194,11 @@ struct exynos5_i2c {
*/
int trans_done;
+ /*
+ * Called from atomic context, don't use interrupts.
+ */
+ unsigned int atomic;
+
/* Controller operating frequency */
unsigned int op_clock;
@@ -265,7 +270,7 @@ static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
* exynos5_i2c_set_timing: updates the registers with appropriate
* timing values calculated
*
- * Timing values for operation are calculated against either 100kHz
+ * Timing values for operation are calculated against 100kHz, 400kHz
* or 1MHz controller operating frequency.
*
* Returns 0 on success, -EINVAL if the cycle length cannot
@@ -328,6 +333,23 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
*
* Constraints: 4 <= temp, 0 <= CLK_DIV < 256, 2 <= clk_cycle <= 510
*
+ * To split SCL clock into low, high periods appropriately, one
+ * proportion factor for each I2C mode is used, which is calculated
+ * using this formula.
+ * ```
+ * ((t_low_min + (scl_clock - t_low_min - t_high_min) / 2) / scl_clock)
+ * ```
+ * where:
+ * t_low_min is the minimal value of low period of the SCL clock in us;
+ * t_high_min is the minimal value of high period of the SCL clock in us;
+ * scl_clock is converted from SCL clock frequency into us.
+ *
+ * Below are the proportion factors for these I2C modes:
+ * t_low_min, t_high_min, scl_clock, proportion
+ * Standard Mode: 4.7us, 4.0us, 10us, 0.535
+ * Fast Mode: 1.3us, 0.6us, 2.5us, 0.64
+ * Fast-Plus Mode: 0.5us, 0.26us, 1us, 0.62
+ *
*/
t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
temp = clkin / op_clk - 8 - t_ftl_cycle;
@@ -341,8 +363,19 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
return -EINVAL;
}
- t_scl_l = clk_cycle / 2;
- t_scl_h = clk_cycle / 2;
+ /*
+ * Scale clk_cycle to get t_scl_l using the proption factors for individual I2C modes.
+ */
+ if (op_clk <= I2C_MAX_STANDARD_MODE_FREQ)
+ t_scl_l = clk_cycle * 535 / 1000;
+ else if (op_clk <= I2C_MAX_FAST_MODE_FREQ)
+ t_scl_l = clk_cycle * 64 / 100;
+ else
+ t_scl_l = clk_cycle * 62 / 100;
+
+ if (t_scl_l > 0xFF)
+ t_scl_l = 0xFF;
+ t_scl_h = clk_cycle - t_scl_l;
t_start_su = t_scl_l;
t_start_hd = t_scl_l;
t_stop_su = t_scl_l;
@@ -711,6 +744,22 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
spin_unlock_irqrestore(&i2c->lock, flags);
}
+static bool exynos5_i2c_poll_irqs_timeout(struct exynos5_i2c *i2c,
+ unsigned long timeout)
+{
+ unsigned long time_left = jiffies + timeout;
+
+ while (time_before(jiffies, time_left) &&
+ !((i2c->trans_done && (i2c->msg->len == i2c->msg_ptr)) ||
+ (i2c->state < 0))) {
+ while (readl(i2c->regs + HSI2C_INT_ENABLE) &
+ readl(i2c->regs + HSI2C_INT_STATUS))
+ exynos5_i2c_irq(i2c->irq, i2c);
+ usleep_range(100, 200);
+ }
+ return time_before(jiffies, time_left);
+}
+
static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c,
struct i2c_msg *msgs, int stop)
{
@@ -725,8 +774,13 @@ static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c,
exynos5_i2c_message_start(i2c, stop);
- timeout = wait_for_completion_timeout(&i2c->msg_complete,
- EXYNOS5_I2C_TIMEOUT);
+ if (!i2c->atomic)
+ timeout = wait_for_completion_timeout(&i2c->msg_complete,
+ EXYNOS5_I2C_TIMEOUT);
+ else
+ timeout = exynos5_i2c_poll_irqs_timeout(i2c,
+ EXYNOS5_I2C_TIMEOUT);
+
if (timeout == 0)
ret = -ETIMEDOUT;
else
@@ -777,6 +831,21 @@ err_pclk:
return ret ?: num;
}
+static int exynos5_i2c_xfer_atomic(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct exynos5_i2c *i2c = adap->algo_data;
+ int ret;
+
+ disable_irq(i2c->irq);
+ i2c->atomic = true;
+ ret = exynos5_i2c_xfer(adap, msgs, num);
+ i2c->atomic = false;
+ enable_irq(i2c->irq);
+
+ return ret;
+}
+
static u32 exynos5_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
@@ -784,6 +853,7 @@ static u32 exynos5_i2c_func(struct i2c_adapter *adap)
static const struct i2c_algorithm exynos5_i2c_algorithm = {
.master_xfer = exynos5_i2c_xfer,
+ .master_xfer_atomic = exynos5_i2c_xfer_atomic,
.functionality = exynos5_i2c_func,
};
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index e5a5b9e8bf2c..fb35a75fe0e3 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -263,15 +263,10 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
* 'fault-injector' dir there. Until then, we have a global dir with
* all adapters as subdirs.
*/
- if (!i2c_gpio_debug_dir) {
+ if (!i2c_gpio_debug_dir)
i2c_gpio_debug_dir = debugfs_create_dir("i2c-fault-injector", NULL);
- if (!i2c_gpio_debug_dir)
- return;
- }
priv->debug_dir = debugfs_create_dir(pdev->name, i2c_gpio_debug_dir);
- if (!priv->debug_dir)
- return;
init_completion(&priv->scl_irq_completion);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 1d855258a45d..070999139c6d 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -79,6 +79,7 @@
* Meteor Lake-P (SOC) 0x7e22 32 hard yes yes yes
* Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes
* Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes
+ * Birch Stream (SOC) 0x5796 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@@ -231,6 +232,7 @@
#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3
+#define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
@@ -285,7 +287,6 @@ struct i801_priv {
u8 *data;
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
- const struct i801_mux_config *mux_drvdata;
struct platform_device *mux_pdev;
struct gpiod_lookup_table *lookup;
#endif
@@ -293,10 +294,9 @@ struct i801_priv {
/*
* If set to true the host controller registers are reserved for
- * ACPI AML use. Protected by acpi_lock.
+ * ACPI AML use.
*/
bool acpi_reserved;
- struct mutex acpi_lock;
};
#define FEATURE_SMBUS_PEC BIT(0)
@@ -679,15 +679,11 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
return result ? priv->status : -ETIMEDOUT;
}
- for (i = 1; i <= len; i++) {
- if (i == len && read_write == I2C_SMBUS_READ)
- smbcmd |= SMBHSTCNT_LAST_BYTE;
- outb_p(smbcmd, SMBHSTCNT(priv));
-
- if (i == 1)