Merge branch 'i2c/for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:
 "Here is the 4.9 pull request from I2C including:

   - centralized error messages when registering to the core
   - improved lockdep annotations to prevent false positives
   - DT support for muxes, gates, and arbitrators
   - bus speeds can now be obtained from ACPI
   - i2c-octeon got refactored and now supports ThunderX SoCs, too
   - i2c-tegra and i2c-designware got a bigger bunch of updates
   - a couple of standard driver fixes and improvements"

* 'i2c/for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (71 commits)
  i2c: axxia: disable clks in case of failure in probe
  i2c: octeon: thunderx: Limit register access retries
  i2c: uniphier-f: fix misdetection of incomplete STOP condition
  gpio: pca953x: variable 'id' was used twice
  i2c: i801: Add support for Kaby Lake PCH-H
  gpio: pca953x: fix an incorrect lockdep warning
  i2c: add a warning to i2c_adapter_depth()
  lockdep: make MAX_LOCKDEP_SUBCLASSES unconditionally visible
  i2c: export i2c_adapter_depth()
  i2c: rk3x: Fix variable 'min_total_ns' unused warning
  i2c: rk3x: Fix sparse warning
  i2c / ACPI: Do not touch an I2C device if it belongs to another adapter
  i2c: octeon: Fix high-level controller status check
  i2c: octeon: Avoid sending STOP during recovery
  i2c: octeon: Fix set SCL recovery function
  i2c: rcar: add support for r8a7796 (R-Car M3-W)
  i2c: imx: make bus recovery through pinctrl optional
  i2c: meson: add gxbb compatible string
  i2c: uniphier-f: set the adapter to master mode when probing
  i2c: uniphier-f: avoid WARN_ON() of clk_disable() in failure path
  ...
This commit is contained in:
Linus Torvalds 2016-10-07 14:12:21 -07:00
commit 87840a2b7e
82 changed files with 2233 additions and 1444 deletions

View File

