mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
i2c-for-6.13-part2
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. Despite the late collection, they have been properly reviewed and have been in -next for 6 days now in Andi's tree. 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). -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmdDRfUACgkQFA3kzBSg KbZpFA//ZYScU383VPaSc6U750yAM3lFLfjlmi8gfgJ5r42a5xTG+zltu8MJeu3C wRJGu3MDxuE5jjHMGAUMauuD0w0tTkY7ZcfPqpj2hDEs7Un/oVD2quz5EkRyaKIS mU86GoEFr4RB7lUguSsQbV9Fk+mlu6CEiOxT270AnwSF2O0YKkrBPV+htvh/VKdL TdFLQph2XGk0atGnklraBHQqZq7bVFGgpfdj/oKg2uM+2gnfJuAU86CHCg0kGp7/ /95sIlu8jORA9/0jJ6d5yyb4ScuGnYfjxdomnbODXsOAcLPfgjtnStKrApAH3I0K DyBfherU8o+kvEe1APjecxGFifms/01YxSpVUvsKW3I0UXM6ahOcbjJs9rQ++5JB BDfR7nE0eOh1yf7hwqRjOMYot4+tkAzSMoUefSfdfRay+dzgR2NSC8Y2uovkvbiu Ce5YVXCnbBcJB6IlSKuy4YiN65/tucypugpjvgtduCxHegkr7N0tAf+/mokPlGHV AO7BUnTovZQ3/YwIlpayD1kKKpvNtB4dmEPNnji1SMACHteB3PKPoybNlig+244K +G0f4oMUr1LBEwyeFLg0RNxFw8H1JviaVfOiUWaaPqUrJ3BxQk1XmqveI5IHxzB8 yWDywTzyJuai9VI8NU8z7szTGepcNla9RlrixdDHmopS4sgBuxo= =TpAe -----END PGP SIGNATURE----- Merge tag 'i2c-for-6.13-part2' of git://git.kernel.org/pub/scm/linux/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
This commit is contained in:
commit
70dbb12e95
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
@ -67,7 +68,7 @@ properties:
|
||||
|
||||
clock-frequency:
|
||||
minimum: 1
|
||||
maximum: 400000
|
||||
maximum: 3400000
|
||||
|
||||
mobileye,olb:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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 },
|
||||
|
@ -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>
|
||||
@ -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>
|
||||
@ -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;
|
||||
@ -443,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;
|
||||
|
||||
@ -451,30 +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, 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 */
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
@ -1068,15 +1063,39 @@ 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 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");
|
||||
|
@ -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 */
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user