Skip to content

Commit

Permalink
Merge tag 'i2c-for-6.13-part2' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/wsa/linux

Pull more i2c updates from Wolfram Sang:
 "Andi was super busy the last weeks, so this pull requests contains one
  series (nomadik) and a number of smaller additions which were ready to
  go but nearly overlooked.

  New feature support:

   - Added support for frequencies up to 3.4 MHz on Nomadik I2C

   - DesignWare now accounts for bus capacitance and clock optimisation
     (declared as new parameters in the binding) to improve the
     calculation of signal rise and fall times (t_high and t_low)

  New Hardware support:

   - DWAPB I2C controller on FUJITSU-MONAKA (new ACPI HID)

   - Allwinner A523 (new compatible ID)

   - Mobileye EyeQ6H (new compatible ID)"

* tag 'i2c-for-6.13-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  MAINTAINERS: transfer i2c-aspeed maintainership from Brendan to Ryan
  i2c: designware: determine HS tHIGH and tLOW based on HW parameters
  dt-bindings: i2c: snps,designware-i2c: declare bus capacitance and clk freq optimized
  i2c: nomadik: support >=1MHz speed modes
  i2c: nomadik: fix BRCR computation
  i2c: nomadik: support Mobileye EyeQ6H I2C controller
  i2c: nomadik: switch from of_device_is_compatible() to of_match_device()
  dt-bindings: i2c: nomadik: support 400kHz < clock-frequency <= 3.4MHz
  dt-bindings: i2c: nomadik: add mobileye,eyeq6h-i2c bindings
  dt-bindings: i2c: mv64xxx: Add Allwinner A523 compatible string
  i2c: designware: Add ACPI HID for DWAPB I2C controller on FUJITSU-MONAKA
  i2c: qup: use generic device property accessors
  • Loading branch information
Linus Torvalds committed Nov 26, 2024
2 parents 5d38cb9 + 16470f6 commit 70dbb12
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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 {
Expand Down
13 changes: 7 additions & 6 deletions Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,23 @@ select:
enum:
- st,nomadik-i2c
- mobileye,eyeq5-i2c
- mobileye,eyeq6h-i2c
required:
- compatible

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
Expand All @@ -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
Expand All @@ -67,7 +68,7 @@ properties:

clock-frequency:
minimum: 1
maximum: 400000
maximum: 3400000

mobileye,olb:
$ref: /schemas/types.yaml#/definitions/phandle-array
Expand Down
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2213,7 +2213,7 @@ F: drivers/mmc/host/usdhi6rol0.c
F: drivers/pinctrl/pinctrl-artpec*

ARM/ASPEED I2C DRIVER
M: Brendan Higgins <brendanhiggins@google.com>
M: Ryan Chen <ryan_chen@aspeedtech.com>
R: Benjamin Herrenschmidt <benh@kernel.crashing.org>
R: Joel Stanley <joel@jms.id.au>
L: linux-i2c@vger.kernel.org
Expand Down
5 changes: 5 additions & 0 deletions drivers/i2c/busses/i2c-designware-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
6 changes: 6 additions & 0 deletions drivers/i2c/busses/i2c-designware-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
23 changes: 21 additions & 2 deletions drivers/i2c/busses/i2c-designware-master.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
}
Expand Down
1 change: 1 addition & 0 deletions drivers/i2c/busses/i2c-designware-platdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
87 changes: 53 additions & 34 deletions drivers/i2c/busses/i2c-nomadik.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <srinidhi.kasagar@stericsson.com>
Expand All @@ -26,6 +26,7 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
Expand Down Expand Up @@ -396,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;
Expand Down Expand Up @@ -443,38 +444,31 @@ 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;

/*
* 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, 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 */
Expand Down Expand Up @@ -1015,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 */

Expand All @@ -1046,8 +1043,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);
Expand All @@ -1068,26 +1063,50 @@ 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),
},
{
.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)
{
int ret = 0;
struct nmk_i2c_dev *priv;
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;
struct i2c_vendor_data *vendor = id->data;
u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1;
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)
return -ENOMEM;

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");
Expand Down
4 changes: 2 additions & 2 deletions drivers/i2c/busses/i2c-qup.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/scatterlist.h>

/* QUP Registers */
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 70dbb12

Please sign in to comment.