@ -44,8 +44,7 @@ Required properties:
- our-claim-gpio: The GPIO that we use to claim the bus.
- their-claim-gpios: The GPIOs that the other sides use to claim the bus.
Note that some implementations may only support a single other master.
- Standard I2C mux properties. See i2c-mux.txt in this directory.
- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory.
- I2C arbitration bus node. See i2c-arb.txt in this directory.
Optional properties:
- slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.
@ -63,8 +62,6 @@ Example:
i2c-arbitrator {
compatible = "i2c-arb-gpio-challenge";
#address-cells = <1>;
#size-cells = <0>;
i2c-parent = <&{/i2c@12CA0000}>;
@ -74,8 +71,7 @@ Example:
wait-retry-us = <3000>;
wait-free-us = <50000>;
i2c@0 {
reg = <0>;
i2c-arb {
#address-cells = <1>;
#size-cells = <0>;

View File

@ -0,0 +1,35 @@
Common i2c arbitration bus properties.
- i2c-arb child node
Required properties for the i2c-arb child node:
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties for i2c-arb child node:
- Child nodes conforming to i2c bus binding
Example :
/*
An NXP pca9541 I2C bus master selector at address 0x74
with a NXP pca8574 GPIO expander attached.
*/
arb@74 {
compatible = "nxp,pca9541";
reg = <0x74>;
i2c-arb {
#address-cells = <1>;
#size-cells = <0>;
gpio@38 {
compatible = "nxp,pca8574";
reg = <0x38>;
#gpio-cells = <2>;
gpio-controller;
};
};
};

View File

@ -0,0 +1,41 @@
An i2c gate is useful to e.g. reduce the digital noise for RF tuners connected
to the i2c bus. Gates are similar to arbitrators in that you need to perform
some kind of operation to access the i2c bus past the arbitrator/gate, but
there are no competing masters to consider for gates and therefore there is
no arbitration happening for gates.
Common i2c gate properties.
- i2c-gate child node
Required properties for the i2c-gate child node:
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties for i2c-gate child node:
- Child nodes conforming to i2c bus binding
Example :
/*
An Invensense mpu9150 at address 0x68 featuring an on-chip Asahi
Kasei ak8975 compass behind a gate.
*/
mpu9150@68 {
compatible = "invensense,mpu9150";
reg = <0x68>;
interrupt-parent = <&gpio1>;
interrupts = <18 1>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
ax8975@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};

View File

@ -1,7 +1,7 @@
Amlogic Meson I2C controller
Required properties:
- compatible: must be "amlogic,meson6-i2c"
- compatible: must be "amlogic,meson6-i2c" or "amlogic,meson-gxbb-i2c"
- reg: physical address and length of the device registers
- interrupts: a single interrupt specifier
- clocks: clock for the device

View File

@ -2,19 +2,32 @@ Common i2c bus multiplexer/switch properties.
An i2c bus multiplexer/switch will have several child busses that are
numbered uniquely in a device dependent manner. The nodes for an i2c bus
multiplexer/switch will have one child node for each child
bus.
multiplexer/switch will have one child node for each child bus.
Required properties:
Optional properties:
- #address-cells = <1>;
This property is required is the i2c-mux child node does not exist.
- #size-cells = <0>;
This property is required is the i2c-mux child node does not exist.
- i2c-mux
For i2c multiplexers/switches that have child nodes that are a mixture
of both i2c child busses and other child nodes, the 'i2c-mux' subnode
can be used for populating the i2c child busses. If an 'i2c-mux'
subnode is present, only subnodes of this will be considered as i2c
child busses.
Required properties for the i2c-mux child node:
- #address-cells = <1>;
- #size-cells = <0>;
Required properties for child nodes:
Required properties for i2c child bus nodes:
- #address-cells = <1>;
- #size-cells = <0>;
- reg : The sub-bus number.
Optional properties for child nodes:
Optional properties for i2c child bus nodes:
- Other properties specific to the multiplexer/switch hardware.
- Child nodes conforming to i2c bus binding

View File

@ -11,6 +11,7 @@ Required properties:
"renesas,i2c-r8a7793"
"renesas,i2c-r8a7794"
"renesas,i2c-r8a7795"
"renesas,i2c-r8a7796"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: interrupt specifier.

View File

@ -0,0 +1,29 @@
* NXP PCA9541 I2C bus master selector
Required Properties:
- compatible: Must be "nxp,pca9541"
- reg: The I2C address of the device.
The following required properties are defined externally:
- I2C arbitration bus node. See i2c-arb.txt in this directory.
Example:
i2c-arbitrator@74 {
compatible = "nxp,pca9541";
reg = <0x74>;
i2c-arb {
#address-cells = <1>;
#size-cells = <0>;
eeprom@54 {
compatible = "at,24c08";
reg = <0x54>;
};
};
};

View File

@ -2908,6 +2908,14 @@ S: Maintained
F: drivers/iio/light/cm*
F: Documentation/devicetree/bindings/i2c/trivial-devices.txt
CAVIUM I2C DRIVER
M: Jan Glauber <jglauber@cavium.com>
M: David Daney <david.daney@cavium.com>
W: http://www.cavium.com
S: Supported
F: drivers/i2c/busses/i2c-octeon*
F: drivers/i2c/busses/i2c-thunderx*
CAVIUM LIQUIDIO NETWORK DRIVER
M: Derek Chickles <derek.chickles@caviumnetworks.com>
M: Satanand Burla <satananda.burla@caviumnetworks.com>
@ -5788,6 +5796,8 @@ S: Maintained
F: Documentation/i2c/i2c-topology
F: Documentation/i2c/muxes/
F: Documentation/devicetree/bindings/i2c/i2c-mux*
F: Documentation/devicetree/bindings/i2c/i2c-arb*
F: Documentation/devicetree/bindings/i2c/i2c-gate*
F: drivers/i2c/i2c-mux.c
F: drivers/i2c/muxes/
F: include/linux/i2c-mux.h

View File

@ -732,7 +732,7 @@ out:
static const struct of_device_id pca953x_dt_ids[];
static int pca953x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
const struct i2c_device_id *i2c_id)
{
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
@ -773,27 +773,29 @@ static int pca953x_probe(struct i2c_client *client,
}
chip->regulator = reg;
if (id) {
chip->driver_data = id->driver_data;
if (i2c_id) {
chip->driver_data = i2c_id->driver_data;
} else {
const struct acpi_device_id *id;
const struct acpi_device_id *acpi_id;
const struct of_device_id *match;
match = of_match_device(pca953x_dt_ids, &client->dev);
if (match) {
chip->driver_data = (int)(uintptr_t)match->data;
} else {
id = acpi_match_device(pca953x_acpi_ids, &client->dev);
if (!id) {
acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev);
if (!acpi_id) {
ret = -ENODEV;
goto err_exit;
}
chip->driver_data = id->driver_data;
chip->driver_data = acpi_id->driver_data;
}
}
mutex_init(&chip->i2c_lock);
lockdep_set_subclass(&chip->i2c_lock,
i2c_adapter_depth(client->adapter));
/* initialize cached registers from their original values.
* we can't share this chip with another i2c master.

View File

@ -790,6 +790,12 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags)
mutex_unlock(&i2c_to_aux(i2c)->hw_mutex);
}
static const struct i2c_lock_operations drm_dp_i2c_lock_ops = {
.lock_bus = lock_bus,
.trylock_bus = trylock_bus,
.unlock_bus = unlock_bus,
};
/**
* drm_dp_aux_init() - minimally initialise an aux channel
* @aux: DisplayPort AUX channel
@ -807,9 +813,7 @@ void drm_dp_aux_init(struct drm_dp_aux *aux)
aux->ddc.algo_data = aux;
aux->ddc.retries = 3;
aux->ddc.lock_bus = lock_bus;
aux->ddc.trylock_bus = trylock_bus;
aux->ddc.unlock_bus = unlock_bus;
aux->ddc.lock_ops = &drm_dp_i2c_lock_ops;
}
EXPORT_SYMBOL(drm_dp_aux_init);

View File

@ -836,7 +836,7 @@ config I2C_SH7760
config I2C_SH_MOBILE
tristate "SuperH Mobile I2C Controller"
depends on HAS_DMA
depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
depends on ARCH_SHMOBILE || ARCH_RENESAS || COMPILE_TEST
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Renesas SH-Mobile processor.
@ -956,6 +956,17 @@ config I2C_OCTEON
This driver can also be built as a module. If so, the module
will be called i2c-octeon.
config I2C_THUNDERX
tristate "Cavium ThunderX I2C bus support"
depends on 64BIT && PCI && (ARM64 || COMPILE_TEST)
select I2C_SMBUS
help
Say yes if you want to support the I2C serial bus on Cavium
ThunderX SOC.
This driver can also be built as a module. If so, the module
will be called i2c-thunderx.
config I2C_XILINX
tristate "Xilinx I2C Controller"
depends on HAS_IOMEM

View File

@ -91,7 +91,10 @@ obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_WMT) += i2c-wmt.o
i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o
obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o
obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o

View File

@ -378,11 +378,8 @@ static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
amd756_ioport);
error = i2c_add_adapter(&amd756_smbus);
if (error) {
dev_err(&pdev->dev,
"Adapter registration failed, module not inserted\n");
if (error)
goto out_err;
}
return 0;

View File

@ -1122,8 +1122,6 @@ static int at91_twi_probe(struct platform_device *pdev)
rc = i2c_add_numbered_adapter(&dev->adapter);
if (rc) {
dev_err(dev->dev, "Adapter %s registration failed\n",
dev->adapter.name);
clk_disable_unprepare(dev->clk);
pm_runtime_disable(dev->dev);

View File

@ -545,7 +545,11 @@ static int axxia_i2c_probe(struct platform_device *pdev)
return ret;
}
clk_prepare_enable(idev->i2c_clk);
ret = clk_prepare_enable(idev->i2c_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable clock\n");
return ret;
}
i2c_set_adapdata(&idev->adapter, idev);
strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
@ -560,7 +564,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&idev->adapter);
if (ret) {
dev_err(&pdev->dev, "failed to add adapter\n");
clk_disable_unprepare(idev->i2c_clk);
return ret;
}

View File

@ -488,13 +488,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
ret = i2c_add_adapter(adap);
if (ret) {
dev_err(iproc_i2c->device, "failed to add adapter\n");
return ret;
}
return 0;
return i2c_add_adapter(adap);
}
static int bcm_iproc_i2c_remove(struct platform_device *pdev)

View File

@ -858,10 +858,8 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev)
adap->dev.of_node = pdev->dev.of_node;
rc = i2c_add_adapter(adap);
if (rc) {
dev_err(dev->device, "failed to add adapter\n");
if (rc)
return rc;
}
dev_info(dev->device, "device registered successfully\n");

View File

@ -685,10 +685,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
rc = i2c_add_numbered_adapter(p_adap);
if (rc < 0) {
dev_err(&pdev->dev, "Can't add i2c adapter!\n");
if (rc < 0)
goto out_error;
}
platform_set_drvdata(pdev, iface);

View File

@ -648,10 +648,8 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
rc = i2c_add_adapter(adap);
if (rc) {
dev_err(dev->device, "failed to add adapter\n");
if (rc)
goto probe_errorout;
}
dev_info(dev->device, "%s@%dhz registered in %s mode\n",
int_name ? int_name : " ", dev->clk_freq_hz,

View File

@ -963,10 +963,8 @@ static int cdns_i2c_probe(struct platform_device *pdev)
}
ret = i2c_add_adapter(&id->adap);
if (ret < 0) {
dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
if (ret < 0)
goto err_clk_dis;
}
/*
* Cadence I2C controller has a bug wherein it generates

View File

@ -665,10 +665,8 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
result = i2c_add_numbered_adapter(&cpm->adap);
if (result < 0) {
dev_err(&ofdev->dev, "Unable to register with I2C\n");
if (result < 0)
goto out_shut;
}
dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
cpm->adap.name);

View File

@ -281,10 +281,8 @@ static int ec_i2c_probe(struct platform_device *pdev)
bus->adap.retries = I2C_MAX_RETRIES;
err = i2c_add_adapter(&bus->adap);
if (err) {
dev_err(dev, "cannot register i2c adapter\n");
if (err)
return err;
}
platform_set_drvdata(pdev, bus);
return err;

View File

@ -846,10 +846,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
adap->nr = pdev->id;
r = i2c_add_numbered_adapter(adap);
if (r) {
dev_err(&pdev->dev, "failure adding adapter\n");
if (r)
goto err_unuse_clocks;
}
return 0;

View File

@ -42,6 +42,8 @@
#define DW_IC_SS_SCL_LCNT 0x18
#define DW_IC_FS_SCL_HCNT 0x1c
#define DW_IC_FS_SCL_LCNT 0x20
#define DW_IC_HS_SCL_HCNT 0x24
#define DW_IC_HS_SCL_LCNT 0x28
#define DW_IC_INTR_STAT 0x2c
#define DW_IC_INTR_MASK 0x30
#define DW_IC_RAW_INTR_STAT 0x34
@ -90,11 +92,16 @@
DW_IC_INTR_STOP_DET)
#define DW_IC_STATUS_ACTIVITY 0x1
#define DW_IC_STATUS_TFE BIT(2)
#define DW_IC_STATUS_MST_ACTIVITY BIT(5)
#define DW_IC_ERR_TX_ABRT 0x1
#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3))
#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2)
/*
* status codes
*/
@ -251,11 +258,16 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
}
static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
{
dw_writel(dev, enable, DW_IC_ENABLE);
}
static void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
{
int timeout = 100;
do {
dw_writel(dev, enable, DW_IC_ENABLE);
__i2c_dw_enable(dev, enable);
if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
return;
@ -282,6 +294,28 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
return dev->get_clk_rate_khz(dev);
}
static int i2c_dw_acquire_lock(struct dw_i2c_dev *dev)
{
int ret;
if (!dev->acquire_lock)
return 0;
ret = dev->acquire_lock(dev);
if (!ret)
return 0;
dev_err(dev->dev, "couldn't acquire bus ownership\n");
return ret;
}
static void i2c_dw_release_lock(struct dw_i2c_dev *dev)
{
if (dev->release_lock)
dev->release_lock(dev);
}
/**
* i2c_dw_init() - initialize the designware i2c master hardware
* @dev: device private data
@ -293,17 +327,13 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
int i2c_dw_init(struct dw_i2c_dev *dev)
{
u32 hcnt, lcnt;
u32 reg;
u32 reg, comp_param1;
u32 sda_falling_time, scl_falling_time;
int ret;
if (dev->acquire_lock) {
ret = dev->acquire_lock(dev);
if (ret) {
dev_err(dev->dev, "couldn't acquire bus ownership\n");
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
}
}
reg = dw_readl(dev, DW_IC_COMP_TYPE);
if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
@ -315,13 +345,14 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
} else if (reg != DW_IC_COMP_TYPE_VALUE) {
dev_err(dev->dev, "Unknown Synopsys component type: "
"0x%08x\n", reg);
if (dev->release_lock)
dev->release_lock(dev);
i2c_dw_release_lock(dev);
return -ENODEV;
}
comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
/* Disable the adapter */
__i2c_dw_enable(dev, false);
__i2c_dw_enable_and_wait(dev, false);
/* set standard and fast speed deviders for high/low periods */
@ -347,8 +378,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
/* Set SCL timing parameters for fast-mode */
if (dev->fs_hcnt && dev->fs_lcnt) {
/* Set SCL timing parameters for fast-mode or fast-mode plus */
if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) {
hcnt = dev->fp_hcnt;
lcnt = dev->fp_lcnt;
} else if (dev->fs_hcnt && dev->fs_lcnt) {
hcnt = dev->fs_hcnt;
lcnt = dev->fs_lcnt;
} else {
@ -366,6 +400,23 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
DW_IC_CON_SPEED_HIGH) {
if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
!= DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) {
dev_err(dev->dev, "High Speed not supported!\n");
dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
dev->master_cfg |= DW_IC_CON_SPEED_FAST;
} else if (dev->hs_hcnt && dev->hs_lcnt) {
hcnt = dev->hs_hcnt;
lcnt = dev->hs_lcnt;
dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
hcnt, lcnt);
}
}
/* Configure SDA Hold Time if required */
reg = dw_readl(dev, DW_IC_COMP_VERSION);
if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
@ -387,8 +438,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
/* configure the i2c master */
dw_writel(dev, dev->master_cfg , DW_IC_CON);
if (dev->release_lock)
dev->release_lock(dev);
i2c_dw_release_lock(dev);
return 0;
}
EXPORT_SYMBOL_GPL(i2c_dw_init);
@ -415,27 +466,45 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
{
struct i2c_msg *msgs = dev->msgs;
u32 ic_con, ic_tar = 0;
u32 ic_tar = 0;
bool enabled;
/* Disable the adapter */
__i2c_dw_enable(dev, false);
enabled = dw_readl(dev, DW_IC_ENABLE_STATUS) & 1;
if (enabled) {
u32 ic_status;
/* if the slave address is ten bit address, enable 10BITADDR */
ic_con = dw_readl(dev, DW_IC_CON);
if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) {
ic_con |= DW_IC_CON_10BITADDR_MASTER;
/*
* If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing
* mode has to be enabled via bit 12 of IC_TAR register.
* We set it always as I2C_DYNAMIC_TAR_UPDATE can't be
* detected from registers.
* Only disable adapter if ic_tar and ic_con can't be
* dynamically updated
*/
ic_tar = DW_IC_TAR_10BITADDR_MASTER;
} else {
ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
ic_status = dw_readl(dev, DW_IC_STATUS);
if (!dev->dynamic_tar_update_enabled ||
(ic_status & DW_IC_STATUS_MST_ACTIVITY) ||
!(ic_status & DW_IC_STATUS_TFE)) {
__i2c_dw_enable_and_wait(dev, false);
enabled = false;
}
}
/* if the slave address is ten bit address, enable 10BITADDR */
if (dev->dynamic_tar_update_enabled) {
/*
* If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing
* mode has to be enabled via bit 12 of IC_TAR register,
* otherwise bit 4 of IC_CON is used.
*/
if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
ic_tar = DW_IC_TAR_10BITADDR_MASTER;
} else {
u32 ic_con = dw_readl(dev, DW_IC_CON);
if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
ic_con |= DW_IC_CON_10BITADDR_MASTER;
else
ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
dw_writel(dev, ic_con, DW_IC_CON);
}
/*
* Set the slave (target) address and enable 10-bit addressing mode
@ -446,7 +515,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
/* enforce disabled interrupts (due to HW issues) */
i2c_dw_disable_int(dev);
/* Enable the adapter */
if (!enabled)
__i2c_dw_enable(dev, true);
/* Clear and enable interrupts */
@ -628,7 +697,8 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
}
/*
* Prepare controller for a transaction and call i2c_dw_xfer_msg
* Prepare controller for a transaction and start transfer by calling
* i2c_dw_xfer_init()
*/
static int
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
@ -651,13 +721,9 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev->abort_source = 0;
dev->rx_outstanding = 0;
if (dev->acquire_lock) {
ret = dev->acquire_lock(dev);
if (ret) {
dev_err(dev->dev, "couldn't acquire bus ownership\n");
ret = i2c_dw_acquire_lock(dev);
if (ret)
goto done_nolock;
}
}
ret = i2c_dw_wait_bus_not_busy(dev);
if (ret < 0)
@ -675,16 +741,6 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
goto done;
}
/*
* We must disable the adapter before returning and signaling the end
* of the current transfer. Otherwise the hardware might continue
* generating interrupts which in turn causes a race condition with
* the following transfer. Needs some more investigation if the
* additional interrupts are a hardware bug or this driver doesn't
* handle them correctly yet.
*/
__i2c_dw_enable(dev, false);
if (dev->msg_err) {
ret = dev->msg_err;
goto done;
@ -704,8 +760,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
ret = -EIO;
done:
if (dev->release_lock)
dev->release_lock(dev);
i2c_dw_release_lock(dev);
done_nolock:
pm_runtime_mark_last_busy(dev->dev);
@ -822,9 +877,19 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
*/
tx_aborted:
if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET))
|| dev->msg_err) {
/*
* We must disable interruts before returning and signaling
* the end of the current transfer. Otherwise the hardware
* might continue generating interrupts for non-existent
* transfers.
*/
i2c_dw_disable_int(dev);
dw_readl(dev, DW_IC_CLR_INTR);
complete(&dev->cmd_complete);
else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) {
} else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) {
/* workaround to trigger pending interrupt */
stat = dw_readl(dev, DW_IC_INTR_MASK);
i2c_dw_disable_int(dev);
@ -837,7 +902,7 @@ tx_aborted:
void i2c_dw_disable(struct dw_i2c_dev *dev)
{
/* Disable controller */
__i2c_dw_enable(dev, false);
__i2c_dw_enable_and_wait(dev, false);
/* Disable all interupts */
dw_writel(dev, 0, DW_IC_INTR_MASK);
@ -861,6 +926,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
int r;
u32 reg;
init_completion(&dev->cmd_complete);
@ -868,6 +934,26 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
if (r)
return r;
r = i2c_dw_acquire_lock(dev);
if (r)
return r;
/*
* Test if dynamic TAR update is enabled in this controller by writing
* to IC_10BITADDR_MASTER field in IC_CON: when it is enabled this
* field is read-only so it should not succeed
*/
reg = dw_readl(dev, DW_IC_CON);
dw_writel(dev, reg ^ DW_IC_CON_10BITADDR_MASTER, DW_IC_CON);
if ((dw_readl(dev, DW_IC_CON) & DW_IC_CON_10BITADDR_MASTER) ==
(reg & DW_IC_CON_10BITADDR_MASTER)) {
dev->dynamic_tar_update_enabled = true;
dev_dbg(dev->dev, "Dynamic TAR update enabled");
}
i2c_dw_release_lock(dev);
snprintf(adap->name, sizeof(adap->name),
"Synopsys DesignWare I2C adapter");
adap->retries = 3;

View File

@ -26,6 +26,7 @@
#define DW_IC_CON_MASTER 0x1
#define DW_IC_CON_SPEED_STD 0x2
#define DW_IC_CON_SPEED_FAST 0x4
#define DW_IC_CON_SPEED_HIGH 0x6
#define DW_IC_CON_SPEED_MASK 0x6
#define DW_IC_CON_10BITADDR_MASTER 0x10
#define DW_IC_CON_RESTART_EN 0x20
@ -57,10 +58,15 @@
* @tx_fifo_depth: depth of the hardware tx fifo
* @rx_fifo_depth: depth of the hardware rx fifo
* @rx_outstanding: current master-rx elements in tx fifo
* @clk_freq: bus clock frequency
* @ss_hcnt: standard speed HCNT value
* @ss_lcnt: standard speed LCNT value
* @fs_hcnt: fast speed HCNT value
* @fs_lcnt: fast speed LCNT value
* @fp_hcnt: fast plus HCNT value
* @fp_lcnt: fast plus LCNT value
* @hs_hcnt: high speed HCNT value
* @hs_lcnt: high speed LCNT value
* @acquire_lock: function to acquire a hardware lock on the bus
* @release_lock: function to release a hardware lock on the bus
* @pm_runtime_disabled: true if pm runtime is disabled
@ -96,6 +102,7 @@ struct dw_i2c_dev {
unsigned int tx_fifo_depth;
unsigned int rx_fifo_depth;
int rx_outstanding;
u32 clk_freq;
u32 sda_hold_time;
u32 sda_falling_time;
u32 scl_falling_time;
@ -103,9 +110,14 @@ struct dw_i2c_dev {
u16 ss_lcnt;
u16 fs_hcnt;
u16 fs_lcnt;
u16 fp_hcnt;
u16 fp_lcnt;
u16 hs_hcnt;
u16 hs_lcnt;
int (*acquire_lock)(struct dw_i2c_dev *dev);
void (*release_lock)(struct dw_i2c_dev *dev);
bool pm_runtime_disabled;
bool dynamic_tar_update_enabled;
};
#define ACCESS_SWAP 0x00000001

View File

@ -107,6 +107,8 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, NULL);
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
&dev->sda_hold_time);
dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, NULL);
dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, NULL);
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id && id->driver_data)
@ -155,7 +157,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct resource *mem;
int irq, r;
u32 clk_freq, ht = 0;
u32 acpi_speed, ht = 0;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@ -175,10 +177,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
/* fast mode by default because of legacy reasons */
clk_freq = 400000;
dev->clk_freq = 400000;
if (pdata) {
clk_freq = pdata->i2c_scl_freq;
dev->clk_freq = pdata->i2c_scl_freq;
} else {
device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
&ht);
@ -187,17 +189,24 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
&dev->scl_falling_time);
device_property_read_u32(&pdev->dev, "clock-frequency",
&clk_freq);
&dev->clk_freq);
}
acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
if (acpi_speed)
dev->clk_freq = acpi_speed;
if (has_acpi_companion(&pdev->dev))
dw_i2c_acpi_configure(pdev);
/*
* Only standard mode at 100kHz and fast mode at 400kHz are supported.
* Only standard mode at 100kHz, fast mode at 400kHz,
* fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
*/
if (clk_freq != 100000 && clk_freq != 400000) {
dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
if (dev->clk_freq != 100000 && dev->clk_freq != 400000
&& dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
dev_err(&pdev->dev,
"Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
return -EINVAL;
}
@ -212,12 +221,20 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK;
if (clk_freq == 100000)
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_STD;
else
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
DW_IC_CON_RESTART_EN;
switch (dev->clk_freq) {
case 100000:
dev->master_cfg |= DW_IC_CON_SPEED_STD;
break;
case 3400000:
dev->master_cfg |= DW_IC_CON_SPEED_HIGH;
break;
default:
dev->master_cfg |= DW_IC_CON_SPEED_FAST;
}
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (!i2c_dw_plat_prepare_clk(dev, true)) {

View File

@ -487,10 +487,8 @@ static int diolan_u2c_probe(struct usb_interface *interface,
/* and finally attach to i2c layer */
ret = i2c_add_adapter(&dev->adapter);
if (ret < 0) {
dev_err(&interface->dev, "failed to add I2C adapter\n");
if (ret < 0)
goto error_free;
}
dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");

View File

@ -228,10 +228,8 @@ static int dln2_i2c_probe(struct platform_device *pdev)
/* and finally attach to i2c layer */
ret = i2c_add_adapter(&dln2->adapter);
if (ret < 0) {
dev_err(dev, "failed to add I2C adapter: %d\n", ret);
if (ret < 0)
goto out_disable;
}
return 0;

View File

@ -438,7 +438,6 @@ static int efm32_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&ddata->adapter);
if (ret) {
dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret);
free_irq(ddata->irq, ddata);
err_disable_clk:

View File

@ -796,10 +796,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
exynos5_i2c_reset(i2c);
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
if (ret < 0)
goto err_clk;
}
platform_set_drvdata(pdev, i2c);

View File

@ -478,10 +478,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
pm_runtime_enable(priv->dev);
ret = i2c_add_adapter(&priv->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
if (ret < 0)
goto err_runtime;
}
return ret;

View File

@ -64,6 +64,7 @@
* Broxton (SOC) 0x5ad4 32 hard yes yes yes
* Lewisburg (PCH) 0xa1a3 32 hard yes yes yes
* Lewisburg Supersku (PCH) 0xa223 32 hard yes yes yes
* Kaby Lake PCH-H (PCH) 0xa2a3 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@ -226,6 +227,7 @@
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS 0xa123
#define PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS 0xa1a3
#define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS 0xa223
#define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3
struct i801_mux_config {
char *gpio_chip;
@ -1006,6 +1008,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS) },
{ 0, }
};
@ -1482,6 +1485,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS:
case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS:
case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:
priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ;
priv->features |= FEATURE_SMBUS_PEC;
@ -1615,7 +1619,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
"SMBus I801 adapter at %04lx", priv->smba);
err = i2c_add_adapter(&priv->adapter);
if (err) {
dev_err(&dev->dev, "Failed to add SMBus adapter\n");
i801_acpi_remove(priv);
return err;
}

View File

