From 50b9d43e6ceaaaa59c54c95aca5f8dfc862fe48e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 8 Oct 2024 18:09:47 +0200 Subject: [PATCH 01/12] i2c: qup: use generic device property accessors There's no reason for this driver to use OF-specific property helpers. Drop the last one in favor of the generic variant and no longer include of.h. Signed-off-by: Bartosz Golaszewski Reviewed-by: Neil Armstrong Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-qup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 86ec391616b0..da20b4487c9a 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -17,9 +17,9 @@ #include #include #include -#include #include #include +#include #include /* QUP Registers */ @@ -1683,7 +1683,7 @@ static int qup_i2c_probe(struct platform_device *pdev) } } - if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) { + if (device_is_compatible(&pdev->dev, "qcom,i2c-qup-v1.1.1")) { qup->adap.algo = &qup_i2c_algo; qup->adap.quirks = &qup_i2c_quirks; is_qup_v1 = true; From 7c3a833a1da6ab1e29fcb4740edf770aea816c6f Mon Sep 17 00:00:00 2001 From: Yoshihiro Furudera Date: Thu, 24 Oct 2024 07:15:53 +0000 Subject: [PATCH 02/12] i2c: designware: Add ACPI HID for DWAPB I2C controller on FUJITSU-MONAKA Enable DWAPB I2C controller support on FUJITSU-MONAKA. This will be used in the FUJITSU-MONAKA server scheduled for shipment in 2027. The DSDT information obtained when verified using an in-house simulator is presented below. Device (SMB0) { Name (_HID, "FUJI200B") // _HID: Hardware ID Name (_UID, Zero) // _UID: Unique ID ... Name (_CRS, ResourceTemplate () { Memory32Fixed (ReadWrite, 0x2A4B0000, // Address Base 0x00010000, // Address Length ) Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, ) { 0x00000159, } }) ... } The expression SMB0 is used to indicate SMBus HC#0, a string of up to four characters. Created the SMB0 object according to the following specifications: ACPI Specification 13.2. Accessing the SMBus from ASL Code https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/13_ACPI_System_Mgmt_Bus_Interface_Spec/accessing-the-smbus-from-asl-code.html IPMI Specification Example 4: SSIF Interface(P574) https://www.intel.co.jp/content/www/jp/ja/products/docs/servers/ipmi/ipmi-second-gen-interface-spec-v2-rev1-1.html Signed-off-by: Yoshihiro Furudera Reviewed-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-platdrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 1643cad6489c..3e12aab6bf2d 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -349,6 +349,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = { { "AMDI0019", ACCESS_INTR_MASK | ARBITRATION_SEMAPHORE }, { "AMDI0510", 0 }, { "APMC0D0F", 0 }, + { "FUJI200B", 0 }, { "HISI02A1", 0 }, { "HISI02A2", 0 }, { "HISI02A3", 0 }, From efdc7828b7cc8cb8a1c2a83ff6f7741ca055b1b1 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 11 Nov 2024 01:30:24 +0000 Subject: [PATCH 03/12] dt-bindings: i2c: mv64xxx: Add Allwinner A523 compatible string The I2C controller IP used in the Allwinner A523/T527 SoCs is compatible with the ones used in the other recent Allwinner SoCs. Add the A523 specific compatible string to the list of existing names falling back to the allwinner,sun8i-v536-i2c string. Signed-off-by: Andre Przywara Acked-by: Conor Dooley Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml index 984fc1ed3ec6..c4efcef59133 100644 --- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml @@ -33,6 +33,7 @@ properties: - allwinner,sun50i-a100-i2c - allwinner,sun50i-h616-i2c - allwinner,sun50i-r329-i2c + - allwinner,sun55i-a523-i2c - const: allwinner,sun8i-v536-i2c - const: allwinner,sun6i-a31-i2c - const: marvell,mv64xxx-i2c From 2eec351eed02da9955ac7a79dd9481f61c355c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Wed, 9 Oct 2024 16:01:07 +0200 Subject: [PATCH 04/12] dt-bindings: i2c: nomadik: add mobileye,eyeq6h-i2c bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After EyeQ5, it is time for Mobileye EyeQ6H to reuse the Nomadik I2C controller. Add a specific compatible because its HW integration is slightly different from EyeQ5. Do NOT add an example as it looks like EyeQ5 from a DT standpoint (without the mobileye,olb property). Reviewed-by: Linus Walleij Signed-off-by: Théo Lebrun Reviewed-by: Rob Herring (Arm) Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- .../devicetree/bindings/i2c/st,nomadik-i2c.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml index 44c54b162bb1..7e84465c2009 100644 --- a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml @@ -22,6 +22,7 @@ select: enum: - st,nomadik-i2c - mobileye,eyeq5-i2c + - mobileye,eyeq6h-i2c required: - compatible @@ -29,15 +30,15 @@ properties: compatible: oneOf: - items: - - const: st,nomadik-i2c + - enum: + - st,nomadik-i2c + - mobileye,eyeq5-i2c + - mobileye,eyeq6h-i2c - const: arm,primecell - items: - const: stericsson,db8500-i2c - const: st,nomadik-i2c - const: arm,primecell - - items: - - const: mobileye,eyeq5-i2c - - const: arm,primecell reg: maxItems: 1 @@ -54,7 +55,7 @@ properties: - items: - const: mclk - const: apb_pclk - # Clock name in DB8500 or EyeQ5 + # Clock name in DB8500 or EyeQ - items: - const: i2cclk - const: apb_pclk From 54202106c0fe23693c5e9e81e7587ce89e6dd182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Wed, 9 Oct 2024 16:01:08 +0200 Subject: [PATCH 05/12] dt-bindings: i2c: nomadik: support 400kHz < clock-frequency <= 3.4MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware is not limited to 400kHz, its documentation does mention how to configure it for high-speed (a specific Speed-Mode enum value and a different bus rate clock divider register to be used). Reviewed-by: Linus Walleij Signed-off-by: Théo Lebrun Reviewed-by: Rob Herring (Arm) Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml index 7e84465c2009..012402debfeb 100644 --- a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml @@ -68,7 +68,7 @@ properties: clock-frequency: minimum: 1 - maximum: 400000 + maximum: 3400000 mobileye,olb: $ref: /schemas/types.yaml#/definitions/phandle-array From a0d15cc47f29be6d588fa55bdbe116c26549178d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Wed, 9 Oct 2024 16:01:09 +0200 Subject: [PATCH 06/12] i2c: nomadik: switch from of_device_is_compatible() to of_match_device() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compatible-specific behavior is implemented using a if-condition on the return value from of_device_is_compatible(), from probe. It does not scale well when compatible number increases. Switch to using a match table and a call to of_match_device(). We DO NOT attach a .of_match_table field to our amba driver, as we do not use the table to match our driver to devices. Sort probe variable declarations in reverse christmas tree to try and introduce some logic into the ordering. Reviewed-by: Linus Walleij Signed-off-by: Théo Lebrun Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 37 ++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index ad0f02acdb12..c40328d1bca6 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1046,8 +1047,6 @@ static int nmk_i2c_eyeq5_probe(struct nmk_i2c_dev *priv) struct regmap *olb; unsigned int id; - priv->has_32b_bus = true; - olb = syscon_regmap_lookup_by_phandle_args(np, "mobileye,olb", 1, &id); if (IS_ERR(olb)) return PTR_ERR(olb); @@ -1068,15 +1067,35 @@ static int nmk_i2c_eyeq5_probe(struct nmk_i2c_dev *priv) return 0; } +#define NMK_I2C_EYEQ_FLAG_32B_BUS BIT(0) +#define NMK_I2C_EYEQ_FLAG_IS_EYEQ5 BIT(1) + +static const struct of_device_id nmk_i2c_eyeq_match_table[] = { + { + .compatible = "mobileye,eyeq5-i2c", + .data = (void *)(NMK_I2C_EYEQ_FLAG_32B_BUS | NMK_I2C_EYEQ_FLAG_IS_EYEQ5), + }, +}; + static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) { - int ret = 0; - struct nmk_i2c_dev *priv; - struct device_node *np = adev->dev.of_node; - struct device *dev = &adev->dev; - struct i2c_adapter *adap; struct i2c_vendor_data *vendor = id->data; u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; + struct device_node *np = adev->dev.of_node; + const struct of_device_id *match; + struct device *dev = &adev->dev; + unsigned long match_flags = 0; + struct nmk_i2c_dev *priv; + struct i2c_adapter *adap; + int ret = 0; + + /* + * We do not want to attach a .of_match_table to our amba driver. + * Do not convert to device_get_match_data(). + */ + match = of_match_device(nmk_i2c_eyeq_match_table, dev); + if (match) + match_flags = (unsigned long)match->data; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -1084,10 +1103,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) priv->vendor = vendor; priv->adev = adev; - priv->has_32b_bus = false; + priv->has_32b_bus = match_flags & NMK_I2C_EYEQ_FLAG_32B_BUS; nmk_i2c_of_probe(np, priv); - if (of_device_is_compatible(np, "mobileye,eyeq5-i2c")) { + if (match_flags & NMK_I2C_EYEQ_FLAG_IS_EYEQ5) { ret = nmk_i2c_eyeq5_probe(priv); if (ret) return dev_err_probe(dev, ret, "failed OLB lookup\n"); From 814a3225f4e9b3631369029ed5ecf35e7a2999bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Wed, 9 Oct 2024 16:01:10 +0200 Subject: [PATCH 07/12] i2c: nomadik: support Mobileye EyeQ6H I2C controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add EyeQ6H support to the nmk-i2c AMBA driver. It shares the same quirk as EyeQ5: the memory bus only supports 32-bit accesses. Avoid writeb() and readb() by reusing the same `priv->has_32b_bus` flag. It does NOT need to write speed-mode specific value into a register; therefore it does not depend on the mobileye,olb DT property. Reviewed-by: Linus Walleij Signed-off-by: Théo Lebrun Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index c40328d1bca6..8f52ae4d6285 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -6,10 +6,10 @@ * I2C master mode controller driver, used in Nomadik 8815 * and Ux500 platforms. * - * The Mobileye EyeQ5 platform is also supported; it uses + * The Mobileye EyeQ5 and EyeQ6H platforms are also supported; they use * the same Ux500/DB8500 IP block with two quirks: * - The memory bus only supports 32-bit accesses. - * - A register must be configured for the I2C speed mode; + * - (only EyeQ5) A register must be configured for the I2C speed mode; * it is located in a shared register region called OLB. * * Author: Srinidhi Kasagar @@ -1075,6 +1075,10 @@ static const struct of_device_id nmk_i2c_eyeq_match_table[] = { .compatible = "mobileye,eyeq5-i2c", .data = (void *)(NMK_I2C_EYEQ_FLAG_32B_BUS | NMK_I2C_EYEQ_FLAG_IS_EYEQ5), }, + { + .compatible = "mobileye,eyeq6h-i2c", + .data = (void *)NMK_I2C_EYEQ_FLAG_32B_BUS, + }, }; static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) From 16674c8c488ec40cbf15806658a22a68bb15a810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Wed, 9 Oct 2024 16:01:11 +0200 Subject: [PATCH 08/12] i2c: nomadik: fix BRCR computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current BRCR computation is: brcr = floor(i2cclk / (clkfreq * div)) With brcr: "baud rate counter", an internal clock divider, and i2cclk: input clock rate (24MHz, 38.4MHz or 48MHz), and clkfreq: desired bus rate, and div: speed-mode dependent divider (2 for standard, 3 otherwise). Assume i2cclk=48MHz, clkfreq=3.4MHz, div=3, then brcr = floor(48MHz / (3.4MHz * 3)) = 4 and resulting bus rate = 48MHz / (4 * 3) = 4MHz Assume i2cclk=38.4MHz, clkfreq=1.0MHz, div=3, then brcr = floor(38.4MHz / (1.0MHz * 3)) = 12 and resulting bus rate = 38.4MHz / (12 * 3) = 1066kHz The current computation means we always pick the smallest divider that gives a bus rate above target. We should instead pick the largest divider that gives a bus rate below target, using: brcr = floor(i2cclk / (clkfreq * div)) + 1 If we redo the above examples: Assume i2cclk=48MHz, clkfreq=3.4MHz, div=3, then brcr = floor(48MHz / (3.4MHz * 3)) + 1 = 5 and resulting bus rate = 48MHz / (5 * 3) = 3.2MHz Assume i2cclk=38.4MHz, clkfreq=1.0MHz, div=3, then brcr = floor(38.4MHz / (1.0MHz * 3)) + 1 = 13 and resulting bus rate = 38.4MHz / (13 * 3) = 985kHz In kernel C code, floor(x) is DIV_ROUND_DOWN() and, floor(x)+1 is DIV_ROUND_UP(). This is much less of an issue with slower bus rates (ie those currently supported), because the gap from one divider to the next is much smaller. It however keeps us from always using bus rates superior to the target. This fix is required for later on supporting faster bus rates: I2C_FREQ_MODE_FAST_PLUS (1MHz) and I2C_FREQ_MODE_HIGH_SPEED (3.4MHz). Signed-off-by: Théo Lebrun Reviewed-by: Linus Walleij Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 8f52ae4d6285..90e3390cd66d 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -454,9 +454,13 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv) * operation, and the other is for std, fast mode, fast mode * plus operation. Currently we do not supprt high speed mode * so set brcr1 to 0. + * + * BRCR is a clock divider amount. Pick highest value that + * leads to rate strictly below target. Eg when asking for + * 400kHz you want a bus rate <=400kHz (and not >=400kHz). */ brcr1 = FIELD_PREP(I2C_BRCR_BRCNT1, 0); - brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, i2c_clk / (priv->clk_freq * div)); + brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, DIV_ROUND_UP(i2c_clk, priv->clk_freq * div)); /* set the baud rate counter register */ writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR); From 4fb1b640d68dba271e6b580582ac5c1381c6157a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Wed, 9 Oct 2024 16:01:12 +0200 Subject: [PATCH 09/12] i2c: nomadik: support >=1MHz speed modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BRCR value must go into the BRCR1 field when in high-speed mode. It goes into BRCR2 otherwise. - Remove fallback to standard mode if priv->sm > I2C_FREQ_MODE_FAST. - Set SM properly in probe; previously it only checked STANDARD versus FAST. Now we set STANDARD, FAST, FAST_PLUS or HIGH_SPEED. - Remove all comment sections saying we only support low-speeds. Reviewed-by: Linus Walleij Signed-off-by: Théo Lebrun Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 40 +++++++++++++------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 90e3390cd66d..efb33802804f 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -397,7 +397,7 @@ static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *priv, u16 flags) */ static void setup_i2c_controller(struct nmk_i2c_dev *priv) { - u32 brcr1, brcr2; + u32 brcr; u32 i2c_clk, div; u32 ns; u16 slsu; @@ -444,7 +444,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv) /* * The spec says, in case of std. mode the divider is * 2 whereas it is 3 for fast and fastplus mode of - * operation. TODO - high speed support. + * operation. */ div = (priv->clk_freq > I2C_MAX_STANDARD_MODE_FREQ) ? 3 : 2; @@ -452,34 +452,23 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv) * generate the mask for baud rate counters. The controller * has two baud rate counters. One is used for High speed * operation, and the other is for std, fast mode, fast mode - * plus operation. Currently we do not supprt high speed mode - * so set brcr1 to 0. + * plus operation. * * BRCR is a clock divider amount. Pick highest value that * leads to rate strictly below target. Eg when asking for * 400kHz you want a bus rate <=400kHz (and not >=400kHz). */ - brcr1 = FIELD_PREP(I2C_BRCR_BRCNT1, 0); - brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, DIV_ROUND_UP(i2c_clk, priv->clk_freq * div)); + brcr = DIV_ROUND_UP(i2c_clk, priv->clk_freq * div); + + if (priv->sm == I2C_FREQ_MODE_HIGH_SPEED) + brcr = FIELD_PREP(I2C_BRCR_BRCNT1, brcr); + else + brcr = FIELD_PREP(I2C_BRCR_BRCNT2, brcr); /* set the baud rate counter register */ - writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR); + writel(brcr, priv->virtbase + I2C_BRCR); - /* - * set the speed mode. Currently we support - * only standard and fast mode of operation - * TODO - support for fast mode plus (up to 1Mb/s) - * and high speed (up to 3.4 Mb/s) - */ - if (priv->sm > I2C_FREQ_MODE_FAST) { - dev_err(&priv->adev->dev, - "do not support this mode defaulting to std. mode\n"); - brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, - i2c_clk / (I2C_MAX_STANDARD_MODE_FREQ * 2)); - writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR); - writel(FIELD_PREP(I2C_CR_SM, I2C_FREQ_MODE_STANDARD), - priv->virtbase + I2C_CR); - } + /* set the speed mode */ writel(FIELD_PREP(I2C_CR_SM, priv->sm), priv->virtbase + I2C_CR); /* set the Tx and Rx FIFO threshold */ @@ -1020,11 +1009,14 @@ static void nmk_i2c_of_probe(struct device_node *np, if (of_property_read_u32(np, "clock-frequency", &priv->clk_freq)) priv->clk_freq = I2C_MAX_STANDARD_MODE_FREQ; - /* This driver only supports 'standard' and 'fast' modes of operation. */ if (priv->clk_freq <= I2C_MAX_STANDARD_MODE_FREQ) priv->sm = I2C_FREQ_MODE_STANDARD; - else + else if (priv->clk_freq <= I2C_MAX_FAST_MODE_FREQ) priv->sm = I2C_FREQ_MODE_FAST; + else if (priv->clk_freq <= I2C_MAX_FAST_MODE_PLUS_FREQ) + priv->sm = I2C_FREQ_MODE_FAST_PLUS; + else + priv->sm = I2C_FREQ_MODE_HIGH_SPEED; priv->tft = 1; /* Tx FIFO threshold */ priv->rft = 8; /* Rx FIFO threshold */ From bbc89a6e837f291e7ad04cea50915c71110e781a Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Thu, 3 Oct 2024 19:15:23 +0800 Subject: [PATCH 10/12] dt-bindings: i2c: snps,designware-i2c: declare bus capacitance and clk freq optimized Since there are no registers controlling the hardware parameters IC_CAP_LOADING and IC_CLK_FREQ_OPTIMIZATION, their values can only be declared in the device tree. snps,bus-capacitance-pf indicates the bus capacitance in picofarads (pF). It affects the high and low pulse width of SCL line in high speed mode. The legal values for this property are 100 and 400 only, and default value is 100. This property corresponds to IC_CAP_LOADING. snps,clk-freq-optimized indicates whether the hardware reduce its internal clock frequency by reducing the internal latency required to generate the high period and low period of SCL line. This property corresponds to IC_CLK_FREQ_OPTIMIZATION. The driver can calculate the high period count and low period count of SCL line for high speed mode based on these two properties. Signed-off-by: Michael Wu Reviewed-by: Krzysztof Kozlowski Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- .../bindings/i2c/snps,designware-i2c.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml index 60035a787e5c..e5d05263c45a 100644 --- a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml @@ -97,6 +97,22 @@ properties: - const: tx - const: rx + snps,bus-capacitance-pf: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + This property indicates the bus capacitance in picofarads (pF). + This value is used to compute the tHIGH and tLOW periods for high speed + mode. + enum: [100, 400] + default: 100 + + snps,clk-freq-optimized: + description: + This property indicates whether the hardware reduce its clock frequency + by reducing the internal latency required to generate the high period and + low period of SCL line. + type: boolean + unevaluatedProperties: false required: @@ -121,6 +137,8 @@ examples: i2c-sda-hold-time-ns = <300>; i2c-sda-falling-time-ns = <300>; i2c-scl-falling-time-ns = <300>; + snps,bus-capacitance-pf = <400>; + snps,clk-freq-optimized; }; - | i2c@2000 { From 61ab42c7f32d6d881a62e5cf76c46f95cb7ca2bd Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Thu, 3 Oct 2024 19:15:24 +0800 Subject: [PATCH 11/12] i2c: designware: determine HS tHIGH and tLOW based on HW parameters In commit 35eba185fd1a ("i2c: designware: Calculate SCL timing parameter for High Speed Mode") the SCL high period count and low period count for high speed mode are calculated based on fixed tHIGH = 160 and tLOW = 120. However, the set of two fixed values is only applicable to the combination of hardware parameters IC_CAP_LOADING is 400 and IC_CLK_FREQ_OPTIMIZATION is true. Outside of this combination, the SCL frequency may not reach 3.4 MHz because the fixed tHIGH and tLOW are not small enough. If IC_CAP_LOADING is 400, it means the bus capacitance is 400pF; Otherwise, 100 pF. If IC_CLK_FREQ_OPTIMIZATION is true, it means that the hardware reduces its internal clock frequency by reducing the internal latency required to generate the high period and low period of the SCL line. Section 3.15.4.5 in DesignWare DW_apb_i2b Databook v2.03 says that when IC_CLK_FREQ_OPTIMIZATION = 0, MIN_SCL_HIGHtime = 60 ns for 3.4 Mbps, bus loading = 100pF = 120 ns for 3.4 Mbps, bus loading = 400pF MIN_SCL_LOWtime = 160 ns for 3.4 Mbps, bus loading = 100pF = 320 ns for 3.4 Mbps, bus loading = 400pF and section 3.15.4.6 says that when IC_CLK_FREQ_OPTIMIZATION = 1, MIN_SCL_HIGHtime = 60 ns for 3.4 Mbps, bus loading = 100pF = 160 ns for 3.4 Mbps, bus loading = 400pF MIN_SCL_LOWtime = 120 ns for 3.4 Mbps, bus loading = 100pF = 320 ns for 3.4 Mbps, bus loading = 400pF In order to calculate more accurate SCL high period count and low period count for high speed mode, two hardware parameters IC_CAP_LOADING and IC_CLK_FREQ_OPTIMIZATION must be considered together. Since there're no registers controlliing these these two hardware parameters, users can declare them in the device tree so that the driver can obtain them. Signed-off-by: Michael Wu Reviewed-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-common.c | 5 +++++ drivers/i2c/busses/i2c-designware-core.h | 6 ++++++ drivers/i2c/busses/i2c-designware-master.c | 23 ++++++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 443f946acf36..857783d458fb 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -382,6 +382,11 @@ int i2c_dw_fw_parse_and_configure(struct dw_i2c_dev *dev) i2c_parse_fw_timings(device, t, false); + if (device_property_read_u32(device, "snps,bus-capacitance-pf", &dev->bus_capacitance_pF)) + dev->bus_capacitance_pF = 100; + + dev->clk_freq_optimized = device_property_read_bool(device, "snps,clk-freq-optimized"); + i2c_dw_adjust_bus_speed(dev); if (is_of_node(fwnode)) diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 520f9699e3bd..347843b4f5dd 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -242,6 +242,10 @@ struct reset_control; * @set_sda_hold_time: callback to retrieve IP specific SDA hold timing * @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE * @rinfo: I²C GPIO recovery information + * @bus_capacitance_pF: bus capacitance in picofarads + * @clk_freq_optimized: if this value is true, it means the hardware reduces + * its internal clock frequency by reducing the internal latency required + * to generate the high period and low period of SCL line. * * HCNT and LCNT parameters can be used if the platform knows more accurate * values than the one computed based only on the input clock frequency. @@ -299,6 +303,8 @@ struct dw_i2c_dev { int (*set_sda_hold_time)(struct dw_i2c_dev *dev); int mode; struct i2c_bus_recovery_info rinfo; + u32 bus_capacitance_pF; + bool clk_freq_optimized; }; #define ACCESS_INTR_MASK BIT(0) diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 528b969253a7..eca8998d640f 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -151,19 +151,38 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev) dev->hs_hcnt = 0; dev->hs_lcnt = 0; } else if (!dev->hs_hcnt || !dev->hs_lcnt) { + u32 t_high, t_low; + + /* + * The legal values stated in the databook for bus + * capacitance are only 100pF and 400pF. + * If dev->bus_capacitance_pF is greater than or equals + * to 400, t_high and t_low are assumed to be + * appropriate values for 400pF, otherwise 100pF. + */ + if (dev->bus_capacitance_pF >= 400) { + /* assume bus capacitance is 400pF */ + t_high = dev->clk_freq_optimized ? 160 : 120; + t_low = 320; + } else { + /* assume bus capacitance is 100pF */ + t_high = 60; + t_low = dev->clk_freq_optimized ? 120 : 160; + } + ic_clk = i2c_dw_clk_rate(dev); dev->hs_hcnt = i2c_dw_scl_hcnt(dev, DW_IC_HS_SCL_HCNT, ic_clk, - 160, /* tHIGH = 160 ns */ + t_high, sda_falling_time, 0); /* No offset */ dev->hs_lcnt = i2c_dw_scl_lcnt(dev, DW_IC_HS_SCL_LCNT, ic_clk, - 320, /* tLOW = 320 ns */ + t_low, scl_falling_time, 0); /* No offset */ } From 16470f60666618830cb9f0b8dfafd34a838c6dbd Mon Sep 17 00:00:00 2001 From: Brendan Higgins Date: Fri, 15 Nov 2024 04:43:03 +0000 Subject: [PATCH 12/12] MAINTAINERS: transfer i2c-aspeed maintainership from Brendan to Ryan Remove Brendan Higgins from i2c-aspeed entry and replace with Ryan Chen . Signed-off-by: Brendan Higgins Acked-by: Ryan Chen Signed-off-by: Andi Shyti Signed-off-by: Wolfram Sang --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index e7f017097701..d59434619fdf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2213,7 +2213,7 @@ F: drivers/mmc/host/usdhi6rol0.c F: drivers/pinctrl/pinctrl-artpec* ARM/ASPEED I2C DRIVER -M: Brendan Higgins +M: Ryan Chen R: Benjamin Herrenschmidt R: Joel Stanley L: linux-i2c@vger.kernel.org