@ -751,10 +751,8 @@ static int iic_probe(struct platform_device *ofdev)
adap->timeout = HZ;
ret = i2c_add_adapter(adap);
if (ret < 0) {
dev_err(&ofdev->dev, "failed to register i2c adapter\n");
if (ret < 0)
goto error_cleanup;
}
dev_info(&ofdev->dev, "using %s mode\n",
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");

View File

@ -1394,10 +1394,8 @@ static int img_i2c_probe(struct platform_device *pdev)
goto disable_clk;
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add adapter\n");
if (ret < 0)
goto disable_clk;
}
return 0;

View File

@ -984,11 +984,24 @@ static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default);
}
static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
/*
* We switch SCL and SDA to their GPIO function and do some bitbanging
* for bus recovery. These alternative pinmux settings can be
* described in the device tree by a separate pinctrl state "gpio". If
* this is missing this is not a big problem, the only implication is
* that we can't do bus recovery.
*/
static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
struct platform_device *pdev)
{
struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo;
i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
if (!i2c_imx->pinctrl || IS_ERR(i2c_imx->pinctrl)) {
dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n");
return PTR_ERR(i2c_imx->pinctrl);
}
i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl,
PINCTRL_STATE_DEFAULT);
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
@ -1001,7 +1014,7 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
IS_ERR(i2c_imx->pinctrl_pins_default) ||
IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
dev_dbg(&pdev->dev, "recovery information incomplete\n");
return;
return 0;
}
dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
@ -1011,6 +1024,8 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
rinfo->recover_bus = i2c_generic_gpio_recovery;
i2c_imx->adapter.bus_recovery_info = rinfo;
return 0;
}
static u32 i2c_imx_func(struct i2c_adapter *adapter)
@ -1081,12 +1096,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
return ret;
}
i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(i2c_imx->pinctrl)) {
ret = PTR_ERR(i2c_imx->pinctrl);
goto clk_disable;
}
/* Request IRQ */
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
pdev->name, i2c_imx);
@ -1125,14 +1134,16 @@ static int i2c_imx_probe(struct platform_device *pdev)
i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
i2c_imx_init_recovery_info(i2c_imx, pdev);
/* Init optional bus recovery function */
ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
/* Give it another chance if pinctrl used is not ready yet */
if (ret == -EPROBE_DEFER)
goto rpm_disable;
/* Add I2C adapter */
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0) {
dev_err(&pdev->dev, "registration failed\n");
if (ret < 0)
goto rpm_disable;
}
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);

View File

@ -288,10 +288,8 @@ static int smbus_sch_probe(struct platform_device *dev)
"SMBus SCH adapter at %04x", sch_smba);
retval = i2c_add_adapter(&sch_adapter);
if (retval) {
dev_err(&dev->dev, "Couldn't register adapter!\n");
if (retval)
sch_smba = 0;
}
return retval;
}

View File

@ -922,10 +922,8 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return err;
err = i2c_add_adapter(&priv->adapter);
if (err) {
dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n");
if (err)
return -ENODEV;
}
return 0;
}

View File

@ -798,10 +798,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
goto err;
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to add bus\n");
if (ret < 0)
goto err;
}
return 0;

View File

@ -432,10 +432,8 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
i2c->adap.dev.of_node = pdev->dev.of_node;
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add adapter!\n");
if (ret < 0)
goto fail_clk;
}
dev_info(&pdev->dev, "LPC2K I2C adapter\n");

View File

@ -453,7 +453,6 @@ static int meson_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "can't register adapter\n");
clk_unprepare(i2c->clk);
return ret;
}
@ -473,6 +472,7 @@ static int meson_i2c_remove(struct platform_device *pdev)
static const struct of_device_id meson_i2c_match[] = {
{ .compatible = "amlogic,meson6-i2c" },
{ .compatible = "amlogic,meson-gxbb-i2c" },
{ },
};
MODULE_DEVICE_TABLE(of, meson_i2c_match);

View File

@ -737,10 +737,8 @@ static int fsl_i2c_probe(struct platform_device *op)
i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
result = i2c_add_adapter(&i2c->adap);
if (result < 0) {
dev_err(i2c->dev, "failed to add adapter\n");
if (result < 0)
goto fail_add;
}
return result;

View File

@ -786,10 +786,8 @@ static int mtk_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&i2c->adap, i2c);
ret = i2c_add_adapter(&i2c->adap);
if (ret) {
dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
if (ret)
return ret;
}
platform_set_drvdata(pdev, i2c);

View File

@ -868,7 +868,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, i2c);
err = i2c_add_numbered_adapter(adap);
if (err) {
dev_err(dev, "Failed to add adapter (%d)\n", err);
writel(MXS_I2C_CTRL0_SFTRST,
i2c->regs + MXS_I2C_CTRL0_SET);
return err;

View File

@ -366,7 +366,6 @@ static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
error = i2c_add_adapter(&smbus->adapter);
if (error) {
dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
release_region(smbus->base, smbus->size);
return error;
}

View File

@ -1046,10 +1046,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
adap->name, dev->virtbase);
ret = i2c_add_adapter(adap);
if (ret) {
dev_err(&adev->dev, "failed to add adapter\n");
if (ret)
goto err_no_adap;
}
pm_runtime_put(&adev->dev);

View File

@ -494,10 +494,8 @@ static int ocores_i2c_probe(struct platform_device *pdev)
/* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap);
if (ret) {
dev_err(&pdev->dev, "Failed to add adapter\n");
if (ret)
goto err_clk;
}
/* add in known devices to the bus */
if (pdata) {

View File

@ -0,0 +1,216 @@
#include <linux/atomic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/pci.h>
/* Controller command patterns */
#define SW_TWSI_V BIT_ULL(63) /* Valid bit */
#define SW_TWSI_EIA BIT_ULL(61) /* Extended internal address */
#define SW_TWSI_R BIT_ULL(56) /* Result or read bit */
#define SW_TWSI_SOVR BIT_ULL(55) /* Size override */
#define SW_TWSI_SIZE_SHIFT 52
#define SW_TWSI_ADDR_SHIFT 40
#define SW_TWSI_IA_SHIFT 32 /* Internal address */
/* Controller opcode word (bits 60:57) */
#define SW_TWSI_OP_SHIFT 57
#define SW_TWSI_OP_7 (0ULL << SW_TWSI_OP_SHIFT)
#define SW_TWSI_OP_7_IA (1ULL << SW_TWSI_OP_SHIFT)
#define SW_TWSI_OP_10 (2ULL << SW_TWSI_OP_SHIFT)
#define SW_TWSI_OP_10_IA (3ULL << SW_TWSI_OP_SHIFT)
#define SW_TWSI_OP_TWSI_CLK (4ULL << SW_TWSI_OP_SHIFT)
#define SW_TWSI_OP_EOP (6ULL << SW_TWSI_OP_SHIFT) /* Extended opcode */
/* Controller extended opcode word (bits 34:32) */
#define SW_TWSI_EOP_SHIFT 32
#define SW_TWSI_EOP_TWSI_DATA (SW_TWSI_OP_EOP | 1ULL << SW_TWSI_EOP_SHIFT)
#define SW_TWSI_EOP_TWSI_CTL (SW_TWSI_OP_EOP | 2ULL << SW_TWSI_EOP_SHIFT)
#define SW_TWSI_EOP_TWSI_CLKCTL (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT)
#define SW_TWSI_EOP_TWSI_STAT (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT)
#define SW_TWSI_EOP_TWSI_RST (SW_TWSI_OP_EOP | 7ULL << SW_TWSI_EOP_SHIFT)
/* Controller command and status bits */
#define TWSI_CTL_CE 0x80 /* High level controller enable */
#define TWSI_CTL_ENAB 0x40 /* Bus enable */
#define TWSI_CTL_STA 0x20 /* Master-mode start, HW clears when done */
#define TWSI_CTL_STP 0x10 /* Master-mode stop, HW clears when done */
#define TWSI_CTL_IFLG 0x08 /* HW event, SW writes 0 to ACK */
#define TWSI_CTL_AAK 0x04 /* Assert ACK */
/* Status values */
#define STAT_ERROR 0x00
#define STAT_START 0x08
#define STAT_REP_START 0x10
#define STAT_TXADDR_ACK 0x18
#define STAT_TXADDR_NAK 0x20
#define STAT_TXDATA_ACK 0x28
#define STAT_TXDATA_NAK 0x30
#define STAT_LOST_ARB_38 0x38
#define STAT_RXADDR_ACK 0x40
#define STAT_RXADDR_NAK 0x48
#define STAT_RXDATA_ACK 0x50
#define STAT_RXDATA_NAK 0x58
#define STAT_SLAVE_60 0x60
#define STAT_LOST_ARB_68 0x68
#define STAT_SLAVE_70 0x70
#define STAT_LOST_ARB_78 0x78
#define STAT_SLAVE_80 0x80
#define STAT_SLAVE_88 0x88
#define STAT_GENDATA_ACK 0x90
#define STAT_GENDATA_NAK 0x98
#define STAT_SLAVE_A0 0xA0
#define STAT_SLAVE_A8 0xA8
#define STAT_LOST_ARB_B0 0xB0
#define STAT_SLAVE_LOST 0xB8
#define STAT_SLAVE_NAK 0xC0
#define STAT_SLAVE_ACK 0xC8
#define STAT_AD2W_ACK 0xD0
#define STAT_AD2W_NAK 0xD8
#define STAT_IDLE 0xF8
/* TWSI_INT values */
#define TWSI_INT_ST_INT BIT_ULL(0)
#define TWSI_INT_TS_INT BIT_ULL(1)
#define TWSI_INT_CORE_INT BIT_ULL(2)
#define TWSI_INT_ST_EN BIT_ULL(4)
#define TWSI_INT_TS_EN BIT_ULL(5)
#define TWSI_INT_CORE_EN BIT_ULL(6)
#define TWSI_INT_SDA_OVR BIT_ULL(8)
#define TWSI_INT_SCL_OVR BIT_ULL(9)
#define TWSI_INT_SDA BIT_ULL(10)
#define TWSI_INT_SCL BIT_ULL(11)
#define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */
/* Register offsets */
struct octeon_i2c_reg_offset {
unsigned int sw_twsi;
unsigned int twsi_int;
unsigned int sw_twsi_ext;
};
#define SW_TWSI(x) (x->roff.sw_twsi)
#define TWSI_INT(x) (x->roff.twsi_int)
#define SW_TWSI_EXT(x) (x->roff.sw_twsi_ext)
struct octeon_i2c {
wait_queue_head_t queue;
struct i2c_adapter adap;
struct octeon_i2c_reg_offset roff;
struct clk *clk;
int irq;
int hlc_irq; /* For cn7890 only */
u32 twsi_freq;
int sys_freq;
void __iomem *twsi_base;
struct device *dev;
bool hlc_enabled;
bool broken_irq_mode;
bool broken_irq_check;
void (*int_enable)(struct octeon_i2c *);
void (*int_disable)(struct octeon_i2c *);
void (*hlc_int_enable)(struct octeon_i2c *);
void (*hlc_int_disable)(struct octeon_i2c *);
atomic_t int_enable_cnt;
atomic_t hlc_int_enable_cnt;
#if IS_ENABLED(CONFIG_I2C_THUNDERX)
struct msix_entry i2c_msix;
#endif
struct i2c_smbus_alert_setup alert_data;
struct i2c_client *ara;
};
static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
{
__raw_writeq(val, addr);
__raw_readq(addr); /* wait for write to land */
}
/**
* octeon_i2c_reg_write - write an I2C core register
* @i2c: The struct octeon_i2c
* @eop_reg: Register selector
* @data: Value to be written
*
* The I2C core registers are accessed indirectly via the SW_TWSI CSR.
*/
static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
{
u64 tmp;
__raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c));
readq_poll_timeout(i2c->twsi_base + SW_TWSI(i2c), tmp, tmp & SW_TWSI_V,
I2C_OCTEON_EVENT_WAIT, i2c->adap.timeout);
}
#define octeon_i2c_ctl_write(i2c, val) \
octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, val)
#define octeon_i2c_data_write(i2c, val) \
octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, val)
/**
* octeon_i2c_reg_read - read lower bits of an I2C core register
* @i2c: The struct octeon_i2c
* @eop_reg: Register selector
*
* Returns the data.
*
* The I2C core registers are accessed indirectly via the SW_TWSI CSR.
*/
static inline int octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg,
int *error)
{
u64 tmp;
int ret;
__raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c));
ret = readq_poll_timeout(i2c->twsi_base + SW_TWSI(i2c), tmp,
tmp & SW_TWSI_V, I2C_OCTEON_EVENT_WAIT,
i2c->adap.timeout);
if (error)
*error = ret;
return tmp & 0xFF;
}
#define octeon_i2c_ctl_read(i2c) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL)
#define octeon_i2c_data_read(i2c, error) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error)
#define octeon_i2c_stat_read(i2c) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT, NULL)
/**
* octeon_i2c_read_int - read the TWSI_INT register
* @i2c: The struct octeon_i2c
*
* Returns the value of the register.
*/
static inline u64 octeon_i2c_read_int(struct octeon_i2c *i2c)
{
return __raw_readq(i2c->twsi_base + TWSI_INT(i2c));
}
/**
* octeon_i2c_write_int - write the TWSI_INT register
* @i2c: The struct octeon_i2c
* @data: Value to be written
*/
static inline void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
{
octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT(i2c));
}
/* Prototypes */
irqreturn_t octeon_i2c_isr(int irq, void *dev_id);
int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c);
void octeon_i2c_set_clock(struct octeon_i2c *i2c);
extern struct i2c_bus_recovery_info octeon_i2c_recovery_info;

View File

@ -0,0 +1,286 @@
/*
* (C) Copyright 2009-2010
* Nokia Siemens Networks, michael.lawnick.ext@nsn.com
*
* Portions Copyright (C) 2010 - 2016 Cavium, Inc.
*
* This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <asm/octeon/octeon.h>
#include "i2c-octeon-core.h"
#define DRV_NAME "i2c-octeon"
/**
* octeon_i2c_int_enable - enable the CORE interrupt
* @i2c: The struct octeon_i2c
*
* The interrupt will be asserted when there is non-STAT_IDLE state in
* the SW_TWSI_EOP_TWSI_STAT register.
*/
static void octeon_i2c_int_enable(struct octeon_i2c *i2c)
{
octeon_i2c_write_int(i2c, TWSI_INT_CORE_EN);
}
/* disable the CORE interrupt */
static void octeon_i2c_int_disable(struct octeon_i2c *i2c)
{
/* clear TS/ST/IFLG events */
octeon_i2c_write_int(i2c, 0);
}
/**
* octeon_i2c_int_enable78 - enable the CORE interrupt
* @i2c: The struct octeon_i2c
*
* The interrupt will be asserted when there is non-STAT_IDLE state in the
* SW_TWSI_EOP_TWSI_STAT register.
*/
static void octeon_i2c_int_enable78(struct octeon_i2c *i2c)
{
atomic_inc_return(&i2c->int_enable_cnt);
enable_irq(i2c->irq);
}
static void __octeon_i2c_irq_disable(atomic_t *cnt, int irq)
{
int count;
/*
* The interrupt can be disabled in two places, but we only
* want to make the disable_irq_nosync() call once, so keep
* track with the atomic variable.
*/
count = atomic_dec_if_positive(cnt);
if (count >= 0)
disable_irq_nosync(irq);
}
/* disable the CORE interrupt */
static void octeon_i2c_int_disable78(struct octeon_i2c *i2c)
{
__octeon_i2c_irq_disable(&i2c->int_enable_cnt, i2c->irq);
}
/**
* octeon_i2c_hlc_int_enable78 - enable the ST interrupt
* @i2c: The struct octeon_i2c
*
* The interrupt will be asserted when there is non-STAT_IDLE state in
* the SW_TWSI_EOP_TWSI_STAT register.
*/
static void octeon_i2c_hlc_int_enable78(struct octeon_i2c *i2c)
{
atomic_inc_return(&i2c->hlc_int_enable_cnt);
enable_irq(i2c->hlc_irq);
}
/* disable the ST interrupt */
static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c)
{
__octeon_i2c_irq_disable(&i2c->hlc_int_enable_cnt, i2c->hlc_irq);
}
/* HLC interrupt service routine */
static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id)
{
struct octeon_i2c *i2c = dev_id;
i2c->hlc_int_disable(i2c);
wake_up(&i2c->queue);
return IRQ_HANDLED;
}
static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c)
{
octeon_i2c_write_int(i2c, TWSI_INT_ST_EN);
}
static u32 octeon_i2c_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL;
}
static const struct i2c_algorithm octeon_i2c_algo = {
.master_xfer = octeon_i2c_xfer,
.functionality = octeon_i2c_functionality,
};
static struct i2c_adapter octeon_i2c_ops = {
.owner = THIS_MODULE,
.name = "OCTEON adapter",
.algo = &octeon_i2c_algo,
};
static int octeon_i2c_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
int irq, result = 0, hlc_irq = 0;
struct resource *res_mem;
struct octeon_i2c *i2c;
bool cn78xx_style;
cn78xx_style = of_device_is_compatible(node, "cavium,octeon-7890-twsi");
if (cn78xx_style) {
hlc_irq = platform_get_irq(pdev, 0);
if (hlc_irq < 0)
return hlc_irq;
irq = platform_get_irq(pdev, 2);
if (irq < 0)
return irq;
} else {
/* All adaptors have an irq. */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
}
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) {
result = -ENOMEM;
goto out;
}
i2c->dev = &pdev->dev;
i2c->roff.sw_twsi = 0x00;
i2c->roff.twsi_int = 0x10;
i2c->roff.sw_twsi_ext = 0x18;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c->twsi_base = devm_ioremap_resource(&pdev->dev, res_mem);
if (IS_ERR(i2c->twsi_base)) {
result = PTR_ERR(i2c->twsi_base);
goto out;
}
/*
* "clock-rate" is a legacy binding, the official binding is
* "clock-frequency". Try the official one first and then
* fall back if it doesn't exist.
*/
if (of_property_read_u32(node, "clock-frequency", &i2c->twsi_freq) &&
of_property_read_u32(node, "clock-rate", &i2c->twsi_freq)) {
dev_err(i2c->dev,
"no I2C 'clock-rate' or 'clock-frequency' property\n");
result = -ENXIO;
goto out;
}
i2c->sys_freq = octeon_get_io_clock_rate();
init_waitqueue_head(&i2c->queue);
i2c->irq = irq;
if (cn78xx_style) {
i2c->hlc_irq = hlc_irq;
i2c->int_enable = octeon_i2c_int_enable78;
i2c->int_disable = octeon_i2c_int_disable78;
i2c->hlc_int_enable = octeon_i2c_hlc_int_enable78;
i2c->hlc_int_disable = octeon_i2c_hlc_int_disable78;
irq_set_status_flags(i2c->irq, IRQ_NOAUTOEN);
irq_set_status_flags(i2c->hlc_irq, IRQ_NOAUTOEN);
result = devm_request_irq(&pdev->dev, i2c->hlc_irq,
octeon_i2c_hlc_isr78, 0,
DRV_NAME, i2c);
if (result < 0) {
dev_err(i2c->dev, "failed to attach interrupt\n");
goto out;
}
} else {
i2c->int_enable = octeon_i2c_int_enable;
i2c->int_disable = octeon_i2c_int_disable;
i2c->hlc_int_enable = octeon_i2c_hlc_int_enable;
i2c->hlc_int_disable = octeon_i2c_int_disable;
}
result = devm_request_irq(&pdev->dev, i2c->irq,
octeon_i2c_isr, 0, DRV_NAME, i2c);
if (result < 0) {
dev_err(i2c->dev, "failed to attach interrupt\n");
goto out;
}
if (OCTEON_IS_MODEL(OCTEON_CN38XX))
i2c->broken_irq_check = true;
result = octeon_i2c_init_lowlevel(i2c);
if (result) {
dev_err(i2c->dev, "init low level failed\n");
goto out;
}
octeon_i2c_set_clock(i2c);
i2c->adap = octeon_i2c_ops;
i2c->adap.timeout = msecs_to_jiffies(2);
i2c->adap.retries = 5;
i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = node;
i2c_set_adapdata(&i2c->adap, i2c);
platform_set_drvdata(pdev, i2c);
result = i2c_add_adapter(&i2c->adap);
if (result < 0)
goto out;
dev_info(i2c->dev, "probed\n");
return 0;
out:
return result;
};
static int octeon_i2c_remove(struct platform_device *pdev)
{
struct octeon_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
return 0;
};
static const struct of_device_id octeon_i2c_match[] = {
{ .compatible = "cavium,octeon-3860-twsi", },
{ .compatible = "cavium,octeon-7890-twsi", },
{},
};
MODULE_DEVICE_TABLE(of, octeon_i2c_match);
static struct platform_driver octeon_i2c_driver = {
.probe = octeon_i2c_probe,
.remove = octeon_i2c_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = octeon_i2c_match,
},
};
module_platform_driver(octeon_i2c_driver);
MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");
MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
MODULE_LICENSE("GPL");

View File

@ -1425,10 +1425,8 @@ omap_i2c_probe(struct platform_device *pdev)
/* i2c device drivers may be active on return from add_adapter() */
adap->nr = pdev->id;
r = i2c_add_numbered_adapter(adap);
if (r) {
dev_err(omap->dev, "failure adding adapter\n");
if (r)
goto err_unuse_clocks;
}
dev_info(omap->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
major, minor, omap->speed);

View File

@ -694,7 +694,6 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
retval = i2c_add_adapter(adap);
if (retval) {
dev_err(&dev->dev, "Couldn't register adapter!\n");
kfree(adapdata);
kfree(adap);
release_region(smba, SMBIOSIZE);

View File

@ -329,10 +329,8 @@ static int pmcmsptwi_probe(struct platform_device *pldev)
i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
rc = i2c_add_adapter(&pmcmsptwi_adapter);
if (rc) {
dev_err(&pldev->dev, "Unable to register I2C adapter\n");
if (rc)
goto ret_unmap;
}
return 0;

View File

@ -714,10 +714,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
/* Register this adapter with the I2C subsystem */
ret = i2c_add_numbered_adapter(&alg_data->adapter);
if (ret < 0) {
dev_err(&pdev->dev, "I2C: Failed to add bus\n");
if (ret < 0)
goto out_clock;
}
dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
alg_data->adapter.name, res->start, alg_data->irq);

View File

@ -212,11 +212,8 @@ static int puv3_i2c_probe(struct platform_device *pdev)
adapter->nr = pdev->id;
rc = i2c_add_numbered_adapter(adapter);
if (rc) {
dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
adapter->name);
if (rc)
goto fail_add_adapter;
}
dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
return 0;

View File

@ -1292,10 +1292,8 @@ static int i2c_pxa_probe(struct platform_device *dev)
#endif
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&dev->dev, "failed to add bus: %d\n", ret);
if (ret < 0)
goto ereqirq;
}
platform_set_drvdata(dev, i2c);

View File

@ -802,6 +802,7 @@ static const struct of_device_id rcar_i2c_dt_ids[] = {
{ .compatible = "renesas,i2c-r8a7793", .data = (void *)I2C_RCAR_GEN2 },
{ .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 },
{},
};
MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
@ -875,10 +876,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(dev, "reg adap failed: %d\n", ret);
if (ret < 0)
goto out_pm_disable;
}
dev_info(dev, "probed\n");

View File

@ -383,10 +383,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(adap);
if (ret) {
dev_err(&pdev->dev, "failed to add adapter\n");
if (ret)
return ret;
}
platform_set_drvdata(pdev, riic);

View File

@ -58,7 +58,7 @@ enum {
#define REG_CON_LASTACK BIT(5) /* 1: send NACK after last received byte */
#define REG_CON_ACTACK BIT(6) /* 1: stop if NACK is received */
#define REG_CON_TUNING_MASK GENMASK(15, 8)
#define REG_CON_TUNING_MASK GENMASK_ULL(15, 8)
#define REG_CON_SDA_CFG(cfg) ((cfg) << 8)
#define REG_CON_STA_CFG(cfg) ((cfg) << 12)
@ -742,7 +742,7 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
struct i2c_timings *t,
struct rk3x_i2c_calced_timings *t_calc)
{
unsigned long min_low_ns, min_high_ns, min_total_ns;
unsigned long min_low_ns, min_high_ns;
unsigned long min_setup_start_ns, min_setup_data_ns;
unsigned long min_setup_stop_ns, max_hold_data_ns;
@ -793,7 +793,6 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
/* These are the min dividers needed for min hold times. */
min_div_for_hold = (min_low_div + min_high_div);
min_total_ns = min_low_ns + min_high_ns;
/*
* This is the maximum divider so we don't go over the maximum.
@ -1312,10 +1311,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
rk3x_i2c_adapt_div(i2c, clk_rate);
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register adapter\n");
if (ret < 0)
goto err_clk_notifier;
}
dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);

View File

@ -1215,7 +1215,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
pm_runtime_disable(&pdev->dev);
s3c24xx_i2c_deregister_cpufreq(i2c);
clk_unprepare(i2c->clk);

View File

@ -510,10 +510,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
}
ret = i2c_add_numbered_adapter(&id->adap);
if (ret < 0) {
dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
if (ret < 0)
goto out4;
}
platform_set_drvdata(pdev, id);

View File

@ -981,7 +981,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
sh_mobile_i2c_release_dma(pd);
dev_err(&dev->dev, "cannot add numbered adapter\n");
return ret;
}

View File

@ -387,10 +387,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY);
err = i2c_add_numbered_adapter(adap);
if (err < 0) {
dev_err(&pdev->dev, "Can't add new i2c adapter\n");
if (err < 0)
goto out;
}
clk_disable(clk);

View File

@ -874,10 +874,8 @@ static int st_i2c_probe(struct platform_device *pdev)
init_completion(&i2c_dev->complete);
ret = i2c_add_adapter(adap);
if (ret) {
dev_err(&pdev->dev, "Failed to add adapter\n");
if (ret)
return ret;
}
platform_set_drvdata(pdev, i2c_dev);

View File

@ -920,11 +920,8 @@ static int stu300_probe(struct platform_device *pdev)
/* i2c device drivers may be active on return from add_adapter() */
ret = i2c_add_numbered_adapter(adap);
if (ret) {
dev_err(&pdev->dev, "failure adding ST Micro DDC "
"I2C adapter\n");
if (ret)
return ret;
}
platform_set_drvdata(pdev, dev);
dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n",

View File

@ -28,6 +28,9 @@
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/reset.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/iopoll.h>
#include <asm/unaligned.h>
@ -36,21 +39,21 @@
#define I2C_CNFG 0x000
#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12
#define I2C_CNFG_PACKET_MODE_EN (1<<10)
#define I2C_CNFG_NEW_MASTER_FSM (1<<11)
#define I2C_CNFG_MULTI_MASTER_MODE (1<<17)
#define I2C_CNFG_PACKET_MODE_EN BIT(10)
#define I2C_CNFG_NEW_MASTER_FSM BIT(11)
#define I2C_CNFG_MULTI_MASTER_MODE BIT(17)
#define I2C_STATUS 0x01C
#define I2C_SL_CNFG 0x020
#define I2C_SL_CNFG_NACK (1<<1)
#define I2C_SL_CNFG_NEWSL (1<<2)
#define I2C_SL_CNFG_NACK BIT(1)
#define I2C_SL_CNFG_NEWSL BIT(2)
#define I2C_SL_ADDR1 0x02c
#define I2C_SL_ADDR2 0x030
#define I2C_TX_FIFO 0x050
#define I2C_RX_FIFO 0x054
#define I2C_PACKET_TRANSFER_STATUS 0x058
#define I2C_FIFO_CONTROL 0x05c
#define I2C_FIFO_CONTROL_TX_FLUSH (1<<1)
#define I2C_FIFO_CONTROL_RX_FLUSH (1<<0)
#define I2C_FIFO_CONTROL_TX_FLUSH BIT(1)
#define I2C_FIFO_CONTROL_RX_FLUSH BIT(0)
#define I2C_FIFO_CONTROL_TX_TRIG_SHIFT 5
#define I2C_FIFO_CONTROL_RX_TRIG_SHIFT 2
#define I2C_FIFO_STATUS 0x060
@ -60,26 +63,26 @@
#define I2C_FIFO_STATUS_RX_SHIFT 0
#define I2C_INT_MASK 0x064
#define I2C_INT_STATUS 0x068
#define I2C_INT_PACKET_XFER_COMPLETE (1<<7)
#define I2C_INT_ALL_PACKETS_XFER_COMPLETE (1<<6)
#define I2C_INT_TX_FIFO_OVERFLOW (1<<5)
#define I2C_INT_RX_FIFO_UNDERFLOW (1<<4)
#define I2C_INT_NO_ACK (1<<3)
#define I2C_INT_ARBITRATION_LOST (1<<2)
#define I2C_INT_TX_FIFO_DATA_REQ (1<<1)
#define I2C_INT_RX_FIFO_DATA_REQ (1<<0)
#define I2C_INT_PACKET_XFER_COMPLETE BIT(7)
#define I2C_INT_ALL_PACKETS_XFER_COMPLETE BIT(6)
#define I2C_INT_TX_FIFO_OVERFLOW BIT(5)
#define I2C_INT_RX_FIFO_UNDERFLOW BIT(4)
#define I2C_INT_NO_ACK BIT(3)
#define I2C_INT_ARBITRATION_LOST BIT(2)
#define I2C_INT_TX_FIFO_DATA_REQ BIT(1)
#define I2C_INT_RX_FIFO_DATA_REQ BIT(0)
#define I2C_CLK_DIVISOR 0x06c
#define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT 16
#define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8
#define DVC_CTRL_REG1 0x000
#define DVC_CTRL_REG1_INTR_EN (1<<10)
#define DVC_CTRL_REG1_INTR_EN BIT(10)
#define DVC_CTRL_REG2 0x004
#define DVC_CTRL_REG3 0x008
#define DVC_CTRL_REG3_SW_PROG (1<<26)
#define DVC_CTRL_REG3_I2C_DONE_INTR_EN (1<<30)
#define DVC_CTRL_REG3_SW_PROG BIT(26)
#define DVC_CTRL_REG3_I2C_DONE_INTR_EN BIT(30)
#define DVC_STATUS 0x00c
#define DVC_STATUS_I2C_DONE_INTR (1<<30)
#define DVC_STATUS_I2C_DONE_INTR BIT(30)
#define I2C_ERR_NONE 0x00
#define I2C_ERR_NO_ACK 0x01
@ -89,26 +92,28 @@
#define PACKET_HEADER0_HEADER_SIZE_SHIFT 28
#define PACKET_HEADER0_PACKET_ID_SHIFT 16
#define PACKET_HEADER0_CONT_ID_SHIFT 12
#define PACKET_HEADER0_PROTOCOL_I2C (1<<4)
#define PACKET_HEADER0_PROTOCOL_I2C BIT(4)
#define I2C_HEADER_HIGHSPEED_MODE (1<<22)
#define I2C_HEADER_CONT_ON_NAK (1<<21)
#define I2C_HEADER_SEND_START_BYTE (1<<20)
#define I2C_HEADER_READ (1<<19)
#define I2C_HEADER_10BIT_ADDR (1<<18)
#define I2C_HEADER_IE_ENABLE (1<<17)
#define I2C_HEADER_REPEAT_START (1<<16)
#define I2C_HEADER_CONTINUE_XFER (1<<15)
#define I2C_HEADER_HIGHSPEED_MODE BIT(22)
#define I2C_HEADER_CONT_ON_NAK BIT(21)
#define I2C_HEADER_SEND_START_BYTE BIT(20)
#define I2C_HEADER_READ BIT(19)
#define I2C_HEADER_10BIT_ADDR BIT(18)
#define I2C_HEADER_IE_ENABLE BIT(17)
#define I2C_HEADER_REPEAT_START BIT(16)
#define I2C_HEADER_CONTINUE_XFER BIT(15)
#define I2C_HEADER_MASTER_ADDR_SHIFT 12
#define I2C_HEADER_SLAVE_ADDR_SHIFT 1
#define I2C_CONFIG_LOAD 0x08C
#define I2C_MSTR_CONFIG_LOAD (1 << 0)
#define I2C_SLV_CONFIG_LOAD (1 << 1)
#define I2C_TIMEOUT_CONFIG_LOAD (1 << 2)
#define I2C_MSTR_CONFIG_LOAD BIT(0)
#define I2C_SLV_CONFIG_LOAD BIT(1)
#define I2C_TIMEOUT_CONFIG_LOAD BIT(2)
#define I2C_CLKEN_OVERRIDE 0x090
#define I2C_MST_CORE_CLKEN_OVR (1 << 0)
#define I2C_MST_CORE_CLKEN_OVR BIT(0)
#define I2C_CONFIG_LOAD_TIMEOUT 1000000
/*
* msg_end_type: The bus control which need to be send at end of transfer.
@ -191,9 +196,11 @@ struct tegra_i2c_dev {
u16 clk_divisor_non_hs_mode;
bool is_suspended;
bool is_multimaster_mode;
spinlock_t xfer_lock;
};
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg)
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned long reg)
{
writel(val, i2c_dev->base + reg);
}
@ -244,15 +251,17 @@ static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
{
u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK);
int_mask &= ~mask;
u32 int_mask;
int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) & ~mask;
i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
}
static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
{
u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK);
int_mask |= mask;
u32 int_mask;
int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) | mask;
i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
}
@ -260,6 +269,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
{
unsigned long timeout = jiffies + HZ;
u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL);
val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH;
i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
@ -385,7 +395,8 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
*/
static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
{
u32 val = 0;
u32 val;
val = dvc_readl(i2c_dev, DVC_CTRL_REG3);
val |= DVC_CTRL_REG3_SW_PROG;
val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN;
@ -396,9 +407,15 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
}
static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev)
static int tegra_i2c_runtime_resume(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int ret;
ret = pinctrl_pm_select_default_state(i2c_dev->dev);
if (ret)
return ret;
if (!i2c_dev->hw->has_single_clk_source) {
ret = clk_enable(i2c_dev->fast_clk);
if (ret < 0) {
@ -407,32 +424,66 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev)
return ret;
}
}
ret = clk_enable(i2c_dev->div_clk);
if (ret < 0) {
dev_err(i2c_dev->dev,
"Enabling div clk failed, err %d\n", ret);
clk_disable(i2c_dev->fast_clk);
}
return ret;
}
static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev)
return 0;
}
static int tegra_i2c_runtime_suspend(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
clk_disable(i2c_dev->div_clk);
if (!i2c_dev->hw->has_single_clk_source)
clk_disable(i2c_dev->fast_clk);
return pinctrl_pm_select_idle_state(i2c_dev->dev);
}
static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
{
unsigned long reg_offset;
void __iomem *addr;
u32 val;
int err;
if (i2c_dev->hw->has_config_load_reg) {
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD);
addr = i2c_dev->base + reg_offset;
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
if (in_interrupt())
err = readl_poll_timeout_atomic(addr, val, val == 0,
1000, I2C_CONFIG_LOAD_TIMEOUT);
else
err = readl_poll_timeout(addr, val, val == 0,
1000, I2C_CONFIG_LOAD_TIMEOUT);
if (err) {
dev_warn(i2c_dev->dev,
"timeout waiting for config load\n");
return err;
}
}
return 0;
}
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
int err = 0;
int err;
u32 clk_divisor;
unsigned long timeout = jiffies + HZ;
err = tegra_i2c_clock_enable(i2c_dev);
err = pm_runtime_get_sync(i2c_dev->dev);
if (err < 0) {
dev_err(i2c_dev->dev, "Clock enable failed %d\n", err);
dev_err(i2c_dev->dev, "runtime resume failed %d\n", err);
return err;
}
@ -460,54 +511,59 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
if (!i2c_dev->is_dvc) {
u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL;
i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG);
i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1);
i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);
}
val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
if (tegra_i2c_flush_fifos(i2c_dev))
err = -ETIMEDOUT;
err = tegra_i2c_flush_fifos(i2c_dev);
if (err)
goto err;
if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
if (i2c_dev->hw->has_config_load_reg) {
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
while (i2c_readl(i2c_dev, I2C_CONFIG_LOAD) != 0) {
if (time_after(jiffies, timeout)) {
dev_warn(i2c_dev->dev,
"timeout waiting for config load\n");
err = -ETIMEDOUT;
err = tegra_i2c_wait_for_config_load(i2c_dev);
if (err)
goto err;
}
msleep(1);
}
}
if (i2c_dev->irq_disabled) {
i2c_dev->irq_disabled = 0;
i2c_dev->irq_disabled = false;
enable_irq(i2c_dev->irq);
}
err:
tegra_i2c_clock_disable(i2c_dev);
pm_runtime_put(i2c_dev->dev);
return err;
}
static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
{
u32 cnfg;
cnfg = i2c_readl(i2c_dev, I2C_CNFG);
if (cnfg & I2C_CNFG_PACKET_MODE_EN)
i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG);
return tegra_i2c_wait_for_config_load(i2c_dev);
}
static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
{
u32 status;
const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
struct tegra_i2c_dev *i2c_dev = dev_id;
unsigned long flags;
status = i2c_readl(i2c_dev, I2C_INT_STATUS);
spin_lock_irqsave(&i2c_dev->xfer_lock, flags);
if (status == 0) {
dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n",
i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
@ -517,12 +573,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
if (!i2c_dev->irq_disabled) {
disable_irq_nosync(i2c_dev->irq);
i2c_dev->irq_disabled = 1;
i2c_dev->irq_disabled = true;
}
goto err;
}
if (unlikely(status & status_err)) {
tegra_i2c_disable_packet_mode(i2c_dev);
if (status & I2C_INT_NO_ACK)
i2c_dev->msg_err |= I2C_ERR_NO_ACK;
if (status & I2C_INT_ARBITRATION_LOST)
@ -552,7 +609,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
BUG_ON(i2c_dev->msg_buf_remaining);
complete(&i2c_dev->msg_complete);
}
return IRQ_HANDLED;
goto done;
err:
/* An error occurred, mask all interrupts */
tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST |
@ -563,6 +620,8 @@ err:
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
complete(&i2c_dev->msg_complete);
done:
spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags);
return IRQ_HANDLED;
}
@ -572,6 +631,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
u32 packet_header;
u32 int_mask;
unsigned long time_left;
unsigned long flags;
tegra_i2c_flush_fifos(i2c_dev);
@ -584,6 +644,11 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
i2c_dev->msg_read = (msg->flags & I2C_M_RD);
reinit_completion(&i2c_dev->msg_complete);
spin_lock_irqsave(&i2c_dev->xfer_lock, flags);
int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
tegra_i2c_unmask_irq(i2c_dev, int_mask);
packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) |
PACKET_HEADER0_PROTOCOL_I2C |
(i2c_dev->cont_id << PACKET_HEADER0_CONT_ID_SHIFT) |
@ -613,14 +678,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
if (!(msg->flags & I2C_M_RD))
tegra_i2c_fill_tx_fifo(i2c_dev);
int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
if (i2c_dev->hw->has_per_pkt_xfer_complete_irq)
int_mask |= I2C_INT_PACKET_XFER_COMPLETE;
if (msg->flags & I2C_M_RD)
int_mask |= I2C_INT_RX_FIFO_DATA_REQ;
else if (i2c_dev->msg_buf_remaining)
int_mask |= I2C_INT_TX_FIFO_DATA_REQ;
tegra_i2c_unmask_irq(i2c_dev, int_mask);
spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags);
dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",
i2c_readl(i2c_dev, I2C_INT_MASK));
@ -643,9 +709,10 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
return 0;
/*
* NACK interrupt is generated before the I2C controller generates the
* STOP condition on the bus. So wait for 2 clock periods before resetting
* the controller so that STOP condition has been delivered properly.
* NACK interrupt is generated before the I2C controller generates
* the STOP condition on the bus. So wait for 2 clock periods
* before resetting the controller so that the STOP condition has
* been delivered properly.
*/
if (i2c_dev->msg_err == I2C_ERR_NO_ACK)
udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate));
@ -670,14 +737,15 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
if (i2c_dev->is_suspended)
return -EBUSY;
ret = tegra_i2c_clock_enable(i2c_dev);
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0) {
dev_err(i2c_dev->dev, "Clock enable failed %d\n", ret);
dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret);
return ret;
}
for (i = 0; i < num; i++) {
enum msg_end_type end_type = MSG_END_STOP;
if (i < (num - 1)) {
if (msgs[i + 1].flags & I2C_M_NOSTART)
end_type = MSG_END_CONTINUE;
@ -688,7 +756,9 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
if (ret)
break;
}
tegra_i2c_clock_disable(i2c_dev);
pm_runtime_put(i2c_dev->dev);
return ret ?: i;
}
@ -825,7 +895,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
div_clk = devm_clk_get(&pdev->dev, "div-clk");
if (IS_ERR(div_clk)) {
dev_err(&pdev->dev, "missing controller clock");
dev_err(&pdev->dev, "missing controller clock\n");
return PTR_ERR(div_clk);
}
@ -843,27 +913,22 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->rst = devm_reset_control_get(&pdev->dev, "i2c");
if (IS_ERR(i2c_dev->rst)) {
dev_err(&pdev->dev, "missing controller reset");
dev_err(&pdev->dev, "missing controller reset\n");
return PTR_ERR(i2c_dev->rst);
}
tegra_i2c_parse_dt(i2c_dev);
i2c_dev->hw = &tegra20_i2c_hw;
if (pdev->dev.of_node) {
i2c_dev->hw = of_device_get_match_data(&pdev->dev);
i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
"nvidia,tegra20-i2c-dvc");
} else if (pdev->id == 3) {
i2c_dev->is_dvc = 1;
}
init_completion(&i2c_dev->msg_complete);
spin_lock_init(&i2c_dev->xfer_lock);
if (!i2c_dev->hw->has_single_clk_source) {
fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
if (IS_ERR(fast_clk)) {
dev_err(&pdev->dev, "missing fast clock");
dev_err(&pdev->dev, "missing fast clock\n");
return PTR_ERR(fast_clk);
}
i2c_dev->fast_clk = fast_clk;
@ -900,18 +965,27 @@ static int tegra_i2c_probe(struct platform_device *pdev)
goto unprepare_fast_clk;
}
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = tegra_i2c_runtime_resume(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "runtime resume failed\n");
goto unprepare_div_clk;
}
}
if (i2c_dev->is_multimaster_mode) {
ret = clk_enable(i2c_dev->div_clk);
if (ret < 0) {
dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
ret);
goto unprepare_div_clk;
goto disable_rpm;
}
}
ret = tegra_i2c_init(i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize i2c controller");
dev_err(&pdev->dev, "Failed to initialize i2c controller\n");
goto disable_div_clk;
}
@ -925,17 +999,15 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
i2c_dev->adapter.owner = THIS_MODULE;
i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
strlcpy(i2c_dev->adapter.name, dev_name(&pdev->dev),
sizeof(i2c_dev->adapter.name));
i2c_dev->adapter.dev.parent = &pdev->dev;
i2c_dev->adapter.nr = pdev->id;
i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (ret) {
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
if (ret)
goto disable_div_clk;
}
return 0;
@ -943,6 +1015,11 @@ disable_div_clk:
if (i2c_dev->is_multimaster_mode)
clk_disable(i2c_dev->div_clk);
disable_rpm:
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
tegra_i2c_runtime_suspend(&pdev->dev);
unprepare_div_clk:
clk_unprepare(i2c_dev->div_clk);
@ -956,11 +1033,16 @@ unprepare_fast_clk:
static int tegra_i2c_remove(struct platform_device *pdev)
{
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c_dev->adapter);
if (i2c_dev->is_multimaster_mode)
clk_disable(i2c_dev->div_clk);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
tegra_i2c_runtime_suspend(&pdev->dev);
clk_unprepare(i2c_dev->div_clk);
if (!i2c_dev->hw->has_single_clk_source)
clk_unprepare(i2c_dev->fast_clk);
@ -988,20 +1070,19 @@ static int tegra_i2c_resume(struct device *dev)
i2c_lock_adapter(&i2c_dev->adapter);
ret = tegra_i2c_init(i2c_dev);
if (ret) {
i2c_unlock_adapter(&i2c_dev->adapter);
return ret;
}
if (!ret)
i2c_dev->is_suspended = false;
i2c_unlock_adapter(&i2c_dev->adapter);
return 0;
return ret;
}
static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume);
static const struct dev_pm_ops tegra_i2c_pm = {
SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume,
NULL)
SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
};
#define TEGRA_I2C_PM (&tegra_i2c_pm)
#else
#define TEGRA_I2C_PM NULL

View File

@ -0,0 +1,259 @@
/*
* Cavium ThunderX i2c driver.
*
* Copyright (C) 2015,2016 Cavium Inc.
* Authors: Fred Martin <fmartin@caviumnetworks.com>
* Jan Glauber <jglauber@cavium.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/pci.h>
#include "i2c-octeon-core.h"
#define DRV_NAME "i2c-thunderx"
#define PCI_DEVICE_ID_THUNDER_TWSI 0xa012
#define SYS_FREQ_DEFAULT 700000000
#define TWSI_INT_ENA_W1C 0x1028
#define TWSI_INT_ENA_W1S 0x1030
/*
* Enable the CORE interrupt.
* The interrupt will be asserted when there is non-STAT_IDLE state in the
* SW_TWSI_EOP_TWSI_STAT register.
*/
static void thunder_i2c_int_enable(struct octeon_i2c *i2c)
{
octeon_i2c_writeq_flush(TWSI_INT_CORE_INT,
i2c->twsi_base + TWSI_INT_ENA_W1S);
}
/*
* Disable the CORE interrupt.
*/
static void thunder_i2c_int_disable(struct octeon_i2c *i2c)
{
octeon_i2c_writeq_flush(TWSI_INT_CORE_INT,
i2c->twsi_base + TWSI_INT_ENA_W1C);
}
static void thunder_i2c_hlc_int_enable(struct octeon_i2c *i2c)
{
octeon_i2c_writeq_flush(TWSI_INT_ST_INT | TWSI_INT_TS_INT,
i2c->twsi_base + TWSI_INT_ENA_W1S);
}
static void thunder_i2c_hlc_int_disable(struct octeon_i2c *i2c)
{
octeon_i2c_writeq_flush(TWSI_INT_ST_INT | TWSI_INT_TS_INT,
i2c->twsi_base + TWSI_INT_ENA_W1C);
}
static u32 thunderx_i2c_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL;
}
static const struct i2c_algorithm thunderx_i2c_algo = {
.master_xfer = octeon_i2c_xfer,
.functionality = thunderx_i2c_functionality,
};
static struct i2c_adapter thunderx_i2c_ops = {
.owner = THIS_MODULE,
.name = "ThunderX adapter",
.algo = &thunderx_i2c_algo,
};
static void thunder_i2c_clock_enable(struct device *dev, struct octeon_i2c *i2c)
{
int ret;
i2c->clk = clk_get(dev, NULL);
if (IS_ERR(i2c->clk)) {
i2c->clk = NULL;
goto skip;
}
ret = clk_prepare_enable(i2c->clk);
if (ret)
goto skip;
i2c->sys_freq = clk_get_rate(i2c->clk);
skip:
if (!i2c->sys_freq)
i2c->sys_freq = SYS_FREQ_DEFAULT;
}
static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk)
{
if (!clk)
return;
clk_disable_unprepare(clk);
clk_put(clk);
}
static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
struct device_node *node)
{
u32 type;
if (!node)
return -EINVAL;
i2c->alert_data.irq = irq_of_parse_and_map(node, 0);
if (!i2c->alert_data.irq)
return -EINVAL;
type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
i2c->alert_data.alert_edge_triggered =
(type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data);
if (!i2c->ara)
return -ENODEV;
return 0;
}
static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
struct device_node *node)
{
/* TODO: ACPI support */
if (!acpi_disabled)
return -EOPNOTSUPP;
return thunder_i2c_smbus_setup_of(i2c, node);
}
static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
{
if (i2c->ara)
i2c_unregister_device(i2c->ara);
}
static int thunder_i2c_probe_pci(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
struct octeon_i2c *i2c;
int ret;
i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
i2c->roff.sw_twsi = 0x1000;
i2c->roff.twsi_int = 0x1010;
i2c->roff.sw_twsi_ext = 0x1018;
i2c->dev = dev;
pci_set_drvdata(pdev, i2c);
ret = pcim_enable_device(pdev);
if (ret)
return ret;
ret = pci_request_regions(pdev, DRV_NAME);
if (ret)
return ret;
i2c->twsi_base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
if (!i2c->twsi_base)
return -EINVAL;
thunder_i2c_clock_enable(dev, i2c);
ret = device_property_read_u32(dev, "clock-frequency", &i2c->twsi_freq);
if (ret)
i2c->twsi_freq = 100000;
init_waitqueue_head(&i2c->queue);
i2c->int_enable = thunder_i2c_int_enable;
i2c->int_disable = thunder_i2c_int_disable;
i2c->hlc_int_enable = thunder_i2c_hlc_int_enable;
i2c->hlc_int_disable = thunder_i2c_hlc_int_disable;
ret = pci_enable_msix(pdev, &i2c->i2c_msix, 1);
if (ret)
goto error;
ret = devm_request_irq(dev, i2c->i2c_msix.vector, octeon_i2c_isr, 0,
DRV_NAME, i2c);
if (ret)
goto error;
ret = octeon_i2c_init_lowlevel(i2c);
if (ret)
goto error;
octeon_i2c_set_clock(i2c);
i2c->adap = thunderx_i2c_ops;
i2c->adap.retries = 5;
i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
i2c->adap.dev.parent = dev;
i2c->adap.dev.of_node = pdev->dev.of_node;
snprintf(i2c->adap.name, sizeof(i2c->adap.name),
"Cavium ThunderX i2c adapter at %s", dev_name(dev));
i2c_set_adapdata(&i2c->adap, i2c);
ret = i2c_add_adapter(&i2c->adap);
if (ret)
goto error;
dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq);
ret = thunder_i2c_smbus_setup(i2c, pdev->dev.of_node);
if (ret)
dev_info(dev, "SMBUS alert not active on this bus\n");
return 0;
error:
thunder_i2c_clock_disable(dev, i2c->clk);
return ret;
}
static void thunder_i2c_remove_pci(struct pci_dev *pdev)
{
struct octeon_i2c *i2c = pci_get_drvdata(pdev);
thunder_i2c_smbus_remove(i2c);
thunder_i2c_clock_disable(&pdev->dev, i2c->clk);
i2c_del_adapter(&i2c->adap);
}
static const struct pci_device_id thunder_i2c_pci_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_TWSI) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, thunder_i2c_pci_id_table);
static struct pci_driver thunder_i2c_pci_driver = {
.name = DRV_NAME,
.id_table = thunder_i2c_pci_id_table,
.probe = thunder_i2c_probe_pci,
.remove = thunder_i2c_remove_pci,
};
module_pci_driver(thunder_i2c_pci_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Fred Martin <fmartin@caviumnetworks.com>");
MODULE_DESCRIPTION("I2C-Bus adapter for Cavium ThunderX SOC");

View File

@ -14,6 +14,7 @@
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/iopoll.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@ -348,14 +349,19 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap,
dev_dbg(&adap->dev, "complete\n");
if (unlikely(priv->flags & UNIPHIER_FI2C_DEFER_STOP_COMP)) {
u32 status = readl(priv->membase + UNIPHIER_FI2C_SR);
u32 status;
int ret;
if (!(status & UNIPHIER_FI2C_SR_STS) ||
status & UNIPHIER_FI2C_SR_BB) {
ret = readl_poll_timeout(priv->membase + UNIPHIER_FI2C_SR,
status,
(status & UNIPHIER_FI2C_SR_STS) &&
!(status & UNIPHIER_FI2C_SR_BB),
1, 20);
if (ret) {
dev_err(&adap->dev,
"stop condition was not completed.\n");
uniphier_fi2c_recover(priv);
return -EBUSY;
return ret;
}
}
@ -455,54 +461,25 @@ static struct i2c_bus_recovery_info uniphier_fi2c_bus_recovery_info = {
.unprepare_recovery = uniphier_fi2c_unprepare_recovery,
};
static int uniphier_fi2c_clk_init(struct device *dev,
struct uniphier_fi2c_priv *priv)
static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv,
u32 bus_speed, unsigned long clk_rate)
{
struct device_node *np = dev->of_node;
unsigned long clk_rate;
u32 bus_speed, clk_count;
int ret;
u32 tmp;
if (of_property_read_u32(np, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED;
if (!bus_speed) {
dev_err(dev, "clock-frequency should not be zero\n");
return -EINVAL;
}
if (bus_speed > UNIPHIER_FI2C_MAX_SPEED)
bus_speed = UNIPHIER_FI2C_MAX_SPEED;
/* Get input clk rate through clk driver */
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(dev, "failed to get clock\n");
return PTR_ERR(priv->clk);
}
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
return -EINVAL;
}
tmp = readl(priv->membase + UNIPHIER_FI2C_CR);
tmp |= UNIPHIER_FI2C_CR_MST;
writel(tmp, priv->membase + UNIPHIER_FI2C_CR);
uniphier_fi2c_reset(priv);
clk_count = clk_rate / bus_speed;
tmp = clk_rate / bus_speed;
writel(clk_count, priv->membase + UNIPHIER_FI2C_CYC);
writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_LCTL);
writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_SSUT);
writel(clk_count / 16, priv->membase + UNIPHIER_FI2C_DSUT);
writel(tmp, priv->membase + UNIPHIER_FI2C_CYC);
writel(tmp / 2, priv->membase + UNIPHIER_FI2C_LCTL);
writel(tmp / 2, priv->membase + UNIPHIER_FI2C_SSUT);
writel(tmp / 16, priv->membase + UNIPHIER_FI2C_DSUT);
uniphier_fi2c_prepare_operation(priv);
return 0;
}
static int uniphier_fi2c_probe(struct platform_device *pdev)
@ -510,8 +487,9 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct uniphier_fi2c_priv *priv;
struct resource *regs;
int irq;
int ret;
u32 bus_speed;
unsigned long clk_rate;
int irq, ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@ -528,6 +506,31 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
return irq;
}
if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED;
if (!bus_speed || bus_speed > UNIPHIER_FI2C_MAX_SPEED) {
dev_err(dev, "invalid clock-frequency %d\n", bus_speed);
return -EINVAL;
}
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(dev, "failed to get clock\n");
return PTR_ERR(priv->clk);
}
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
ret = -EINVAL;
goto err;
}
init_completion(&priv->comp);
priv->adap.owner = THIS_MODULE;
priv->adap.algo = &uniphier_fi2c_algo;
@ -538,9 +541,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&priv->adap, priv);
platform_set_drvdata(pdev, priv);
ret = uniphier_fi2c_clk_init(dev, priv);
if (ret)
goto err;
uniphier_fi2c_hw_init(priv, bus_speed, clk_rate);
ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0,
pdev->name, priv);
@ -550,11 +551,6 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
}
ret = i2c_add_adapter(&priv->adap);
if (ret) {
dev_err(dev, "failed to add I2C adapter\n");
goto err;
}
err:
if (ret)
clk_disable_unprepare(priv->clk);

View File

@ -316,50 +316,15 @@ static struct i2c_bus_recovery_info uniphier_i2c_bus_recovery_info = {
.unprepare_recovery = uniphier_i2c_unprepare_recovery,
};
static int uniphier_i2c_clk_init(struct device *dev,
struct uniphier_i2c_priv *priv)
static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv,
u32 bus_speed, unsigned long clk_rate)
{
struct device_node *np = dev->of_node;
unsigned long clk_rate;
u32 bus_speed;
int ret;
if (of_property_read_u32(np, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_I2C_DEFAULT_SPEED;
if (!bus_speed) {
dev_err(dev, "clock-frequency should not be zero\n");
return -EINVAL;
}
if (bus_speed > UNIPHIER_I2C_MAX_SPEED)
bus_speed = UNIPHIER_I2C_MAX_SPEED;
/* Get input clk rate through clk driver */
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(dev, "failed to get clock\n");
return PTR_ERR(priv->clk);
}
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
return -EINVAL;
}
uniphier_i2c_reset(priv, true);
writel((clk_rate / bus_speed / 2 << 16) | (clk_rate / bus_speed),
priv->membase + UNIPHIER_I2C_CLK);
uniphier_i2c_reset(priv, false);
return 0;
}
static int uniphier_i2c_probe(struct platform_device *pdev)
@ -367,8 +332,9 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct uniphier_i2c_priv *priv;
struct resource *regs;
int irq;
int ret;
u32 bus_speed;
unsigned long clk_rate;
int irq, ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@ -385,6 +351,31 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
return irq;
}
if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_I2C_DEFAULT_SPEED;
if (!bus_speed || bus_speed > UNIPHIER_I2C_MAX_SPEED) {
dev_err(dev, "invalid clock-frequency %d\n", bus_speed);
return -EINVAL;
}
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(dev, "failed to get clock\n");
return PTR_ERR(priv->clk);
}
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
ret = -EINVAL;
goto err;
}
init_completion(&priv->comp);
priv->adap.owner = THIS_MODULE;
priv->adap.algo = &uniphier_i2c_algo;
@ -395,9 +386,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&priv->adap, priv);
platform_set_drvdata(pdev, priv);
ret = uniphier_i2c_clk_init(dev, priv);
if (ret)
goto err;
uniphier_i2c_hw_init(priv, bus_speed, clk_rate);
ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name,
priv);
@ -407,11 +396,6 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
}
ret = i2c_add_adapter(&priv->adap);
if (ret) {
dev_err(dev, "failed to add I2C adapter\n");
goto err;
}
err:
if (ret)
clk_disable_unprepare(priv->clk);

View File

@ -432,10 +432,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
}
err = i2c_add_adapter(adap);
if (err) {
dev_err(&pdev->dev, "failed to add adapter\n");
if (err)
return err;
}
platform_set_drvdata(pdev, i2c_dev);

View File

@ -418,7 +418,6 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adapter, ctx);
rc = i2c_add_adapter(adapter);
if (rc) {
dev_err(&pdev->dev, "Adapter registeration failed\n");
mbox_free_channel(ctx->mbox_chan);
return rc;
}

View File

@ -804,7 +804,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
/* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap);
if (ret) {
dev_err(&pdev->dev, "Failed to add adapter\n");
xiic_deinit(i2c);
goto err_clk_dis;
}

View File

@ -400,10 +400,8 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&priv->adapter, priv);
err = i2c_add_adapter(&priv->adapter);
if (err) {
dev_err(&pdev->dev, "failed to add I2C adapter!\n");
if (err)
return err;
}
platform_set_drvdata(pdev, priv);
dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);

View File

@ -432,10 +432,8 @@ static int xlr_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&priv->adap, priv);
ret = i2c_add_numbered_adapter(&priv->adap);
if (ret < 0) {
dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
if (ret < 0)
return ret;
}
platform_set_drvdata(pdev, priv);
dev_info(&priv->adap.dev, "Added I2C Bus.\n");

View File

@ -88,7 +88,7 @@ void i2c_transfer_trace_unreg(void)
}
#if defined(CONFIG_ACPI)
struct acpi_i2c_handler_data {
struct i2c_acpi_handler_data {
struct acpi_connection_info info;
struct i2c_adapter *adapter;
};
@ -103,15 +103,18 @@ struct gsb_buffer {
};
} __packed;
struct acpi_i2c_lookup {
struct i2c_acpi_lookup {
struct i2c_board_info *info;
acpi_handle adapter_handle;
acpi_handle device_handle;
acpi_handle search_handle;
u32 speed;
u32 min_speed;
};
static int acpi_i2c_fill_info(struct acpi_resource *ares, void *data)
static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
{
struct acpi_i2c_lookup *lookup = data;
struct i2c_acpi_lookup *lookup = data;
struct i2c_board_info *info = lookup->info;
struct acpi_resource_i2c_serialbus *sb;
acpi_status status;
@ -130,19 +133,18 @@ static int acpi_i2c_fill_info(struct acpi_resource *ares, void *data)
return 1;
info->addr = sb->slave_address;
lookup->speed = sb->connection_speed;
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
info->flags |= I2C_CLIENT_TEN;
return 1;
}
static int acpi_i2c_get_info(struct acpi_device *adev,
struct i2c_board_info *info,
acpi_handle *adapter_handle)
static int i2c_acpi_do_lookup(struct acpi_device *adev,
struct i2c_acpi_lookup *lookup)
{
struct i2c_board_info *info = lookup->info;
struct list_head resource_list;
struct resource_entry *entry;
struct acpi_i2c_lookup lookup;
int ret;
if (acpi_bus_get_status(adev) || !adev->status.present ||
@ -150,24 +152,58 @@ static int acpi_i2c_get_info(struct acpi_device *adev,
return -EINVAL;
memset(info, 0, sizeof(*info));
info->fwnode = acpi_fwnode_handle(adev);
memset(&lookup, 0, sizeof(lookup));
lookup.device_handle = acpi_device_handle(adev);
lookup.info = info;
lookup->device_handle = acpi_device_handle(adev);
/* Look up for I2cSerialBus resource */
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list,
acpi_i2c_fill_info, &lookup);
i2c_acpi_fill_info, lookup);
acpi_dev_free_resource_list(&resource_list);
if (ret < 0 || !info->addr)
return -EINVAL;
return 0;
}
static int i2c_acpi_get_info(struct acpi_device *adev,
struct i2c_board_info *info,
struct i2c_adapter *adapter,
acpi_handle *adapter_handle)
{
struct list_head resource_list;
struct resource_entry *entry;
struct i2c_acpi_lookup lookup;
int ret;
memset(&lookup, 0, sizeof(lookup));
lookup.info = info;
ret = i2c_acpi_do_lookup(adev, &lookup);
if (ret)
return ret;
if (adapter) {
/* The adapter must match the one in I2cSerialBus() connector */
if (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle)
return -ENODEV;
} else {
struct acpi_device *adapter_adev;
/* The adapter must be present */
if (acpi_bus_get_device(lookup.adapter_handle, &adapter_adev))
return -ENODEV;
if (acpi_bus_get_status(adapter_adev) ||
!adapter_adev->status.present)
return -ENODEV;
}
info->fwnode = acpi_fwnode_handle(adev);
if (adapter_handle)
*adapter_handle = lookup.adapter_handle;
/* Then fill IRQ number if any */
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (ret < 0)
return -EINVAL;
@ -186,7 +222,7 @@ static int acpi_i2c_get_info(struct acpi_device *adev,
return 0;
}
static void acpi_i2c_register_device(struct i2c_adapter *adapter,
static void i2c_acpi_register_device(struct i2c_adapter *adapter,
struct acpi_device *adev,
struct i2c_board_info *info)
{
@ -201,39 +237,35 @@ static void acpi_i2c_register_device(struct i2c_adapter *adapter,
}
}
static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
void *data, void **return_value)
{
struct i2c_adapter *adapter = data;
struct acpi_device *adev;
acpi_handle adapter_handle;
struct i2c_board_info info;
if (acpi_bus_get_device(handle, &adev))
return AE_OK;
if (acpi_i2c_get_info(adev, &info, &adapter_handle))
if (i2c_acpi_get_info(adev, &info, adapter, NULL))
return AE_OK;
if (adapter_handle != ACPI_HANDLE(&adapter->dev))
return AE_OK;
acpi_i2c_register_device(adapter, adev, &info);
i2c_acpi_register_device(adapter, adev, &info);
return AE_OK;
}
#define ACPI_I2C_MAX_SCAN_DEPTH 32
#define I2C_ACPI_MAX_SCAN_DEPTH 32
/**
* acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
* i2c_acpi_register_devices - enumerate I2C slave devices behind adapter
* @adap: pointer to adapter
*
* Enumerate all I2C slave devices behind this adapter by walking the ACPI
* namespace. When a device is found it will be added to the Linux device
* model and bound to the corresponding ACPI handle.
*/
static void acpi_i2c_register_devices(struct i2c_adapter *adap)
static void i2c_acpi_register_devices(struct i2c_adapter *adap)
{
acpi_status status;
@ -241,14 +273,72 @@ static void acpi_i2c_register_devices(struct i2c_adapter *adap)
return;
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_I2C_MAX_SCAN_DEPTH,
acpi_i2c_add_device, NULL,
I2C_ACPI_MAX_SCAN_DEPTH,
i2c_acpi_add_device, NULL,
adap, NULL);
if (ACPI_FAILURE(status))
dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
}
static int acpi_i2c_match_adapter(struct device *dev, void *data)
static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level,
void *data, void **return_value)
{
struct i2c_acpi_lookup *lookup = data;
struct acpi_device *adev;
if (acpi_bus_get_device(handle, &adev))
return AE_OK;
if (i2c_acpi_do_lookup(adev, lookup))
return AE_OK;
if (lookup->search_handle != lookup->adapter_handle)
return AE_OK;
if (lookup->speed <= lookup->min_speed)
lookup->min_speed = lookup->speed;
return AE_OK;
}
/**
* i2c_acpi_find_bus_speed - find I2C bus speed from ACPI
* @dev: The device owning the bus
*
* Find the I2C bus speed by walking the ACPI namespace for all I2C slaves
* devices connected to this bus and use the speed of slowest device.
*
* Returns the speed in Hz or zero
*/
u32 i2c_acpi_find_bus_speed(struct device *dev)
{
struct i2c_acpi_lookup lookup;
struct i2c_board_info dummy;
acpi_status status;
if (!has_acpi_companion(dev))
return 0;
memset(&lookup, 0, sizeof(lookup));
lookup.search_handle = ACPI_HANDLE(dev);
lookup.min_speed = UINT_MAX;
lookup.info = &dummy;
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
I2C_ACPI_MAX_SCAN_DEPTH,
i2c_acpi_lookup_speed, NULL,
&lookup, NULL);
if (ACPI_FAILURE(status)) {
dev_warn(dev, "unable to find I2C bus speed from ACPI\n");
return 0;
}
return lookup.min_speed != UINT_MAX ? lookup.min_speed : 0;
}
EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
static int i2c_acpi_match_adapter(struct device *dev, void *data)
{
struct i2c_adapter *adapter = i2c_verify_adapter(dev);
@ -258,29 +348,29 @@ static int acpi_i2c_match_adapter(struct device *dev, void *data)
return ACPI_HANDLE(dev) == (acpi_handle)data;
}
static int acpi_i2c_match_device(struct device *dev, void *data)
static int i2c_acpi_match_device(struct device *dev, void *data)
{
return ACPI_COMPANION(dev) == data;
}
static struct i2c_adapter *acpi_i2c_find_adapter_by_handle(acpi_handle handle)
static struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)
{
struct device *dev;
dev = bus_find_device(&i2c_bus_type, NULL, handle,
acpi_i2c_match_adapter);
i2c_acpi_match_adapter);
return dev ? i2c_verify_adapter(dev) : NULL;
}
static struct i2c_client *acpi_i2c_find_client_by_adev(struct acpi_device *adev)
static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)
{
struct device *dev;
dev = bus_find_device(&i2c_bus_type, NULL, adev, acpi_i2c_match_device);
dev = bus_find_device(&i2c_bus_type, NULL, adev, i2c_acpi_match_device);
return dev ? i2c_verify_client(dev) : NULL;
}
static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value,
static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
void *arg)
{
struct acpi_device *adev = arg;
@ -291,20 +381,20 @@ static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value,
switch (value) {
case ACPI_RECONFIG_DEVICE_ADD:
if (acpi_i2c_get_info(adev, &info, &adapter_handle))
if (i2c_acpi_get_info(adev, &info, NULL, &adapter_handle))
break;
adapter = acpi_i2c_find_adapter_by_handle(adapter_handle);
adapter = i2c_acpi_find_adapter_by_handle(adapter_handle);
if (!adapter)
break;
acpi_i2c_register_device(adapter, adev, &info);
i2c_acpi_register_device(adapter, adev, &info);
break;
case ACPI_RECONFIG_DEVICE_REMOVE:
if (!acpi_device_enumerated(adev))
break;
client = acpi_i2c_find_client_by_adev(adev);
client = i2c_acpi_find_client_by_adev(adev);
if (!client)
break;
@ -317,10 +407,10 @@ static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value,
}
static struct notifier_block i2c_acpi_notifier = {
.notifier_call = acpi_i2c_notify,
.notifier_call = i2c_acpi_notify,
};
#else /* CONFIG_ACPI */
static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { }
static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
extern struct notifier_block i2c_acpi_notifier;
#endif /* CONFIG_ACPI */
@ -386,12 +476,12 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
}
static acpi_status
acpi_i2c_space_handler(u32 function, acpi_physical_address command,
i2c_acpi_space_handler(u32 function, acpi_physical_address command,
u32 bits, u64 *value64,
void *handler_context, void *region_context)
{
struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
struct acpi_i2c_handler_data *data = handler_context;
struct i2c_acpi_handler_data *data = handler_context;
struct acpi_connection_info *info = &data->info;
struct acpi_resource_i2c_serialbus *sb;
struct i2c_adapter *adapter = data->adapter;
@ -510,10 +600,10 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command,
}
static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
static int i2c_acpi_install_space_handler(struct i2c_adapter *adapter)
{
acpi_handle handle;
struct acpi_i2c_handler_data *data;
struct i2c_acpi_handler_data *data;
acpi_status status;
if (!adapter->dev.parent)
@ -524,7 +614,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
if (!handle)
return -ENODEV;
data = kzalloc(sizeof(struct acpi_i2c_handler_data),
data = kzalloc(sizeof(struct i2c_acpi_handler_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -538,7 +628,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
status = acpi_install_address_space_handler(handle,
ACPI_ADR_SPACE_GSBUS,
&acpi_i2c_space_handler,
&i2c_acpi_space_handler,
NULL,
data);
if (ACPI_FAILURE(status)) {
@ -552,10 +642,10 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
return 0;
}
static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
static void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter)
{
acpi_handle handle;
struct acpi_i2c_handler_data *data;
struct i2c_acpi_handler_data *data;
acpi_status status;
if (!adapter->dev.parent)
@ -568,7 +658,7 @@ static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
acpi_remove_address_space_handler(handle,
ACPI_ADR_SPACE_GSBUS,
&acpi_i2c_space_handler);
&i2c_acpi_space_handler);
status = acpi_bus_get_private_data(handle, (void **)&data);
if (ACPI_SUCCESS(status))
@ -577,10 +667,10 @@ static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
acpi_bus_detach_private_data(handle);
}
#else /* CONFIG_ACPI_I2C_OPREGION */
static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter)
{ }
static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter)
{ return 0; }
#endif /* CONFIG_ACPI_I2C_OPREGION */
@ -853,7 +943,7 @@ static int i2c_device_probe(struct device *dev)
status = 0;
if (status)
dev_warn(&client->dev, "failed to set up wakeup irq");
dev_warn(&client->dev, "failed to set up wakeup irq\n");
}
dev_dbg(dev, "probe\n");
@ -1208,8 +1298,9 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
return client;
out_err:
dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
"(%d)\n", client->name, client->addr, status);
dev_err(&adap->dev,
"Failed to register i2c client %s at 0x%02x (%d)\n",
client->name, client->addr, status);
out_err_silent:
kfree(client);
return NULL;
@ -1335,21 +1426,19 @@ static void i2c_adapter_dev_release(struct device *dev)
complete(&adap->dev_released);
}
/*
* This function is only needed for mutex_lock_nested, so it is never
* called unless locking correctness checking is enabled. Thus we
* make it inline to avoid a compiler warning. That's what gcc ends up
* doing anyway.
*/
static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
{
unsigned int depth = 0;
while ((adapter = i2c_parent_is_i2c_adapter(adapter)))
depth++;
WARN_ONCE(depth >= MAX_LOCKDEP_SUBCLASSES,
"adapter depth exceeds lockdep subclass limit\n");
return depth;
}
EXPORT_SYMBOL_GPL(i2c_adapter_depth);
/*
* Let users instantiate I2C devices through sysfs. This can be used when
@ -1678,8 +1767,8 @@ static int i2c_do_add_adapter(struct i2c_driver *driver,
if (driver->attach_adapter) {
dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",
driver->driver.name);
dev_warn(&adap->dev, "Please use another way to instantiate "
"your i2c_client\n");
dev_warn(&adap->dev,
"Please use another way to instantiate your i2c_client\n");
/* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap);
}
@ -1691,6 +1780,12 @@ static int __process_new_adapter(struct device_driver *d, void *data)
return i2c_do_add_adapter(to_i2c_driver(d), data);
}
static const struct i2c_lock_operations i2c_adapter_lock_ops = {
.lock_bus = i2c_adapter_lock_bus,
.trylock_bus = i2c_adapter_trylock_bus,
.unlock_bus = i2c_adapter_unlock_bus,
};
static int i2c_register_adapter(struct i2c_adapter *adap)
{
int res = -EINVAL;
@ -1710,11 +1805,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
goto out_list;
}
if (!adap->lock_bus) {
adap->lock_bus = i2c_adapter_lock_bus;
adap->trylock_bus = i2c_adapter_trylock_bus;
adap->unlock_bus = i2c_adapter_unlock_bus;
}
if (!adap->lock_ops)
adap->lock_ops = &i2c_adapter_lock_ops;
rt_mutex_init(&adap->bus_lock);
rt_mutex_init(&adap->mux_lock);
@ -1752,8 +1844,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
/* create pre-declared device nodes */
of_i2c_register_devices(adap);
acpi_i2c_register_devices(adap);
acpi_i2c_install_space_handler(adap);
i2c_acpi_register_devices(adap);
i2c_acpi_install_space_handler(adap);
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
@ -1925,7 +2017,7 @@ void i2c_del_adapter(struct i2c_adapter *adap)
return;
}
acpi_i2c_remove_space_handler(adap);
i2c_acpi_remove_space_handler(adap);
/* Tell drivers about this removal */
mutex_lock(&core_lock);
bus_for_each_drv(&i2c_bus_type, NULL, adap,
@ -2451,15 +2543,16 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (adap->algo->master_xfer) {
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
dev_dbg(&adap->dev,
"master_xfer[%d] %c, addr=0x%02x, len=%d%s\n",
ret, (msgs[ret].flags & I2C_M_RD) ? 'R' : 'W',
msgs[ret].addr, msgs[ret].len,
(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
}
#endif
if (in_atomic() || irqs_disabled()) {
ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT);
ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
@ -2619,9 +2712,9 @@ static int i2c_detect_address(struct i2c_client *temp_client,
/* Consistency check */
if (info.type[0] == '\0') {
dev_err(&adapter->dev, "%s detection function provided "
"no name for 0x%x\n", driver->driver.name,
addr);
dev_err(&adapter->dev,
"%s detection function provided no name for 0x%x\n",
driver->driver.name, addr);
} else {
struct i2c_client *client;
@ -2659,9 +2752,8 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
/* Warn that the adapter lost class based instantiation */
if (adapter->class == I2C_CLASS_DEPRECATED) {
dev_dbg(&adapter->dev,
"This adapter dropped support for I2C classes and "
"won't auto-detect %s devices anymore. If you need it, check "
"'Documentation/i2c/instantiating-devices' for alternatives.\n",
"This adapter dropped support for I2C classes and won't auto-detect %s devices anymore. "
"If you need it, check 'Documentation/i2c/instantiating-devices' for alternatives.\n",
driver->driver.name);
return 0;
}
@ -2677,8 +2769,9 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
temp_client->adapter = adapter;
for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
"addr 0x%02x\n", adap_id, address_list[i]);
dev_dbg(&adapter->dev,
"found normal entry for adapter %d, addr 0x%02x\n",
adap_id, address_list[i]);
temp_client->addr = address_list[i];
err = i2c_detect_address(temp_client, driver);
if (unlikely(err))
@ -2710,15 +2803,16 @@ i2c_new_probed_device(struct i2c_adapter *adap,
for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
/* Check address validity */
if (i2c_check_7bit_addr_validity_strict(addr_list[i]) < 0) {
dev_warn(&adap->dev, "Invalid 7-bit address "
"0x%02x\n", addr_list[i]);
dev_warn(&adap->dev, "Invalid 7-bit address 0x%02x\n",
addr_list[i]);
continue;
}
/* Check address availability (7 bit, no need to encode flags) */
if (i2c_check_addr_busy(adap, addr_list[i])) {
dev_dbg(&adap->dev, "Address 0x%02x already in "
"use, not probing\n", addr_list[i]);
dev_dbg(&adap->dev,
"Address 0x%02x already in use, not probing\n",
addr_list[i]);
continue;
}

View File

@ -159,7 +159,7 @@ static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
return 0; /* mux_lock not locked, failure */
if (!(flags & I2C_LOCK_ROOT_ADAPTER))
return 1; /* we only want mux_lock, success */
if (parent->trylock_bus(parent, flags))
if (i2c_trylock_bus(parent, flags))
return 1; /* parent locked too, success */
rt_mutex_unlock(&parent->mux_lock);
return 0; /* parent not locked, failure */
@ -193,7 +193,7 @@ static int i2c_parent_trylock_bus(struct i2c_adapter *adapter,
if (!rt_mutex_trylock(&parent->mux_lock))
return 0; /* mux_lock not locked, failure */
if (parent->trylock_bus(parent, flags))
if (i2c_trylock_bus(parent, flags))
return 1; /* parent locked too, success */
rt_mutex_unlock(&parent->mux_lock);
return 0; /* parent not locked, failure */
@ -255,6 +255,10 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
muxc->dev = dev;
if (flags & I2C_MUX_LOCKED)
muxc->mux_locked = true;
if (flags & I2C_MUX_ARBITRATOR)
muxc->arbitrator = true;
if (flags & I2C_MUX_GATE)
muxc->gate = true;
muxc->select = select;
muxc->deselect = deselect;
muxc->max_adapters = max_adapters;
@ -263,6 +267,18 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
}
EXPORT_SYMBOL_GPL(i2c_mux_alloc);
static const struct i2c_lock_operations i2c_mux_lock_ops = {
.lock_bus = i2c_mux_lock_bus,
.trylock_bus = i2c_mux_trylock_bus,
.unlock_bus = i2c_mux_unlock_bus,
};
static const struct i2c_lock_operations i2c_parent_lock_ops = {
.lock_bus = i2c_parent_lock_bus,
.trylock_bus = i2c_parent_trylock_bus,
.unlock_bus = i2c_parent_unlock_bus,
};
int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
u32 force_nr, u32 chan_id,
unsigned int class)
@ -312,15 +328,10 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
priv->adap.retries = parent->retries;
priv->adap.timeout = parent->timeout;
priv->adap.quirks = parent->quirks;
if (muxc->mux_locked) {
priv->adap.lock_bus = i2c_mux_lock_bus;
priv->adap.trylock_bus = i2c_mux_trylock_bus;
priv->adap.unlock_bus = i2c_mux_unlock_bus;
} else {
priv->adap.lock_bus = i2c_parent_lock_bus;
priv->adap.trylock_bus = i2c_parent_trylock_bus;
priv->adap.unlock_bus = i2c_parent_unlock_bus;
}
if (muxc->mux_locked)
priv->adap.lock_ops = &i2c_mux_lock_ops;
else
priv->adap.lock_ops = &i2c_parent_lock_ops;
/* Sanity check on class */
if (i2c_mux_parent_classes(parent) & class)
@ -335,18 +346,42 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
* nothing if !CONFIG_OF.
*/
if (muxc->dev->of_node) {
struct device_node *child;
struct device_node *dev_node = muxc->dev->of_node;
struct device_node *mux_node, *child = NULL;
u32 reg;
for_each_child_of_node(muxc->dev->of_node, child) {
if (muxc->arbitrator)
mux_node = of_get_child_by_name(dev_node, "i2c-arb");
else if (muxc->gate)
mux_node = of_get_child_by_name(dev_node, "i2c-gate");
else
mux_node = of_get_child_by_name(dev_node, "i2c-mux");
if (mux_node) {
/* A "reg" property indicates an old-style DT entry */
if (!of_property_read_u32(mux_node, "reg", &reg)) {
of_node_put(mux_node);
mux_node = NULL;
}
}
if (!mux_node)
mux_node = of_node_get(dev_node);
else if (muxc->arbitrator || muxc->gate)
child = of_node_get(mux_node);
if (!child) {
for_each_child_of_node(mux_node, child) {
ret = of_property_read_u32(child, "reg", &reg);
if (ret)
continue;
if (chan_id == reg) {
priv->adap.dev.of_node = child;
if (chan_id == reg)
break;
}
}
priv->adap.dev.of_node = child;
of_node_put(mux_node);
}
/*

View File

@ -130,7 +130,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
return -EINVAL;
}
muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), 0,
muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), I2C_MUX_ARBITRATOR,
i2c_arbitrator_select, i2c_arbitrator_deselect);
if (!muxc)
return -ENOMEM;

View File

@ -85,6 +85,13 @@ static const struct i2c_device_id pca9541_id[] = {
MODULE_DEVICE_TABLE(i2c, pca9541_id);
#ifdef CONFIG_OF
static const struct of_device_id pca9541_of_match[] = {
{ .compatible = "nxp,pca9541" },
{}
};
#endif
/*
* Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
* as they will try to lock the adapter a second time.
@ -349,7 +356,8 @@ static int pca9541_probe(struct i2c_client *client,
force = 0;
if (pdata)
force = pdata->modes[0].adap_id;
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0,
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
I2C_MUX_ARBITRATOR,
pca9541_select_chan, pca9541_release_chan);
if (!muxc)
return -ENOMEM;
@ -382,6 +390,7 @@ static int pca9541_remove(struct i2c_client *client)
static struct i2c_driver pca9541_driver = {
.driver = {
.name = "pca9541",
.of_match_table = of_match_ptr(pca9541_of_match),
},
.probe = pca9541_probe,
.remove = pca9541_remove,

View File

@ -42,6 +42,7 @@
#include <linux/i2c/pca954x.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
@ -58,14 +59,6 @@ enum pca_type {
pca_9548,
};
struct pca954x {
enum pca_type type;
u8 last_chan; /* last register value */
u8 deselect;
struct i2c_client *client;
};
struct chip_desc {
u8 nchans;
u8 enable; /* used for muxes only */
@ -75,6 +68,14 @@ struct chip_desc {
} muxtype;
};
struct pca954x {
const struct chip_desc *chip;
u8 last_chan; /* last register value */
u8 deselect;
struct i2c_client *client;
};
/* Provide specs for the PCA954x types we know about */
static const struct chip_desc chips[] = {
[pca_9540] = {
@ -119,6 +120,20 @@ static const struct i2c_device_id pca954x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca954x_id);
#ifdef CONFIG_OF
static const struct of_device_id pca954x_of_match[] = {
{ .compatible = "nxp,pca9540", .data = &chips[pca_9540] },
{ .compatible = "nxp,pca9542", .data = &chips[pca_9542] },
{ .compatible = "nxp,pca9543", .data = &chips[pca_9543] },
{ .compatible = "nxp,pca9544", .data = &chips[pca_9544] },
{ .compatible = "nxp,pca9545", .data = &chips[pca_9545] },
{ .compatible = "nxp,pca9546", .data = &chips[pca_9546] },
{ .compatible = "nxp,pca9547", .data = &chips[pca_9547] },
{ .compatible = "nxp,pca9548", .data = &chips[pca_9548] },
{}
};
#endif
/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
for this as they will try to lock adapter a second time */
static int pca954x_reg_write(struct i2c_adapter *adap,
@ -151,7 +166,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
{
struct pca954x *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client;
const struct chip_desc *chip = &chips[data->type];
const struct chip_desc *chip = data->chip;
u8 regval;
int ret = 0;
@ -197,6 +212,7 @@ static int pca954x_probe(struct i2c_client *client,
int num, force, class;
struct i2c_mux_core *muxc;
struct pca954x *data;
const struct of_device_id *match;
int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
@ -226,14 +242,19 @@ static int pca954x_probe(struct i2c_client *client,
return -ENODEV;
}
data->type = id->driver_data;
match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
if (match)
data->chip = of_device_get_match_data(&client->dev);
else
data->chip = &chips[id->driver_data];
data->last_chan = 0; /* force the first selection */
idle_disconnect_dt = of_node &&
of_property_read_bool(of_node, "i2c-mux-idle-disconnect");
/* Now create an adapter for each channel */
for (num = 0; num < chips[data->type].nchans; num++) {
for (num = 0; num < data->chip->nchans; num++) {
bool idle_disconnect_pd = false;
force = 0; /* dynamic adap number */
@ -263,7 +284,7 @@ static int pca954x_probe(struct i2c_client *client,
dev_info(&client->dev,
"registered %d multiplexed busses for I2C %s %s\n",
num, chips[data->type].muxtype == pca954x_ismux
num, data->chip->muxtype == pca954x_ismux
? "mux" : "switch", client->name);
return 0;
@ -299,6 +320,7 @@ static struct i2c_driver pca954x_driver = {
.driver = {
.name = "pca954x",
.pm = &pca954x_pm,
.of_match_table = of_match_ptr(pca954x_of_match),
},
.probe = pca954x_probe,
.remove = pca954x_remove,

View File

@ -593,6 +593,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct at24_data *at24;
int err;
unsigned i, num_addresses;
u8 test_byte;
if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data;
@ -743,6 +744,18 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
}
i2c_set_clientdata(client, at24);
/*
* Perform a one-byte test read to verify that the
* chip is functional.
*/
err = at24_read(at24, 0, &test_byte, 1);
if (err) {
err = -ENODEV;
goto err_clients;
}
at24->nvmem_config.name = dev_name(&client->dev);
at24->nvmem_config.dev = &client->dev;
at24->nvmem_config.read_only = !writable;
@ -764,8 +777,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto err_clients;
}
i2c_set_clientdata(client, at24);
dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
chip.byte_len, client->name,
writable ? "writable" : "read-only", at24->write_max);

View File

@ -32,7 +32,9 @@
struct i2c_mux_core {
struct i2c_adapter *parent;
struct device *dev;
bool mux_locked;
unsigned int mux_locked:1;
unsigned int arbitrator:1;
unsigned int gate:1;
void *priv;
@ -52,6 +54,8 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
/* flags for i2c_mux_alloc */
#define I2C_MUX_LOCKED BIT(0)
#define I2C_MUX_ARBITRATOR BIT(1)
#define I2C_MUX_GATE BIT(2)
static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
{

View File

@ -426,6 +426,20 @@ struct i2c_algorithm {
#endif
};
/**
* struct i2c_lock_operations - represent I2C locking operations
* @lock_bus: Get exclusive access to an I2C bus segment
* @trylock_bus: Try to get exclusive access to an I2C bus segment
* @unlock_bus: Release exclusive access to an I2C bus segment
*
* The main operations are wrapped by i2c_lock_bus and i2c_unlock_bus.
*/
struct i2c_lock_operations {
void (*lock_bus)(struct i2c_adapter *, unsigned int flags);
int (*trylock_bus)(struct i2c_adapter *, unsigned int flags);
void (*unlock_bus)(struct i2c_adapter *, unsigned int flags);
};
/**
* struct i2c_timings - I2C timing information
* @bus_freq_hz: the bus frequency in Hz
@ -536,6 +550,7 @@ struct i2c_adapter {
void *algo_data;
/* data fields that are valid for all devices */
const struct i2c_lock_operations *lock_ops;
struct rt_mutex bus_lock;
struct rt_mutex mux_lock;
@ -552,10 +567,6 @@ struct i2c_adapter {
struct i2c_bus_recovery_info *bus_recovery_info;
const struct i2c_adapter_quirks *quirks;
void (*lock_bus)(struct i2c_adapter *, unsigned int flags);
int (*trylock_bus)(struct i2c_adapter *, unsigned int flags);
void (*unlock_bus)(struct i2c_adapter *, unsigned int flags);
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
@ -597,7 +608,21 @@ int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *));
static inline void
i2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
adapter->lock_bus(adapter, flags);
adapter->lock_ops->lock_bus(adapter, flags);
}
/**
* i2c_trylock_bus - Try to get exclusive access to an I2C bus segment
* @adapter: Target I2C bus segment
* @flags: I2C_LOCK_ROOT_ADAPTER tries to locks the root i2c adapter,
* I2C_LOCK_SEGMENT tries to lock only this branch in the adapter tree
*
* Return: true if the I2C bus segment is locked, false otherwise
*/
static inline int
i2c_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
return adapter->lock_ops->trylock_bus(adapter, flags);
}
/**
@ -609,7 +634,7 @@ i2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
static inline void
i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
adapter->unlock_bus(adapter, flags);
adapter->lock_ops->unlock_bus(adapter, flags);
}
static inline void
@ -673,6 +698,7 @@ extern void i2c_clients_command(struct i2c_adapter *adap,
extern struct i2c_adapter *i2c_get_adapter(int nr);
extern void i2c_put_adapter(struct i2c_adapter *adap);
extern unsigned int i2c_adapter_depth(struct i2c_adapter *adapter);
void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults);
@ -766,4 +792,13 @@ static inline struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node
}
#endif /* CONFIG_OF */
#if IS_ENABLED(CONFIG_ACPI)
u32 i2c_acpi_find_bus_speed(struct device *dev);
#else
static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
{
return 0;
}
#endif /* CONFIG_ACPI */
#endif /* _LINUX_I2C_H */

View File

@ -16,6 +16,8 @@ struct lockdep_map;
extern int prove_locking;
extern int lock_stat;
#define MAX_LOCKDEP_SUBCLASSES 8UL
#ifdef CONFIG_LOCKDEP
#include <linux/linkage.h>
@ -29,8 +31,6 @@ extern int lock_stat;
*/
#define XXX_LOCK_USAGE_STATES (1+3*4)
#define MAX_LOCKDEP_SUBCLASSES 8UL
/*
* NR_LOCKDEP_CACHING_CLASSES ... Number of classes
* cached in the instance of lockdep_map