Commit b5df4b5c authored by Linus Torvalds's avatar Linus Torvalds

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

Pull i2c updates from Wolfram Sang:

 - if a host can be a client, too, the I2C core can now use it to
   emulate SMBus HostNotify support (STM32 and R-Car added this so far)

 - also for client mode, a testunit has been added. It can create rare
   situations on the bus, so host controllers can be tested

 - a binding has been added to mark the bus as "single-master". This
   allows for better timeout detections

 - new driver for Mellanox Bluefield

 - massive refactoring of the Tegra driver

 - EEPROMs recognized by the at24 driver can now have custom names

 - rest is driver updates

* 'i2c/for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (80 commits)
  Documentation: i2c: add testunit docs to index
  i2c: tegra: Improve driver module description
  i2c: tegra: Clean up whitespaces, newlines and indentation
  i2c: tegra: Clean up and improve comments
  i2c: tegra: Clean up printk messages
  i2c: tegra: Clean up variable names
  i2c: tegra: Improve formatting of variables
  i2c: tegra: Check errors for both positive and negative values
  i2c: tegra: Factor out hardware initialization into separate function
  i2c: tegra: Factor out register polling into separate function
  i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg()
  i2c: tegra: Factor out error recovery from tegra_i2c_xfer_msg()
  i2c: tegra: Rename wait/poll functions
  i2c: tegra: Remove "dma" variable from tegra_i2c_xfer_msg()
  i2c: tegra: Remove redundant check in tegra_i2c_issue_bus_clear()
  i2c: tegra: Remove likely/unlikely from the code
  i2c: tegra: Remove outdated barrier()
  i2c: tegra: Clean up variable types
  i2c: tegra: Reorder location of functions in the code
  i2c: tegra: Clean up probe function
  ...
parents ed7cfefe 40daf09a
...@@ -114,6 +114,9 @@ properties: ...@@ -114,6 +114,9 @@ properties:
- const: renesas,r1ex24128 - const: renesas,r1ex24128
- const: atmel,24c128 - const: atmel,24c128
label:
description: Descriptive name of the EEPROM.
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -9,12 +9,18 @@ title: Freescale Low Power Inter IC (LPI2C) for i.MX ...@@ -9,12 +9,18 @@ title: Freescale Low Power Inter IC (LPI2C) for i.MX
maintainers: maintainers:
- Anson Huang <Anson.Huang@nxp.com> - Anson Huang <Anson.Huang@nxp.com>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties: properties:
compatible: compatible:
enum: oneOf:
- enum:
- fsl,imx7ulp-lpi2c - fsl,imx7ulp-lpi2c
- fsl,imx8qxp-lpi2c
- fsl,imx8qm-lpi2c - fsl,imx8qm-lpi2c
- items:
- const: fsl,imx8qxp-lpi2c
- const: fsl,imx7ulp-lpi2c
reg: reg:
maxItems: 1 maxItems: 1
...@@ -22,23 +28,34 @@ properties: ...@@ -22,23 +28,34 @@ properties:
interrupts: interrupts:
maxItems: 1 maxItems: 1
assigned-clock-parents: true
assigned-clock-rates: true
assigned-clocks: true
clock-frequency: true
clock-names:
maxItems: 1
clocks: clocks:
maxItems: 1 maxItems: 1
power-domains:
maxItems: 1
required: required:
- compatible - compatible
- reg - reg
- interrupts - interrupts
- clocks - clocks
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
#include <dt-bindings/clock/imx7ulp-clock.h> #include <dt-bindings/clock/imx7ulp-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
lpi2c7@40a50000 { i2c@40a50000 {
compatible = "fsl,imx7ulp-lpi2c"; compatible = "fsl,imx7ulp-lpi2c";
reg = <0x40A50000 0x10000>; reg = <0x40A50000 0x10000>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
......
...@@ -9,6 +9,9 @@ title: Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX ...@@ -9,6 +9,9 @@ title: Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
maintainers: maintainers:
- Wolfram Sang <wolfram@the-dreams.de> - Wolfram Sang <wolfram@the-dreams.de>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties: properties:
compatible: compatible:
oneOf: oneOf:
...@@ -18,6 +21,9 @@ properties: ...@@ -18,6 +21,9 @@ properties:
- items: - items:
- const: fsl,imx35-i2c - const: fsl,imx35-i2c
- const: fsl,imx1-i2c - const: fsl,imx1-i2c
- items:
- const: fsl,imx7d-i2c
- const: fsl,imx21-i2c
- items: - items:
- enum: - enum:
- fsl,imx25-i2c - fsl,imx25-i2c
...@@ -75,7 +81,7 @@ required: ...@@ -75,7 +81,7 @@ required:
- interrupts - interrupts
- clocks - clocks
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -87,6 +87,11 @@ wants to support one of the below features, it should adapt these bindings. ...@@ -87,6 +87,11 @@ wants to support one of the below features, it should adapt these bindings.
this information to detect a stalled bus more reliably, for example. this information to detect a stalled bus more reliably, for example.
Can not be combined with 'multi-master'. Can not be combined with 'multi-master'.
- smbus
states that additional SMBus restrictions and features apply to this bus.
Examples of features are SMBusHostNotify and SMBusAlert. Examples of
restrictions are more reserved addresses and timeout definitions.
Required properties (per child device) Required properties (per child device)
-------------------------------------- --------------------------------------
......
...@@ -17,9 +17,13 @@ properties: ...@@ -17,9 +17,13 @@ properties:
pattern: "^i2c@[0-9a-f]+$" pattern: "^i2c@[0-9a-f]+$"
compatible: compatible:
enum: oneOf:
- ingenic,jz4780-i2c - enum:
- ingenic,jz4770-i2c
- ingenic,x1000-i2c - ingenic,x1000-i2c
- items:
- const: ingenic,jz4780-i2c
- const: ingenic,jz4770-i2c
reg: reg:
maxItems: 1 maxItems: 1
...@@ -60,7 +64,7 @@ examples: ...@@ -60,7 +64,7 @@ examples:
#include <dt-bindings/dma/jz4780-dma.h> #include <dt-bindings/dma/jz4780-dma.h>
#include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/irq.h>
i2c@10054000 { i2c@10054000 {
compatible = "ingenic,jz4780-i2c"; compatible = "ingenic,jz4780-i2c", "ingenic,jz4770-i2c";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
reg = <0x10054000 0x1000>; reg = <0x10054000 0x1000>;
......
Device tree configuration for the Mellanox I2C SMBus on BlueField SoCs
Required Properties:
- compatible : should be "mellanox,i2c-mlxbf1" or "mellanox,i2c-mlxbf2".
- reg : address offset and length of the device registers. The
registers consist of the following set of resources:
1) Smbus block registers.
2) Cause master registers.
3) Cause slave registers.
4) Cause coalesce registers (if compatible isn't set
to "mellanox,i2c-mlxbf1").
- interrupts : interrupt number.
Optional Properties:
- clock-frequency : bus frequency used to configure timing registers;
allowed values are 100000, 400000 and 1000000;
those are expressed in Hz. Default is 100000.
Example:
i2c@2804000 {
compatible = "mellanox,i2c-mlxbf1";
reg = <0x02804000 0x800>,
<0x02801200 0x020>,
<0x02801260 0x020>;
interrupts = <57>;
clock-frequency = <100000>;
};
i2c@2808800 {
compatible = "mellanox,i2c-mlxbf2";
reg = <0x02808800 0x600>,
<0x02808e00 0x020>,
<0x02808e20 0x020>,
<0x02808e40 0x010>;
interrupts = <57>;
clock-frequency = <400000>;
};
...@@ -44,6 +44,7 @@ Supported adapters: ...@@ -44,6 +44,7 @@ Supported adapters:
* Intel Tiger Lake (PCH) * Intel Tiger Lake (PCH)
* Intel Jasper Lake (SOC) * Intel Jasper Lake (SOC)
* Intel Emmitsburg (PCH) * Intel Emmitsburg (PCH)
* Intel Alder Lake (PCH)
Datasheets: Publicly available at the Intel website Datasheets: Publicly available at the Intel website
......
...@@ -47,6 +47,7 @@ Slave I2C ...@@ -47,6 +47,7 @@ Slave I2C
slave-interface slave-interface
slave-eeprom-backend slave-eeprom-backend
slave-testunit-backend
Advanced topics Advanced topics
=============== ===============
......
.. SPDX-License-Identifier: GPL-2.0
================================
Linux I2C slave testunit backend
================================
by Wolfram Sang <wsa@sang-engineering.com> in 2020
This backend can be used to trigger test cases for I2C bus masters which
require a remote device with certain capabilities (and which are usually not so
easy to obtain). Examples include multi-master testing, and SMBus Host Notify
testing. For some tests, the I2C slave controller must be able to switch
between master and slave mode because it needs to send data, too.
Note that this is a device for testing and debugging. It should not be enabled
in a production build. And while there is some versioning and we try hard to
keep backward compatibility, there is no stable ABI guaranteed!
Instantiating the device is regular. Example for bus 0, address 0x30:
# echo "slave-testunit 0x1030" > /sys/bus/i2c/devices/i2c-0/new_device
After that, you will have a write-only device listening. Reads will just return
an 8-bit version number of the testunit. When writing, the device consists of 4
8-bit registers and all must be written to start a testcase, i.e. you must
always write 4 bytes to the device. The registers are:
0x00 CMD - which test to trigger
0x01 DATAL - configuration byte 1 for the test
0x02 DATAH - configuration byte 2 for the test
0x03 DELAY - delay in n * 10ms until test is started
Using 'i2cset' from the i2c-tools package, the generic command looks like:
# i2cset -y <bus_num> <testunit_address> <CMD> <DATAL> <DATAH> <DELAY> i
DELAY is a generic parameter which will delay the execution of the test in CMD.
While a command is running (including the delay), new commands will not be
acknowledged. You need to wait until the old one is completed.
The commands are described in the following section. An invalid command will
result in the transfer not being acknowledged.
Commands
--------
0x00 NOOP (reserved for future use)
0x01 READ_BYTES (also needs master mode)
DATAL - address to read data from (lower 7 bits, highest bit currently unused)
DATAH - number of bytes to read
This is useful to test if your bus master driver is handling multi-master
correctly. You can trigger the testunit to read bytes from another device on
the bus. If the bus master under test also wants to access the bus at the same
time, the bus will be busy. Example to read 128 bytes from device 0x50 after
50ms of delay:
# i2cset -y 0 0x30 0x01 0x50 0x80 0x05 i
0x02 SMBUS_HOST_NOTIFY (also needs master mode)
DATAL - low byte of the status word to send
DATAH - high byte of the status word to send
This test will send an SMBUS_HOST_NOTIFY message to the host. Note that the
status word is currently ignored in the Linux Kernel. Example to send a
notification after 10ms:
# i2cset -y 0 0x30 0x02 0x42 0x64 0x01 i
...@@ -11159,6 +11159,12 @@ W: http://www.melfas.com ...@@ -11159,6 +11159,12 @@ W: http://www.melfas.com
F: Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt F: Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt
F: drivers/input/touchscreen/melfas_mip4.c F: drivers/input/touchscreen/melfas_mip4.c
MELLANOX BLUEFIELD I2C DRIVER
M: Khalil Blaiech <kblaiech@mellanox.com>
L: linux-i2c@vger.kernel.org
S: Supported
F: drivers/i2c/busses/i2c-mlxbf.c
MELLANOX ETHERNET DRIVER (mlx4_en) MELLANOX ETHERNET DRIVER (mlx4_en)
M: Tariq Toukan <tariqt@nvidia.com> M: Tariq Toukan <tariqt@nvidia.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
......
...@@ -101,7 +101,6 @@ source "drivers/i2c/busses/Kconfig" ...@@ -101,7 +101,6 @@ source "drivers/i2c/busses/Kconfig"
config I2C_STUB config I2C_STUB
tristate "I2C/SMBus Test Stub" tristate "I2C/SMBus Test Stub"
depends on m depends on m
default 'n'
help help
This module may be useful to developers of SMBus client drivers, This module may be useful to developers of SMBus client drivers,
especially for certain kinds of sensor chips. especially for certain kinds of sensor chips.
...@@ -126,6 +125,14 @@ config I2C_SLAVE_EEPROM ...@@ -126,6 +125,14 @@ config I2C_SLAVE_EEPROM
This backend makes Linux behave like an I2C EEPROM. Please read This backend makes Linux behave like an I2C EEPROM. Please read
Documentation/i2c/slave-eeprom-backend.rst for further details. Documentation/i2c/slave-eeprom-backend.rst for further details.
config I2C_SLAVE_TESTUNIT
tristate "I2C eeprom testunit driver"
help
This backend can be used to trigger test cases for I2C bus masters
which require a remote device with certain capabilities, e.g.
multi-master, SMBus Host Notify, etc. Please read
Documentation/i2c/slave-testunit-backend.rst for further details.
endif endif
config I2C_DEBUG_CORE config I2C_DEBUG_CORE
......
...@@ -16,5 +16,6 @@ obj-$(CONFIG_I2C_MUX) += i2c-mux.o ...@@ -16,5 +16,6 @@ obj-$(CONFIG_I2C_MUX) += i2c-mux.o
obj-y += algos/ busses/ muxes/ obj-y += algos/ busses/ muxes/
obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_I2C_SLAVE_EEPROM) += i2c-slave-eeprom.o obj-$(CONFIG_I2C_SLAVE_EEPROM) += i2c-slave-eeprom.o
obj-$(CONFIG_I2C_SLAVE_TESTUNIT) += i2c-slave-testunit.o
ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
...@@ -147,6 +147,7 @@ config I2C_I801 ...@@ -147,6 +147,7 @@ config I2C_I801
Tiger Lake (PCH) Tiger Lake (PCH)
Jasper Lake (SOC) Jasper Lake (SOC)
Emmitsburg (PCH) Emmitsburg (PCH)
Alder Lake (PCH)
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-i801. will be called i2c-i801.
...@@ -730,6 +731,19 @@ config I2C_LPC2K ...@@ -730,6 +731,19 @@ config I2C_LPC2K
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-lpc2k. will be called i2c-lpc2k.
config I2C_MLXBF
tristate "Mellanox BlueField I2C controller"
depends on ARM64
help
Enabling this option will add I2C SMBus support for Mellanox BlueField
system.
This driver can also be built as a module. If so, the module will be
called i2c-mlxbf.
This driver implements an I2C SMBus host controller and enables both
master and slave functions.
config I2C_MESON config I2C_MESON
tristate "Amlogic Meson I2C controller" tristate "Amlogic Meson I2C controller"
depends on ARCH_MESON || COMPILE_TEST depends on ARCH_MESON || COMPILE_TEST
...@@ -840,7 +854,6 @@ config I2C_PASEMI ...@@ -840,7 +854,6 @@ config I2C_PASEMI
config I2C_PCA_PLATFORM config I2C_PCA_PLATFORM
tristate "PCA9564/PCA9665 as platform device" tristate "PCA9564/PCA9665 as platform device"
select I2C_ALGOPCA select I2C_ALGOPCA
default n
help help
This driver supports a memory mapped Philips PCA9564/PCA9665 This driver supports a memory mapped Philips PCA9564/PCA9665
parallel bus to I2C bus controller. parallel bus to I2C bus controller.
...@@ -1026,6 +1039,7 @@ config I2C_STM32F7 ...@@ -1026,6 +1039,7 @@ config I2C_STM32F7
tristate "STMicroelectronics STM32F7 I2C support" tristate "STMicroelectronics STM32F7 I2C support"
depends on ARCH_STM32 || COMPILE_TEST depends on ARCH_STM32 || COMPILE_TEST
select I2C_SLAVE select I2C_SLAVE
select I2C_SMBUS
help help
Enable this option to add support for STM32 I2C controller embedded Enable this option to add support for STM32 I2C controller embedded
in STM32F7 SoCs. in STM32F7 SoCs.
...@@ -1181,6 +1195,8 @@ config I2C_RCAR ...@@ -1181,6 +1195,8 @@ config I2C_RCAR
tristate "Renesas R-Car I2C Controller" tristate "Renesas R-Car I2C Controller"
depends on ARCH_RENESAS || COMPILE_TEST depends on ARCH_RENESAS || COMPILE_TEST
select I2C_SLAVE select I2C_SLAVE
select I2C_SMBUS
select RESET_CONTROLLER if ARCH_RCAR_GEN3
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
R-Car I2C controller. R-Car I2C controller.
...@@ -1240,7 +1256,6 @@ config I2C_TAOS_EVM ...@@ -1240,7 +1256,6 @@ config I2C_TAOS_EVM
depends on TTY depends on TTY
select SERIO select SERIO
select SERIO_SERPORT select SERIO_SERPORT
default n
help help
This supports TAOS evaluation modules on serial port. In order to This supports TAOS evaluation modules on serial port. In order to
use this driver, you will need the inputattach tool, which is part use this driver, you will need the inputattach tool, which is part
...@@ -1324,7 +1339,6 @@ config I2C_PCA_ISA ...@@ -1324,7 +1339,6 @@ config I2C_PCA_ISA
tristate "PCA9564/PCA9665 on an ISA bus" tristate "PCA9564/PCA9665 on an ISA bus"
depends on ISA depends on ISA
select I2C_ALGOPCA select I2C_ALGOPCA
default n
help help
This driver supports ISA boards using the Philips PCA9564/PCA9665 This driver supports ISA boards using the Philips PCA9564/PCA9665
parallel bus to I2C bus controller. parallel bus to I2C bus controller.
......
...@@ -140,6 +140,7 @@ obj-$(CONFIG_I2C_BRCMSTB) += i2c-brcmstb.o ...@@ -140,6 +140,7 @@ obj-$(CONFIG_I2C_BRCMSTB) += i2c-brcmstb.o
obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_ICY) += i2c-icy.o obj-$(CONFIG_I2C_ICY) += i2c-icy.o
obj-$(CONFIG_I2C_MLXBF) += i2c-mlxbf.o
obj-$(CONFIG_I2C_MLXCPLD) += i2c-mlxcpld.o obj-$(CONFIG_I2C_MLXCPLD) += i2c-mlxcpld.o
obj-$(CONFIG_I2C_OPAL) += i2c-opal.o obj-$(CONFIG_I2C_OPAL) += i2c-opal.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
......
...@@ -155,7 +155,7 @@ static int i2c_amd_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -155,7 +155,7 @@ static int i2c_amd_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
struct amd_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct amd_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
int i; int i;
struct i2c_msg *pmsg; struct i2c_msg *pmsg;
int err; int err = 0;
/* the adapter might have been deleted while waiting for the bus lock */ /* the adapter might have been deleted while waiting for the bus lock */
if (unlikely(!i2c_dev->common.mp2_dev)) if (unlikely(!i2c_dev->common.mp2_dev))
......
...@@ -421,11 +421,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) ...@@ -421,11 +421,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
return PTR_ERR(i2c_dev->regs); return PTR_ERR(i2c_dev->regs);
mclk = devm_clk_get(&pdev->dev, NULL); mclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(mclk)) { if (IS_ERR(mclk))
if (PTR_ERR(mclk) != -EPROBE_DEFER) return dev_err_probe(&pdev->dev, PTR_ERR(mclk),
dev_err(&pdev->dev, "Could not get clock\n"); "Could not get clock\n");
return PTR_ERR(mclk);
}
i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev); i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
......
...@@ -332,21 +332,15 @@ static int efm32_i2c_probe(struct platform_device *pdev) ...@@ -332,21 +332,15 @@ static int efm32_i2c_probe(struct platform_device *pdev)
return ret; return ret;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ddata->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (!res) { if (IS_ERR(ddata->base))
dev_err(&pdev->dev, "failed to determine base address\n"); return PTR_ERR(ddata->base);
return -ENODEV;
}
if (resource_size(res) < 0x42) { if (resource_size(res) < 0x42) {
dev_err(&pdev->dev, "memory resource too small\n"); dev_err(&pdev->dev, "memory resource too small\n");
return -EINVAL; return -EINVAL;
} }
ddata->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ddata->base))
return PTR_ERR(ddata->base);
ret = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0);
if (ret <= 0) { if (ret <= 0) {
if (!ret) if (!ret)
......
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
* Tiger Lake-H (PCH) 0x43a3 32 hard yes yes yes * Tiger Lake-H (PCH) 0x43a3 32 hard yes yes yes
* Jasper Lake (SOC) 0x4da3 32 hard yes yes yes * Jasper Lake (SOC) 0x4da3 32 hard yes yes yes
* Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes * Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes
* Alder Lake-S (PCH) 0x7aa3 32 hard yes yes yes
* *
* Features supported by this driver: * Features supported by this driver:
* Software PEC no * Software PEC no
...@@ -228,6 +229,7 @@ ...@@ -228,6 +229,7 @@
#define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23
#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 #define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2
#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22 #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22
...@@ -1081,6 +1083,7 @@ static const struct pci_device_id i801_ids[] = { ...@@ -1081,6 +1083,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS) },
{ 0, } { 0, }
}; };
...@@ -1274,6 +1277,7 @@ static const struct { ...@@ -1274,6 +1277,7 @@ static const struct {
/* /*
* Additional individual entries were added after verification. * Additional individual entries were added after verification.
*/ */
{ "Latitude 5480", 0x29 },
{ "Vostro V131", 0x1d }, { "Vostro V131", 0x1d },
}; };
...@@ -1767,6 +1771,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1767,6 +1771,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
case PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS: case PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS:
case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS: case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS:
case PCI_DEVICE_ID_INTEL_EBG_SMBUS: case PCI_DEVICE_ID_INTEL_EBG_SMBUS:
case PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS:
priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_BLOCK_PROC;
priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ; priv->features |= FEATURE_IRQ;
......
...@@ -1159,11 +1159,9 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1159,11 +1159,9 @@ static int i2c_imx_probe(struct platform_device *pdev)
/* Get I2C clock */ /* Get I2C clock */
i2c_imx->clk = devm_clk_get(&pdev->dev, NULL); i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2c_imx->clk)) { if (IS_ERR(i2c_imx->clk))
if (PTR_ERR(i2c_imx->clk) != -EPROBE_DEFER) return dev_err_probe(&pdev->dev, PTR_ERR(i2c_imx->clk),
dev_err(&pdev->dev, "can't get I2C clock\n"); "can't get I2C clock\n");
return PTR_ERR(i2c_imx->clk);
}
ret = clk_prepare_enable(i2c_imx->clk); ret = clk_prepare_enable(i2c_imx->clk);
if (ret) { if (ret) {
...@@ -1171,14 +1169,6 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1171,14 +1169,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* Request IRQ */
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED,
pdev->name, i2c_imx);
if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
goto clk_disable;
}
/* Init queue */ /* Init queue */
init_waitqueue_head(&i2c_imx->queue); init_waitqueue_head(&i2c_imx->queue);
...@@ -1197,6 +1187,14 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1197,6 +1187,14 @@ static int i2c_imx_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto rpm_disable; goto rpm_disable;
/* Request IRQ */
ret = request_threaded_irq(irq, i2c_imx_isr, NULL, IRQF_SHARED,
pdev->name, i2c_imx);
if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
goto rpm_disable;
}
/* Set up clock divider */ /* Set up clock divider */
i2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ; i2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
ret = of_property_read_u32(pdev->dev.of_node, ret = of_property_read_u32(pdev->dev.of_node,
...@@ -1239,13 +1237,12 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1239,13 +1237,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
clk_notifier_unregister: clk_notifier_unregister:
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb); clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
free_irq(irq, i2c_imx);
rpm_disable: rpm_disable:
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev); pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev);
clk_disable:
clk_disable_unprepare(i2c_imx->clk); clk_disable_unprepare(i2c_imx->clk);
return ret; return ret;
} }
...@@ -1253,7 +1250,7 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1253,7 +1250,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
static int i2c_imx_remove(struct platform_device *pdev) static int i2c_imx_remove(struct platform_device *pdev)
{ {
struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
int ret; int irq, ret;
ret = pm_runtime_get_sync(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) if (ret < 0)
...@@ -1273,6 +1270,9 @@ static int i2c_imx_remove(struct platform_device *pdev) ...@@ -1273,6 +1270,9 @@ static int i2c_imx_remove(struct platform_device *pdev)
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb); clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
irq = platform_get_irq(pdev, 0);
if (irq >= 0)
free_irq(irq, i2c_imx);
clk_disable_unprepare(i2c_imx->clk); clk_disable_unprepare(i2c_imx->clk);
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a #define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a
#define PCI_DEVICE_ID_INTEL_CDF_SMT 0x18ac #define PCI_DEVICE_ID_INTEL_CDF_SMT 0x18ac
#define PCI_DEVICE_ID_INTEL_DNV_SMT 0x19ac #define PCI_DEVICE_ID_INTEL_DNV_SMT 0x19ac
#define PCI_DEVICE_ID_INTEL_EBG_SMT 0x1bff
#define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15 #define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15
#define ISMT_DESC_ENTRIES 2 /* number of descriptor entries */ #define ISMT_DESC_ENTRIES 2 /* number of descriptor entries */
...@@ -176,14 +177,12 @@ struct ismt_priv { ...@@ -176,14 +177,12 @@ struct ismt_priv {
u8 buffer[I2C_SMBUS_BLOCK_MAX + 16]; /* temp R/W data buffer */ u8 buffer[I2C_SMBUS_BLOCK_MAX + 16]; /* temp R/W data buffer */
}; };
/**
* ismt_ids - PCI device IDs supported by this driver
*/
static const struct pci_device_id ismt_ids[] = { static const struct pci_device_id ismt_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMT) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMT) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EBG_SMT) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) },
{ 0, } { 0, }
}; };
...@@ -197,6 +196,8 @@ MODULE_PARM_DESC(bus_speed, "Bus Speed in kHz (0 = BIOS default)"); ...@@ -197,6 +196,8 @@ MODULE_PARM_DESC(bus_speed, "Bus Speed in kHz (0 = BIOS default)");
/** /**
* __ismt_desc_dump() - dump the contents of a specific descriptor * __ismt_desc_dump() - dump the contents of a specific descriptor
* @dev: the iSMT device
* @desc: the iSMT hardware descriptor
*/ */
static void __ismt_desc_dump(struct device *dev, const struct ismt_desc *desc) static void __ismt_desc_dump(struct device *dev, const struct ismt_desc *desc)
{ {
...@@ -628,11 +629,6 @@ static u32 ismt_func(struct i2c_adapter *adap) ...@@ -628,11 +629,6 @@ static u32 ismt_func(struct i2c_adapter *adap)
I2C_FUNC_SMBUS_PEC; I2C_FUNC_SMBUS_PEC;
} }
/**
* smbus_algorithm - the adapter algorithm and supported functionality
* @smbus_xfer: the adapter algorithm
* @functionality: functionality supported by the adapter
*/
static const struct i2c_algorithm smbus_algorithm = { static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = ismt_access, .smbus_xfer = ismt_access,
.functionality = ismt_func, .functionality = ismt_func,
......
...@@ -752,6 +752,7 @@ static const struct ingenic_i2c_config x1000_i2c_config = { ...@@ -752,6 +752,7 @@ static const struct ingenic_i2c_config x1000_i2c_config = {
}; };
static const struct of_device_id jz4780_i2c_of_matches[] = { static const struct of_device_id jz4780_i2c_of_matches[] = {
{ .compatible = "ingenic,jz4770-i2c", .data = &jz4780_i2c_config },
{ .compatible = "ingenic,jz4780-i2c", .data = &jz4780_i2c_config }, { .compatible = "ingenic,jz4780-i2c", .data = &jz4780_i2c_config },
{ .compatible = "ingenic,x1000-i2c", .data = &x1000_i2c_config }, { .compatible = "ingenic,x1000-i2c", .data = &x1000_i2c_config },
{ /* sentinel */ } { /* sentinel */ }
...@@ -856,7 +857,7 @@ static struct platform_driver jz4780_i2c_driver = { ...@@ -856,7 +857,7 @@ static struct platform_driver jz4780_i2c_driver = {
.remove = jz4780_i2c_remove, .remove = jz4780_i2c_remove,
.driver = { .driver = {
.name = "jz4780-i2c", .name = "jz4780-i2c",
.of_match_table = of_match_ptr(jz4780_i2c_of_matches), .of_match_table = jz4780_i2c_of_matches,
}, },
}; };
......
// SPDX-License-Identifier: GPL-2.0
/*
* Mellanox BlueField I2C bus driver
*
* Copyright (C) 2020 Mellanox Technologies, Ltd.
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/string.h>
/* Defines what functionality is present. */
#define MLXBF_I2C_FUNC_SMBUS_BLOCK \
(I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL)
#define MLXBF_I2C_FUNC_SMBUS_DEFAULT \
(I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | \
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK | \
I2C_FUNC_SMBUS_PROC_CALL)
#define MLXBF_I2C_FUNC_ALL \
(MLXBF_I2C_FUNC_SMBUS_DEFAULT | MLXBF_I2C_FUNC_SMBUS_BLOCK | \
I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SLAVE)
#define MLXBF_I2C_SMBUS_MAX 3
/* Shared resources info in BlueField platforms. */
#define MLXBF_I2C_COALESCE_TYU_ADDR 0x02801300
#define MLXBF_I2C_COALESCE_TYU_SIZE 0x010
#define MLXBF_I2C_GPIO_TYU_ADDR 0x02802000
#define MLXBF_I2C_GPIO_TYU_SIZE 0x100
#define MLXBF_I2C_COREPLL_TYU_ADDR 0x02800358
#define MLXBF_I2C_COREPLL_TYU_SIZE 0x008
#define MLXBF_I2C_COREPLL_YU_ADDR 0x02800c30
#define MLXBF_I2C_COREPLL_YU_SIZE 0x00c
#define MLXBF_I2C_SHARED_RES_MAX 3
/*
* Note that the following SMBus, CAUSE, GPIO and PLL register addresses
* refer to their respective offsets relative to the corresponding
* memory-mapped region whose addresses are specified in either the DT or
* the ACPI tables or above.
*/
/*
* SMBus Master core clock frequency. Timing configurations are
* strongly dependent on the core clock frequency of the SMBus
* Master. Default value is set to 400MHz.
*/
#define MLXBF_I2C_TYU_PLL_OUT_FREQ (400 * 1000 * 1000)
/* Reference clock for Bluefield 1 - 156 MHz. */
#define MLXBF_I2C_TYU_PLL_IN_FREQ (156 * 1000 * 1000)
/* Reference clock for BlueField 2 - 200 MHz. */
#define MLXBF_I2C_YU_PLL_IN_FREQ (200 * 1000 * 1000)
/* Constant used to determine the PLL frequency. */
#define MLNXBF_I2C_COREPLL_CONST 16384
/* PLL registers. */
#define MLXBF_I2C_CORE_PLL_REG0 0x0
#define MLXBF_I2C_CORE_PLL_REG1 0x4
#define MLXBF_I2C_CORE_PLL_REG2 0x8
/* OR cause register. */
#define MLXBF_I2C_CAUSE_OR_EVTEN0 0x14
#define MLXBF_I2C_CAUSE_OR_CLEAR 0x18
/* Arbiter Cause Register. */
#define MLXBF_I2C_CAUSE_ARBITER 0x1c
/*
* Cause Status flags. Note that those bits might be considered
* as interrupt enabled bits.
*/
/* Transaction ended with STOP. */
#define MLXBF_I2C_CAUSE_TRANSACTION_ENDED BIT(0)
/* Master arbitration lost. */
#define MLXBF_I2C_CAUSE_M_ARBITRATION_LOST BIT(1)
/* Unexpected start detected. */
#define MLXBF_I2C_CAUSE_UNEXPECTED_START BIT(2)
/* Unexpected stop detected. */
#define MLXBF_I2C_CAUSE_UNEXPECTED_STOP BIT(3)
/* Wait for transfer continuation. */
#define MLXBF_I2C_CAUSE_WAIT_FOR_FW_DATA BIT(4)
/* Failed to generate STOP. */
#define MLXBF_I2C_CAUSE_PUT_STOP_FAILED BIT(5)
/* Failed to generate START. */
#define MLXBF_I2C_CAUSE_PUT_START_FAILED BIT(6)
/* Clock toggle completed. */
#define MLXBF_I2C_CAUSE_CLK_TOGGLE_DONE BIT(7)
/* Transfer timeout occurred. */
#define MLXBF_I2C_CAUSE_M_FW_TIMEOUT BIT(8)
/* Master busy bit reset. */
#define MLXBF_I2C_CAUSE_M_GW_BUSY_FALL BIT(9)
#define MLXBF_I2C_CAUSE_MASTER_ARBITER_BITS_MASK GENMASK(9, 0)
#define MLXBF_I2C_CAUSE_MASTER_STATUS_ERROR \
(MLXBF_I2C_CAUSE_M_ARBITRATION_LOST | \
MLXBF_I2C_CAUSE_UNEXPECTED_START | \
MLXBF_I2C_CAUSE_UNEXPECTED_STOP | \
MLXBF_I2C_CAUSE_PUT_STOP_FAILED | \
MLXBF_I2C_CAUSE_PUT_START_FAILED | \
MLXBF_I2C_CAUSE_CLK_TOGGLE_DONE | \
MLXBF_I2C_CAUSE_M_FW_TIMEOUT)
/*
* Slave cause status flags. Note that those bits might be considered
* as interrupt enabled bits.
*/
/* Write transaction received successfully. */
#define MLXBF_I2C_CAUSE_WRITE_SUCCESS BIT(0)
/* Read transaction received, waiting for response. */
#define MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE BIT(13)
/* Slave busy bit reset. */
#define MLXBF_I2C_CAUSE_S_GW_BUSY_FALL BIT(18)
#define MLXBF_I2C_CAUSE_SLAVE_ARBITER_BITS_MASK GENMASK(20, 0)
/* Cause coalesce registers. */
#define MLXBF_I2C_CAUSE_COALESCE_0 0x00
#define MLXBF_I2C_CAUSE_COALESCE_1 0x04
#define MLXBF_I2C_CAUSE_COALESCE_2 0x08
#define MLXBF_I2C_CAUSE_TYU_SLAVE_BIT MLXBF_I2C_SMBUS_MAX
#define MLXBF_I2C_CAUSE_YU_SLAVE_BIT 1
/* Functional enable register. */
#define MLXBF_I2C_GPIO_0_FUNC_EN_0 0x28
/* Force OE enable register. */
#define MLXBF_I2C_GPIO_0_FORCE_OE_EN 0x30
/*
* Note that Smbus GWs are on GPIOs 30:25. Two pins are used to control
* SDA/SCL lines:
*
* SMBUS GW0 -> bits[26:25]
* SMBUS GW1 -> bits[28:27]
* SMBUS GW2 -> bits[30:29]
*/
#define MLXBF_I2C_GPIO_SMBUS_GW_PINS(num) (25 + ((num) << 1))
/* Note that gw_id can be 0,1 or 2. */
#define MLXBF_I2C_GPIO_SMBUS_GW_MASK(num) \
(0xffffffff & (~(0x3 << MLXBF_I2C_GPIO_SMBUS_GW_PINS(num))))
#define MLXBF_I2C_GPIO_SMBUS_GW_RESET_PINS(num, val) \
((val) & MLXBF_I2C_GPIO_SMBUS_GW_MASK(num))
#define MLXBF_I2C_GPIO_SMBUS_GW_ASSERT_PINS(num, val) \
((val) | (0x3 << MLXBF_I2C_GPIO_SMBUS_GW_PINS(num)))
/* SMBus timing parameters. */
#define MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH 0x00
#define MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE 0x04
#define MLXBF_I2C_SMBUS_TIMER_THOLD 0x08
#define MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP 0x0c
#define MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA 0x10
#define MLXBF_I2C_SMBUS_THIGH_MAX_TBUF 0x14
#define MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT 0x18
enum {
MLXBF_I2C_TIMING_100KHZ = 100000,
MLXBF_I2C_TIMING_400KHZ = 400000,
MLXBF_I2C_TIMING_1000KHZ = 1000000,
};
/*
* Defines SMBus operating frequency and core clock frequency.
* According to ADB files, default values are compliant to 100KHz SMBus
* @ 400MHz core clock. The driver should be able to calculate core
* frequency based on PLL parameters.
*/
#define MLXBF_I2C_COREPLL_FREQ MLXBF_I2C_TYU_PLL_OUT_FREQ
/* Core PLL TYU configuration. */
#define MLXBF_I2C_COREPLL_CORE_F_TYU_MASK GENMASK(12, 0)
#define MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK GENMASK(3, 0)
#define MLXBF_I2C_COREPLL_CORE_R_TYU_MASK GENMASK(5, 0)
#define MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT 3
#define MLXBF_I2C_COREPLL_CORE_OD_TYU_SHIFT 16
#define MLXBF_I2C_COREPLL_CORE_R_TYU_SHIFT 20
/* Core PLL YU configuration. */
#define MLXBF_I2C_COREPLL_CORE_F_YU_MASK GENMASK(25, 0)
#define MLXBF_I2C_COREPLL_CORE_OD_YU_MASK GENMASK(3, 0)
#define MLXBF_I2C_COREPLL_CORE_R_YU_MASK GENMASK(5, 0)
#define MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT 0
#define MLXBF_I2C_COREPLL_CORE_OD_YU_SHIFT 1
#define MLXBF_I2C_COREPLL_CORE_R_YU_SHIFT 26
/* Core PLL frequency. */
static u64 mlxbf_i2c_corepll_frequency;
/* SMBus Master GW. */
#define MLXBF_I2C_SMBUS_MASTER_GW 0x200
/* Number of bytes received and sent. */
#define MLXBF_I2C_SMBUS_RS_BYTES 0x300
/* Packet error check (PEC) value. */
#define MLXBF_I2C_SMBUS_MASTER_PEC 0x304
/* Status bits (ACK/NACK/FW Timeout). */
#define MLXBF_I2C_SMBUS_MASTER_STATUS 0x308
/* SMbus Master Finite State Machine. */
#define MLXBF_I2C_SMBUS_MASTER_FSM 0x310
/*
* When enabled, the master will issue a stop condition in case of
* timeout while waiting for FW response.
*/
#define MLXBF_I2C_SMBUS_EN_FW_TIMEOUT 0x31c
/* SMBus master GW control bits offset in MLXBF_I2C_SMBUS_MASTER_GW[31:3]. */
#define MLXBF_I2C_MASTER_LOCK_BIT BIT(31) /* Lock bit. */
#define MLXBF_I2C_MASTER_BUSY_BIT BIT(30) /* Busy bit. */
#define MLXBF_I2C_MASTER_START_BIT BIT(29) /* Control start. */
#define MLXBF_I2C_MASTER_CTL_WRITE_BIT BIT(28) /* Control write phase. */
#define MLXBF_I2C_MASTER_CTL_READ_BIT BIT(19) /* Control read phase. */
#define MLXBF_I2C_MASTER_STOP_BIT BIT(3) /* Control stop. */
#define MLXBF_I2C_MASTER_ENABLE \
(MLXBF_I2C_MASTER_LOCK_BIT | MLXBF_I2C_MASTER_BUSY_BIT | \
MLXBF_I2C_MASTER_START_BIT | MLXBF_I2C_MASTER_STOP_BIT)
#define MLXBF_I2C_MASTER_ENABLE_WRITE \
(MLXBF_I2C_MASTER_ENABLE | MLXBF_I2C_MASTER_CTL_WRITE_BIT)
#define MLXBF_I2C_MASTER_ENABLE_READ \
(MLXBF_I2C_MASTER_ENABLE | MLXBF_I2C_MASTER_CTL_READ_BIT)
#define MLXBF_I2C_MASTER_SLV_ADDR_SHIFT 12 /* Slave address shift. */
#define MLXBF_I2C_MASTER_WRITE_SHIFT 21 /* Control write bytes shift. */
#define MLXBF_I2C_MASTER_SEND_PEC_SHIFT 20 /* Send PEC byte shift. */
#define MLXBF_I2C_MASTER_PARSE_EXP_SHIFT 11 /* Parse expected bytes shift. */
#define MLXBF_I2C_MASTER_READ_SHIFT 4 /* Control read bytes shift. */
/* SMBus master GW Data descriptor. */
#define MLXBF_I2C_MASTER_DATA_DESC_ADDR 0x280
#define MLXBF_I2C_MASTER_DATA_DESC_SIZE 0x80 /* Size in bytes. */
/* Maximum bytes to read/write per SMBus transaction. */
#define MLXBF_I2C_MASTER_DATA_R_LENGTH MLXBF_I2C_MASTER_DATA_DESC_SIZE
#define MLXBF_I2C_MASTER_DATA_W_LENGTH (MLXBF_I2C_MASTER_DATA_DESC_SIZE - 1)
/* All bytes were transmitted. */
#define MLXBF_I2C_SMBUS_STATUS_BYTE_CNT_DONE BIT(0)
/* NACK received. */
#define MLXBF_I2C_SMBUS_STATUS_NACK_RCV BIT(1)
/* Slave's byte count >128 bytes. */
#define MLXBF_I2C_SMBUS_STATUS_READ_ERR BIT(2)
/* Timeout occurred. */
#define MLXBF_I2C_SMBUS_STATUS_FW_TIMEOUT BIT(3)
#define MLXBF_I2C_SMBUS_MASTER_STATUS_MASK GENMASK(3, 0)
#define MLXBF_I2C_SMBUS_MASTER_STATUS_ERROR \
(MLXBF_I2C_SMBUS_STATUS_NACK_RCV | \
MLXBF_I2C_SMBUS_STATUS_READ_ERR | \
MLXBF_I2C_SMBUS_STATUS_FW_TIMEOUT)
#define MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK BIT(31)
#define MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK BIT(15)
/* SMBus slave GW. */
#define MLXBF_I2C_SMBUS_SLAVE_GW 0x400
/* Number of bytes received and sent from/to master. */
#define MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES 0x500
/* Packet error check (PEC) value. */
#define MLXBF_I2C_SMBUS_SLAVE_PEC 0x504
/* SMBus slave Finite State Machine (FSM). */
#define MLXBF_I2C_SMBUS_SLAVE_FSM 0x510
/*
* Should be set when all raised causes handled, and cleared by HW on
* every new cause.
*/
#define MLXBF_I2C_SMBUS_SLAVE_READY 0x52c
/* SMBus slave GW control bits offset in MLXBF_I2C_SMBUS_SLAVE_GW[31:19]. */
#define MLXBF_I2C_SLAVE_BUSY_BIT BIT(30) /* Busy bit. */
#define MLXBF_I2C_SLAVE_WRITE_BIT BIT(29) /* Control write enable. */
#define MLXBF_I2C_SLAVE_ENABLE \
(MLXBF_I2C_SLAVE_BUSY_BIT | MLXBF_I2C_SLAVE_WRITE_BIT)
#define MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT 22 /* Number of bytes to write. */
#define MLXBF_I2C_SLAVE_SEND_PEC_SHIFT 21 /* Send PEC byte shift. */
/* SMBus slave GW Data descriptor. */
#define MLXBF_I2C_SLAVE_DATA_DESC_ADDR 0x480
#define MLXBF_I2C_SLAVE_DATA_DESC_SIZE 0x80 /* Size in bytes. */
/* SMbus slave configuration registers. */
#define MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG 0x514
#define MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT 16
#define MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT 7
#define MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK GENMASK(6, 0)
#define MLXBF_I2C_SLAVE_ADDR_ENABLED(addr) \
((addr) & (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT))
/*
* Timeout is given in microsends. Note also that timeout handling is not
* exact.
*/
#define MLXBF_I2C_SMBUS_TIMEOUT (300 * 1000) /* 300ms */
/* Encapsulates timing parameters. */
struct mlxbf_i2c_timings {
u16 scl_high; /* Clock high period. */
u16 scl_low; /* Clock low period. */
u8 sda_rise; /* Data rise time. */
u8 sda_fall; /* Data fall time. */
u8 scl_rise; /* Clock rise time. */
u8 scl_fall; /* Clock fall time. */
u16 hold_start; /* Hold time after (REPEATED) START. */
u16 hold_data; /* Data hold time. */
u16 setup_start; /* REPEATED START condition setup time. */
u16 setup_stop; /* STOP condition setup time. */
u16 setup_data; /* Data setup time. */
u16 pad; /* Padding. */
u16 buf; /* Bus free time between STOP and START. */
u16 thigh_max; /* Thigh max. */
u32 timeout; /* Detect clock low timeout. */
};
enum {
MLXBF_I2C_F_READ = BIT(0),
MLXBF_I2C_F_WRITE = BIT(1),
MLXBF_I2C_F_NORESTART = BIT(3),
MLXBF_I2C_F_SMBUS_OPERATION = BIT(4),
MLXBF_I2C_F_SMBUS_BLOCK = BIT(5),
MLXBF_I2C_F_SMBUS_PEC = BIT(6),
MLXBF_I2C_F_SMBUS_PROCESS_CALL = BIT(7),
};
struct mlxbf_i2c_smbus_operation {
u32 flags;
u32 length; /* Buffer length in bytes. */
u8 *buffer;
};
#define MLXBF_I2C_SMBUS_OP_CNT_1 1
#define MLXBF_I2C_SMBUS_OP_CNT_2 2
#define MLXBF_I2C_SMBUS_OP_CNT_3 3
#define MLXBF_I2C_SMBUS_MAX_OP_CNT MLXBF_I2C_SMBUS_OP_CNT_3
struct mlxbf_i2c_smbus_request {
u8 slave;
u8 operation_cnt;
struct mlxbf_i2c_smbus_operation operation[MLXBF_I2C_SMBUS_MAX_OP_CNT];
};
struct mlxbf_i2c_resource {
void __iomem *io;
struct resource *params;
struct mutex *lock; /* Mutex to protect mlxbf_i2c_resource. */
u8 type;
};
/* List of chip resources that are being accessed by the driver. */
enum {
MLXBF_I2C_SMBUS_RES,
MLXBF_I2C_MST_CAUSE_RES,
MLXBF_I2C_SLV_CAUSE_RES,
MLXBF_I2C_COALESCE_RES,
MLXBF_I2C_COREPLL_RES,
MLXBF_I2C_GPIO_RES,
MLXBF_I2C_END_RES,
};
/* Helper macro to define an I2C resource parameters. */
#define MLXBF_I2C_RES_PARAMS(addr, size, str) \
{ \
.start = (addr), \
.end = (addr) + (size) - 1, \
.name = (str) \
}
static struct resource mlxbf_i2c_coalesce_tyu_params =
MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COALESCE_TYU_ADDR,
MLXBF_I2C_COALESCE_TYU_SIZE,
"COALESCE_MEM");
static struct resource mlxbf_i2c_corepll_tyu_params =
MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COREPLL_TYU_ADDR,
MLXBF_I2C_COREPLL_TYU_SIZE,
"COREPLL_MEM");
static struct resource mlxbf_i2c_corepll_yu_params =
MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COREPLL_YU_ADDR,
MLXBF_I2C_COREPLL_YU_SIZE,
"COREPLL_MEM");
static struct resource mlxbf_i2c_gpio_tyu_params =
MLXBF_I2C_RES_PARAMS(MLXBF_I2C_GPIO_TYU_ADDR,
MLXBF_I2C_GPIO_TYU_SIZE,
"GPIO_MEM");
static struct mutex mlxbf_i2c_coalesce_lock;
static struct mutex mlxbf_i2c_corepll_lock;
static struct mutex mlxbf_i2c_gpio_lock;
/* Mellanox BlueField chip type. */
enum mlxbf_i2c_chip_type {
MLXBF_I2C_CHIP_TYPE_1, /* Mellanox BlueField-1 chip. */
MLXBF_I2C_CHIP_TYPE_2, /* Mallanox BlueField-2 chip. */
};
struct mlxbf_i2c_chip_info {
enum mlxbf_i2c_chip_type type;
/* Chip shared resources that are being used by the I2C controller. */
struct mlxbf_i2c_resource *shared_res[MLXBF_I2C_SHARED_RES_MAX];
/* Callback to calculate the core PLL frequency. */
u64 (*calculate_freq)(struct mlxbf_i2c_resource *corepll_res);
};
struct mlxbf_i2c_priv {
const struct mlxbf_i2c_chip_info *chip;
struct i2c_adapter adap;
struct mlxbf_i2c_resource *smbus;
struct mlxbf_i2c_resource *mst_cause;
struct mlxbf_i2c_resource *slv_cause;
struct mlxbf_i2c_resource *coalesce;
u64 frequency; /* Core frequency in Hz. */
int bus; /* Physical bus identifier. */
int irq;
struct i2c_client *slave;
};
static struct mlxbf_i2c_resource mlxbf_i2c_coalesce_res[] = {
[MLXBF_I2C_CHIP_TYPE_1] = {
.params = &mlxbf_i2c_coalesce_tyu_params,
.lock = &mlxbf_i2c_coalesce_lock,
.type = MLXBF_I2C_COALESCE_RES
},
{}
};
static struct mlxbf_i2c_resource mlxbf_i2c_corepll_res[] = {
[MLXBF_I2C_CHIP_TYPE_1] = {
.params = &mlxbf_i2c_corepll_tyu_params,
.lock = &mlxbf_i2c_corepll_lock,
.type = MLXBF_I2C_COREPLL_RES
},
[MLXBF_I2C_CHIP_TYPE_2] = {
.params = &mlxbf_i2c_corepll_yu_params,
.lock = &mlxbf_i2c_corepll_lock,
.type = MLXBF_I2C_COREPLL_RES,
}
};
static struct mlxbf_i2c_resource mlxbf_i2c_gpio_res[] = {
[MLXBF_I2C_CHIP_TYPE_1] = {
.params = &mlxbf_i2c_gpio_tyu_params,
.lock = &mlxbf_i2c_gpio_lock,
.type = MLXBF_I2C_GPIO_RES
},
{}
};
static u8 mlxbf_i2c_bus_count;
static struct mutex mlxbf_i2c_bus_lock;
/* Polling frequency in microseconds. */
#define MLXBF_I2C_POLL_FREQ_IN_USEC 200
#define MLXBF_I2C_SHIFT_0 0
#define MLXBF_I2C_SHIFT_8 8
#define MLXBF_I2C_SHIFT_16 16
#define MLXBF_I2C_SHIFT_24 24
#define MLXBF_I2C_MASK_8 GENMASK(7, 0)
#define MLXBF_I2C_MASK_16 GENMASK(15, 0)
#define MLXBF_I2C_FREQUENCY_1GHZ 1000000000
static void mlxbf_i2c_write(void __iomem *io, int reg, u32 val)
{
writel(val, io + reg);
}
static u32 mlxbf_i2c_read(void __iomem *io, int reg)
{
return readl(io + reg);
}
/*
* This function is used to read data from Master GW Data Descriptor.
* Data bytes in the Master GW Data Descriptor are shifted left so the
* data starts at the MSB of the descriptor registers as set by the
* underlying hardware. TYU_READ_DATA enables byte swapping while
* reading data bytes, and MUST be called by the SMBus read routines
* to copy data from the 32 * 32-bit HW Data registers a.k.a Master GW
* Data Descriptor.
*/
static u32 mlxbf_i2c_read_data(void __iomem *io, int reg)
{
return (u32)be32_to_cpu(mlxbf_i2c_read(io, reg));
}
/*
* This function is used to write data to the Master GW Data Descriptor.
* Data copied to the Master GW Data Descriptor MUST be shifted left so
* the data starts at the MSB of the descriptor registers as required by
* the underlying hardware. TYU_WRITE_DATA enables byte swapping when
* writing data bytes, and MUST be called by the SMBus write routines to
* copy data to the 32 * 32-bit HW Data registers a.k.a Master GW Data
* Descriptor.
*/
static void mlxbf_i2c_write_data(void __iomem *io, int reg, u32 val)
{
mlxbf_i2c_write(io, reg, (u32)cpu_to_be32(val));
}
/*
* Function to poll a set of bits at a specific address; it checks whether
* the bits are equal to zero when eq_zero is set to 'true', and not equal
* to zero when eq_zero is set to 'false'.
* Note that the timeout is given in microseconds.
*/
static u32 mlxbf_smbus_poll(void __iomem *io, u32 addr, u32 mask,
bool eq_zero, u32 timeout)
{
u32 bits;
timeout = (timeout / MLXBF_I2C_POLL_FREQ_IN_USEC) + 1;
do {
bits = mlxbf_i2c_read(io, addr) & mask;
if (eq_zero ? bits == 0 : bits != 0)
return eq_zero ? 1 : bits;
udelay(MLXBF_I2C_POLL_FREQ_IN_USEC);
} while (timeout-- != 0);
return 0;
}
/*
* SW must make sure that the SMBus Master GW is idle before starting
* a transaction. Accordingly, this function polls the Master FSM stop
* bit; it returns false when the bit is asserted, true if not.
*/
static bool mlxbf_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv)
{
u32 mask = MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK;
u32 addr = MLXBF_I2C_SMBUS_MASTER_FSM;
u32 timeout = MLXBF_I2C_SMBUS_TIMEOUT;
if (mlxbf_smbus_poll(priv->smbus->io, addr, mask, true, timeout))
return true;
return false;
}
static bool mlxbf_i2c_smbus_transaction_success(u32 master_status,
u32 cause_status)
{
/*
* When transaction ended with STOP, all bytes were transmitted,
* and no NACK received, then the transaction ended successfully.
* On the other hand, when the GW is configured with the stop bit
* de-asserted then the SMBus expects the following GW configuration
* for transfer continuation.
*/
if ((cause_status & MLXBF_I2C_CAUSE_WAIT_FOR_FW_DATA) ||
((cause_status & MLXBF_I2C_CAUSE_TRANSACTION_ENDED) &&
(master_status & MLXBF_I2C_SMBUS_STATUS_BYTE_CNT_DONE) &&
!(master_status & MLXBF_I2C_SMBUS_STATUS_NACK_RCV)))
return true;
return false;
}
/*
* Poll SMBus master status and return transaction status,
* i.e. whether succeeded or failed. I2C and SMBus fault codes
* are returned as negative numbers from most calls, with zero
* or some positive number indicating a non-fault return.
*/
static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv)
{
u32 master_status_bits;
u32 cause_status_bits;
/*
* GW busy bit is raised by the driver and cleared by the HW
* when the transaction is completed. The busy bit is a good
* indicator of transaction status. So poll the busy bit, and
* then read the cause and master status bits to determine if
* errors occurred during the transaction.
*/
mlxbf_smbus_poll(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW,
MLXBF_I2C_MASTER_BUSY_BIT, true,
MLXBF_I2C_SMBUS_TIMEOUT);
/* Read cause status bits. */
cause_status_bits = mlxbf_i2c_read(priv->mst_cause->io,
MLXBF_I2C_CAUSE_ARBITER);
cause_status_bits &= MLXBF_I2C_CAUSE_MASTER_ARBITER_BITS_MASK;
/*
* Parse both Cause and Master GW bits, then return transaction status.
*/
master_status_bits = mlxbf_i2c_read(priv->smbus->io,
MLXBF_I2C_SMBUS_MASTER_STATUS);
master_status_bits &= MLXBF_I2C_SMBUS_MASTER_STATUS_MASK;
if (mlxbf_i2c_smbus_transaction_success(master_status_bits,
cause_status_bits))
return 0;
/*
* In case of timeout on GW busy, the ISR will clear busy bit but
* transaction ended bits cause will not be set so the transaction
* fails. Then, we must check Master GW status bits.
*/
if ((master_status_bits & MLXBF_I2C_SMBUS_MASTER_STATUS_ERROR) &&
(cause_status_bits & (MLXBF_I2C_CAUSE_TRANSACTION_ENDED |
MLXBF_I2C_CAUSE_M_GW_BUSY_FALL)))
return -EIO;
if (cause_status_bits & MLXBF_I2C_CAUSE_MASTER_STATUS_ERROR)
return -EAGAIN;
return -ETIMEDOUT;
}
static void mlxbf_i2c_smbus_write_data(struct mlxbf_i2c_priv *priv,
const u8 *data, u8 length, u32 addr)
{
u8 offset, aligned_length;
u32 data32;
aligned_length = round_up(length, 4);
/* Copy data bytes from 4-byte aligned source buffer. */
for (offset = 0; offset < aligned_length; offset += sizeof(u32)) {
data32 = *((u32 *)(data + offset));
mlxbf_i2c_write_data(priv->smbus->io, addr + offset, data32);
}
}
static void mlxbf_i2c_smbus_read_data(struct mlxbf_i2c_priv *priv,
u8 *data, u8 length, u32 addr)
{
u32 data32, mask;
u8 byte, offset;
mask = sizeof(u32) - 1;
for (offset = 0; offset < (length & ~mask); offset += sizeof(u32)) {
data32 = mlxbf_i2c_read_data(priv->smbus->io, addr + offset);
*((u32 *)(data + offset)) = data32;
}
if (!(length & mask))
return;
data32 = mlxbf_i2c_read_data(priv->smbus->io, addr + offset);
for (byte = 0; byte < (length & mask); byte++) {
data[offset + byte] = data32 & GENMASK(7, 0);
data32 = ror32(data32, MLXBF_I2C_SHIFT_8);
}
}
static int mlxbf_i2c_smbus_enable(struct mlxbf_i2c_priv *priv, u8 slave,
u8 len, u8 block_en, u8 pec_en, bool read)
{
u32 command;
/* Set Master GW control word. */
if (read) {
command = MLXBF_I2C_MASTER_ENABLE_READ;
command |= rol32(len, MLXBF_I2C_MASTER_READ_SHIFT);
} else {
command = MLXBF_I2C_MASTER_ENABLE_WRITE;
command |= rol32(len, MLXBF_I2C_MASTER_WRITE_SHIFT);
}
command |= rol32(slave, MLXBF_I2C_MASTER_SLV_ADDR_SHIFT);
command |= rol32(block_en, MLXBF_I2C_MASTER_PARSE_EXP_SHIFT);
command |= rol32(pec_en, MLXBF_I2C_MASTER_SEND_PEC_SHIFT);
/* Clear status bits. */
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_STATUS, 0x0);
/* Set the cause data. */
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_CAUSE_OR_CLEAR, ~0x0);
/* Zero PEC byte. */
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_PEC, 0x0);
/* Zero byte count. */
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_RS_BYTES, 0x0);
/* GW activation. */
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW, command);
/*
* Poll master status and check status bits. An ACK is sent when
* completing writing data to the bus (Master 'byte_count_done' bit
* is set to 1).
*/
return mlxbf_i2c_smbus_check_status(priv);
}
static int
mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
struct mlxbf_i2c_smbus_request *request)
{
u8 data_desc[MLXBF_I2C_MASTER_DATA_DESC_SIZE] = { 0 };
u8 op_idx, data_idx, data_len, write_len, read_len;
struct mlxbf_i2c_smbus_operation *operation;
u8 read_en, write_en, block_en, pec_en;
u8 slave, flags, addr;
u8 *read_buf;
int ret = 0;
if (request->operation_cnt > MLXBF_I2C_SMBUS_MAX_OP_CNT)
return -EINVAL;
read_buf = NULL;
data_idx = 0;
read_en = 0;
write_en = 0;
write_len = 0;
read_len = 0;
block_en = 0;
pec_en = 0;
slave = request->slave & GENMASK(6, 0);
addr = slave << 1;
/* First of all, check whether the HW is idle. */
if (WARN_ON(!mlxbf_smbus_master_wait_for_idle(priv)))
return -EBUSY;
/* Set first byte. */
data_desc[data_idx++] = addr;
for (op_idx = 0; op_idx < request->operation_cnt; op_idx++) {
operation = &request->operation[op_idx];
flags = operation->flags;
/*
* Note that read and write operations might be handled by a
* single command. If the MLXBF_I2C_F_SMBUS_OPERATION is set
* then write command byte and set the optional SMBus specific
* bits such as block_en and pec_en. These bits MUST be
* submitted by the first operation only.
*/
if (op_idx == 0 && flags & MLXBF_I2C_F_SMBUS_OPERATION) {
block_en = flags & MLXBF_I2C_F_SMBUS_BLOCK;
pec_en = flags & MLXBF_I2C_F_SMBUS_PEC;
}
if (flags & MLXBF_I2C_F_WRITE) {
write_en = 1;
write_len += operation->length;
memcpy(data_desc + data_idx,
operation->buffer, operation->length);
data_idx += operation->length;
}
/*
* We assume that read operations are performed only once per
* SMBus transaction. *TBD* protect this statement so it won't
* be executed twice? or return an error if we try to read more
* than once?
*/
if (flags & MLXBF_I2C_F_READ) {
read_en = 1;
/* Subtract 1 as required by HW. */
read_len = operation->length - 1;
read_buf = operation->buffer;
}
}
/* Set Master GW data descriptor. */
data_len = write_len + 1; /* Add one byte of the slave address. */
/*
* Note that data_len cannot be 0. Indeed, the slave address byte
* must be written to the data registers.
*/
mlxbf_i2c_smbus_write_data(priv, (const u8 *)data_desc, data_len,
MLXBF_I2C_MASTER_DATA_DESC_ADDR);
if (write_en) {
ret = mlxbf_i2c_smbus_enable(priv, slave, write_len, block_en,
pec_en, 0);
if (ret)
return ret;
}
if (read_en) {
/* Write slave address to Master GW data descriptor. */
mlxbf_i2c_smbus_write_data(priv, (const u8 *)&addr, 1,
MLXBF_I2C_MASTER_DATA_DESC_ADDR);
ret = mlxbf_i2c_smbus_enable(priv, slave, read_len, block_en,
pec_en, 1);
if (!ret) {
/* Get Master GW data descriptor. */
mlxbf_i2c_smbus_read_data(priv, data_desc, read_len + 1,
MLXBF_I2C_MASTER_DATA_DESC_ADDR);
/* Get data from Master GW data descriptor. */
memcpy(read_buf, data_desc, read_len + 1);
}
/*
* After a read operation the SMBus FSM ps (present state)
* needs to be 'manually' reset. This should be removed in
* next tag integration.
*/
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_FSM,
MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK);
}
return ret;
}
/* I2C SMBus protocols. */
static void
mlxbf_i2c_smbus_quick_command(struct mlxbf_i2c_smbus_request *request,
u8 read)
{
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_1;
request->operation[0].length = 0;
request->operation[0].flags = MLXBF_I2C_F_WRITE;
request->operation[0].flags |= read ? MLXBF_I2C_F_READ : 0;
}
static void mlxbf_i2c_smbus_byte_func(struct mlxbf_i2c_smbus_request *request,
u8 *data, bool read, bool pec_check)
{
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_1;
request->operation[0].length = 1;
request->operation[0].length += pec_check;
request->operation[0].flags = MLXBF_I2C_F_SMBUS_OPERATION;
request->operation[0].flags |= read ?
MLXBF_I2C_F_READ : MLXBF_I2C_F_WRITE;
request->operation[0].flags |= pec_check ? MLXBF_I2C_F_SMBUS_PEC : 0;
request->operation[0].buffer = data;
}
static void
mlxbf_i2c_smbus_data_byte_func(struct mlxbf_i2c_smbus_request *request,
u8 *command, u8 *data, bool read, bool pec_check)
{
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_2;
request->operation[0].length = 1;
request->operation[0].flags =
MLXBF_I2C_F_SMBUS_OPERATION | MLXBF_I2C_F_WRITE;
request->operation[0].flags |= pec_check ? MLXBF_I2C_F_SMBUS_PEC : 0;
request->operation[0].buffer = command;
request->operation[1].length = 1;
request->operation[1].length += pec_check;
request->operation[1].flags = read ?
MLXBF_I2C_F_READ : MLXBF_I2C_F_WRITE;
request->operation[1].buffer = data;
}
static void
mlxbf_i2c_smbus_data_word_func(struct mlxbf_i2c_smbus_request *request,
u8 *command, u8 *data, bool read, bool pec_check)
{
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_2;
request->operation[0].length = 1;
request->operation[0].flags =
MLXBF_I2C_F_SMBUS_OPERATION | MLXBF_I2C_F_WRITE;
request->operation[0].flags |= pec_check ? MLXBF_I2C_F_SMBUS_PEC : 0;
request->operation[0].buffer = command;
request->operation[1].length = 2;
request->operation[1].length += pec_check;
request->operation[1].flags = read ?
MLXBF_I2C_F_READ : MLXBF_I2C_F_WRITE;
request->operation[1].buffer = data;
}
static void
mlxbf_i2c_smbus_i2c_block_func(struct mlxbf_i2c_smbus_request *request,
u8 *command, u8 *data, u8 *data_len, bool read,
bool pec_check)
{
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_2;
request->operation[0].length = 1;
request->operation[0].flags =
MLXBF_I2C_F_SMBUS_OPERATION | MLXBF_I2C_F_WRITE;
request->operation[0].flags |= pec_check ? MLXBF_I2C_F_SMBUS_PEC : 0;
request->operation[0].buffer = command;
/*
* As specified in the standard, the max number of bytes to read/write
* per block operation is 32 bytes. In Golan code, the controller can
* read up to 128 bytes and write up to 127 bytes.
*/
request->operation[1].length =
(*data_len + pec_check > I2C_SMBUS_BLOCK_MAX) ?
I2C_SMBUS_BLOCK_MAX : *data_len + pec_check;
request->operation[1].flags = read ?
MLXBF_I2C_F_READ : MLXBF_I2C_F_WRITE;
/*
* Skip the first data byte, which corresponds to the number of bytes
* to read/write.
*/
request->operation[1].buffer = data + 1;
*data_len = request->operation[1].length;
/* Set the number of byte to read. This will be used by userspace. */
if (read)
data[0] = *data_len;
}
static void mlxbf_i2c_smbus_block_func(struct mlxbf_i2c_smbus_request *request,
u8 *command, u8 *data, u8 *data_len,
bool read, bool pec_check)
{
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_2;
request->operation[0].length = 1;
request->operation[0].flags =
MLXBF_I2C_F_SMBUS_OPERATION | MLXBF_I2C_F_WRITE;
request->operation[0].flags |= MLXBF_I2C_F_SMBUS_BLOCK;
request->operation[0].flags |= pec_check ? MLXBF_I2C_F_SMBUS_PEC : 0;
request->operation[0].buffer = command;
request->operation[1].length =
(*data_len + pec_check > I2C_SMBUS_BLOCK_MAX) ?
I2C_SMBUS_BLOCK_MAX : *data_len + pec_check;
request->operation[1].flags = read ?
MLXBF_I2C_F_READ : MLXBF_I2C_F_WRITE;
request->operation[1].buffer = data + 1;
*data_len = request->operation[1].length;
/* Set the number of bytes to read. This will be used by userspace. */
if (read)
data[0] = *data_len;
}
static void
mlxbf_i2c_smbus_process_call_func(struct mlxbf_i2c_smbus_request *request,
u8 *command, u8 *data, bool pec_check)
{
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_3;
request->operation[0].length = 1;
request->operation[0].flags =
MLXBF_I2C_F_SMBUS_OPERATION | MLXBF_I2C_F_WRITE;
request->operation[0].flags |= MLXBF_I2C_F_SMBUS_BLOCK;
request->operation[0].flags |= pec_check ? MLXBF_I2C_F_SMBUS_PEC : 0;
request->operation[0].buffer = command;
request->operation[1].length = 2;
request->operation[1].flags = MLXBF_I2C_F_WRITE;
request->operation[1].buffer = data;
request->operation[2].length = 3;
request->operation[2].flags = MLXBF_I2C_F_READ;
request->operation[2].buffer = data;
}
static void
mlxbf_i2c_smbus_blk_process_call_func(struct mlxbf_i2c_smbus_request *request,
u8 *command, u8 *data, u8 *data_len,
bool pec_check)
{
u32 length;
request->operation_cnt = MLXBF_I2C_SMBUS_OP_CNT_3;
request->operation[0].length = 1;
request->operation[0].flags =
MLXBF_I2C_F_SMBUS_OPERATION | MLXBF_I2C_F_WRITE;
request->operation[0].flags |= MLXBF_I2C_F_SMBUS_BLOCK;
request->operation[0].flags |= (pec_check) ? MLXBF_I2C_F_SMBUS_PEC : 0;
request->operation[0].buffer = command;
length = (*data_len + pec_check > I2C_SMBUS_BLOCK_MAX) ?
I2C_SMBUS_BLOCK_MAX : *data_len + pec_check;
request->operation[1].length = length - pec_check;
request->operation[1].flags = MLXBF_I2C_F_WRITE;
request->operation[1].buffer = data;
request->operation[2].length = length;
request->operation[2].flags = MLXBF_I2C_F_READ;
request->operation[2].buffer = data;
*data_len = length; /* including PEC byte. */
}
/* Initialization functions. */
static bool mlxbf_i2c_has_chip_type(struct mlxbf_i2c_priv *priv, u8 type)
{
return priv->chip->type == type;
}
static struct mlxbf_i2c_resource *
mlxbf_i2c_get_shared_resource(struct mlxbf_i2c_priv *priv, u8 type)
{
const struct mlxbf_i2c_chip_info *chip = priv->chip;
struct mlxbf_i2c_resource *res;
u8 res_idx = 0;
for (res_idx = 0; res_idx < MLXBF_I2C_SHARED_RES_MAX; res_idx++) {
res = chip->shared_res[res_idx];
if (res && res->type == type)
return res;
}
return NULL;
}
static int mlxbf_i2c_init_resource(struct platform_device *pdev,
struct mlxbf_i2c_resource **res,
u8 type)
{
struct mlxbf_i2c_resource *tmp_res;
struct device *dev = &pdev->dev;
if (!res || *res || type >= MLXBF_I2C_END_RES)
return -EINVAL;
tmp_res = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_resource),
GFP_KERNEL);
if (!tmp_res)
return -ENOMEM;
tmp_res->params = platform_get_resource(pdev, IORESOURCE_MEM, type);
if (!tmp_res->params) {
devm_kfree(dev, tmp_res);
return -EIO;
}
tmp_res->io = devm_ioremap_resource(dev, tmp_res->params);
if (IS_ERR(tmp_res->io)) {
devm_kfree(dev, tmp_res);
return PTR_ERR(tmp_res->io);
}
tmp_res->type = type;
*res = tmp_res;
return 0;
}
static u32 mlxbf_i2c_get_ticks(struct mlxbf_i2c_priv *priv, u64 nanoseconds,
bool minimum)
{
u64 frequency;
u32 ticks;
/*
* Compute ticks as follow:
*
* Ticks
* Time = --------- x 10^9 => Ticks = Time x Frequency x 10^-9
* Frequency
*/
frequency = priv->frequency;
ticks = (nanoseconds * frequency) / MLXBF_I2C_FREQUENCY_1GHZ;
/*
* The number of ticks is rounded down and if minimum is equal to 1
* then add one tick.
*/
if (minimum)
ticks++;
return ticks;
}
static u32 mlxbf_i2c_set_timer(struct mlxbf_i2c_priv *priv, u64 nsec, bool opt,
u32 mask, u8 shift)
{
u32 val = (mlxbf_i2c_get_ticks(priv, nsec, opt) & mask) << shift;
return val;
}
static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv,
const struct mlxbf_i2c_timings *timings)
{
u32 timer;
timer = mlxbf_i2c_set_timer(priv, timings->scl_high,
false, MLXBF_I2C_MASK_16,
MLXBF_I2C_SHIFT_0);
timer |= mlxbf_i2c_set_timer(priv, timings->scl_low,
false, MLXBF_I2C_MASK_16,
MLXBF_I2C_SHIFT_16);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH,
timer);
timer = mlxbf_i2c_set_timer(priv, timings->sda_rise, false,
MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_0);
timer |= mlxbf_i2c_set_timer(priv, timings->sda_fall, false,
MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_8);
timer |= mlxbf_i2c_set_timer(priv, timings->scl_rise, false,
MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_16);
timer |= mlxbf_i2c_set_timer(priv, timings->scl_fall, false,
MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_24);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE,
timer);
timer = mlxbf_i2c_set_timer(priv, timings->hold_start, true,
MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
timer |= mlxbf_i2c_set_timer(priv, timings->hold_data, true,
MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_THOLD, timer);
timer = mlxbf_i2c_set_timer(priv, timings->setup_start, true,
MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
timer |= mlxbf_i2c_set_timer(priv, timings->setup_stop, true,
MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
mlxbf_i2c_write(priv->smbus->io,
MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP, timer);
timer = mlxbf_i2c_set_timer(priv, timings->setup_data, true,
MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA,
timer);
timer = mlxbf_i2c_set_timer(priv, timings->buf, false,
MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);
timer |= mlxbf_i2c_set_timer(priv, timings->thigh_max, false,
MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_THIGH_MAX_TBUF,
timer);
timer = timings->timeout;
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT,
timer);
}
enum mlxbf_i2c_timings_config {
MLXBF_I2C_TIMING_CONFIG_100KHZ,
MLXBF_I2C_TIMING_CONFIG_400KHZ,
MLXBF_I2C_TIMING_CONFIG_1000KHZ,
};
/*
* Note that the mlxbf_i2c_timings->timeout value is not related to the
* bus frequency, it is impacted by the time it takes the driver to
* complete data transmission before transaction abort.
*/
static const struct mlxbf_i2c_timings mlxbf_i2c_timings[] = {
[MLXBF_I2C_TIMING_CONFIG_100KHZ] = {
.scl_high = 4810,
.scl_low = 5000,
.hold_start = 4000,
.setup_start = 4800,
.setup_stop = 4000,
.setup_data = 250,
.sda_rise = 50,
.sda_fall = 50,
.scl_rise = 50,
.scl_fall = 50,
.hold_data = 300,
.buf = 20000,
.thigh_max = 5000,
.timeout = 106500
},
[MLXBF_I2C_TIMING_CONFIG_400KHZ] = {
.scl_high = 1011,
.scl_low = 1300,
.hold_start = 600,
.setup_start = 700,
.setup_stop = 600,
.setup_data = 100,
.sda_rise = 50,
.sda_fall = 50,
.scl_rise = 50,
.scl_fall = 50,
.hold_data = 300,
.buf = 20000,
.thigh_max = 5000,
.timeout = 106500
},
[MLXBF_I2C_TIMING_CONFIG_1000KHZ] = {
.scl_high = 600,
.scl_low = 1300,
.hold_start = 600,
.setup_start = 600,
.setup_stop = 600,
.setup_data = 100,
.sda_rise = 50,
.sda_fall = 50,
.scl_rise = 50,
.scl_fall = 50,
.hold_data = 300,
.buf = 20000,
.thigh_max = 5000,
.timeout = 106500
}
};
static int mlxbf_i2c_init_timings(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
enum mlxbf_i2c_timings_config config_idx;
struct device *dev = &pdev->dev;
u32 config_khz;
int ret;
ret = device_property_read_u32(dev, "clock-frequency", &config_khz);
if (ret < 0)
config_khz = MLXBF_I2C_TIMING_100KHZ;
switch (config_khz) {
default:
/* Default settings is 100 KHz. */
pr_warn("Illegal value %d: defaulting to 100 KHz\n",
config_khz);
fallthrough;
case MLXBF_I2C_TIMING_100KHZ:
config_idx = MLXBF_I2C_TIMING_CONFIG_100KHZ;
break;
case MLXBF_I2C_TIMING_400KHZ:
config_idx = MLXBF_I2C_TIMING_CONFIG_400KHZ;
break;
case MLXBF_I2C_TIMING_1000KHZ:
config_idx = MLXBF_I2C_TIMING_CONFIG_1000KHZ;
break;
}
mlxbf_i2c_set_timings(priv, &mlxbf_i2c_timings[config_idx]);
return 0;
}
static int mlxbf_i2c_get_gpio(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct mlxbf_i2c_resource *gpio_res;
struct device *dev = &pdev->dev;
struct resource *params;
resource_size_t size;
gpio_res = mlxbf_i2c_get_shared_resource(priv, MLXBF_I2C_GPIO_RES);
if (!gpio_res)
return -EPERM;
/*
* The GPIO region in TYU space is shared among I2C busses.
* This function MUST be serialized to avoid racing when
* claiming the memory region and/or setting up the GPIO.
*/
lockdep_assert_held(gpio_res->lock);
/* Check whether the memory map exist. */
if (gpio_res->io)
return 0;
params = gpio_res->params;
size = resource_size(params);
if (!devm_request_mem_region(dev, params->start, size, params->name))
return -EFAULT;
gpio_res->io = devm_ioremap(dev, params->start, size);
if (IS_ERR(gpio_res->io)) {
devm_release_mem_region(dev, params->start, size);
return PTR_ERR(gpio_res->io);
}
return 0;
}
static int mlxbf_i2c_release_gpio(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct mlxbf_i2c_resource *gpio_res;
struct device *dev = &pdev->dev;
struct resource *params;
gpio_res = mlxbf_i2c_get_shared_resource(priv, MLXBF_I2C_GPIO_RES);
if (!gpio_res)
return 0;
mutex_lock(gpio_res->lock);
if (gpio_res->io) {
/* Release the GPIO resource. */
params = gpio_res->params;
devm_iounmap(dev, gpio_res->io);
devm_release_mem_region(dev, params->start,
resource_size(params));
}
mutex_unlock(gpio_res->lock);
return 0;
}
static int mlxbf_i2c_get_corepll(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct mlxbf_i2c_resource *corepll_res;
struct device *dev = &pdev->dev;
struct resource *params;
resource_size_t size;
corepll_res = mlxbf_i2c_get_shared_resource(priv,
MLXBF_I2C_COREPLL_RES);
if (!corepll_res)
return -EPERM;
/*
* The COREPLL region in TYU space is shared among I2C busses.
* This function MUST be serialized to avoid racing when
* claiming the memory region.
*/
lockdep_assert_held(corepll_res->lock);
/* Check whether the memory map exist. */
if (corepll_res->io)
return 0;
params = corepll_res->params;
size = resource_size(params);
if (!devm_request_mem_region(dev, params->start, size, params->name))
return -EFAULT;
corepll_res->io = devm_ioremap(dev, params->start, size);
if (IS_ERR(corepll_res->io)) {
devm_release_mem_region(dev, params->start, size);
return PTR_ERR(corepll_res->io);
}
return 0;
}
static int mlxbf_i2c_release_corepll(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct mlxbf_i2c_resource *corepll_res;
struct device *dev = &pdev->dev;
struct resource *params;
corepll_res = mlxbf_i2c_get_shared_resource(priv,
MLXBF_I2C_COREPLL_RES);
mutex_lock(corepll_res->lock);
if (corepll_res->io) {
/* Release the CorePLL resource. */
params = corepll_res->params;
devm_iounmap(dev, corepll_res->io);
devm_release_mem_region(dev, params->start,
resource_size(params));
}
mutex_unlock(corepll_res->lock);
return 0;
}
static int mlxbf_i2c_init_master(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct mlxbf_i2c_resource *gpio_res;
struct device *dev = &pdev->dev;
u32 config_reg;
int ret;
/* This configuration is only needed for BlueField 1. */
if (!mlxbf_i2c_has_chip_type(priv, MLXBF_I2C_CHIP_TYPE_1))
return 0;
gpio_res = mlxbf_i2c_get_shared_resource(priv, MLXBF_I2C_GPIO_RES);
if (!gpio_res)
return -EPERM;
/*
* The GPIO region in TYU space is shared among I2C busses.
* This function MUST be serialized to avoid racing when
* claiming the memory region and/or setting up the GPIO.
*/
mutex_lock(gpio_res->lock);
ret = mlxbf_i2c_get_gpio(pdev, priv);
if (ret < 0) {
dev_err(dev, "Failed to get gpio resource");
mutex_unlock(gpio_res->lock);
return ret;
}
/*
* TYU - Configuration for GPIO pins. Those pins must be asserted in
* MLXBF_I2C_GPIO_0_FUNC_EN_0, i.e. GPIO 0 is controlled by HW, and must
* be reset in MLXBF_I2C_GPIO_0_FORCE_OE_EN, i.e. GPIO_OE will be driven
* instead of HW_OE.
* For now, we do not reset the GPIO state when the driver is removed.
* First, it is not necessary to disable the bus since we are using
* the same busses. Then, some busses might be shared among Linux and
* platform firmware; disabling the bus might compromise the system
* functionality.
*/
config_reg = mlxbf_i2c_read(gpio_res->io,
MLXBF_I2C_GPIO_0_FUNC_EN_0);
config_reg = MLXBF_I2C_GPIO_SMBUS_GW_ASSERT_PINS(priv->bus,
config_reg);
mlxbf_i2c_write(gpio_res->io, MLXBF_I2C_GPIO_0_FUNC_EN_0,
config_reg);
config_reg = mlxbf_i2c_read(gpio_res->io,
MLXBF_I2C_GPIO_0_FORCE_OE_EN);
config_reg = MLXBF_I2C_GPIO_SMBUS_GW_RESET_PINS(priv->bus,
config_reg);
mlxbf_i2c_write(gpio_res->io, MLXBF_I2C_GPIO_0_FORCE_OE_EN,
config_reg);
mutex_unlock(gpio_res->lock);
return 0;
}
static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)
{
u64 core_frequency, pad_frequency;
u8 core_od, core_r;
u32 corepll_val;
u16 core_f;
pad_frequency = MLXBF_I2C_TYU_PLL_IN_FREQ;
corepll_val = mlxbf_i2c_read(corepll_res->io,
MLXBF_I2C_CORE_PLL_REG1);
/* Get Core PLL configuration bits. */
core_f = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_F_TYU_MASK;
core_od = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_OD_TYU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK;
core_r = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_R_TYU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_R_TYU_MASK;
/*
* Compute PLL output frequency as follow:
*
* CORE_F + 1
* PLL_OUT_FREQ = PLL_IN_FREQ * ----------------------------
* (CORE_R + 1) * (CORE_OD + 1)
*
* Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency
* and PadFrequency, respectively.
*/
core_frequency = pad_frequency * (++core_f);
core_frequency /= (++core_r) * (++core_od);
return core_frequency;
}
static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)
{
u32 corepll_reg1_val, corepll_reg2_val;
u64 corepll_frequency, pad_frequency;
u8 core_od, core_r;
u32 core_f;
pad_frequency = MLXBF_I2C_YU_PLL_IN_FREQ;
corepll_reg1_val = mlxbf_i2c_read(corepll_res->io,
MLXBF_I2C_CORE_PLL_REG1);
corepll_reg2_val = mlxbf_i2c_read(corepll_res->io,
MLXBF_I2C_CORE_PLL_REG2);
/* Get Core PLL configuration bits */
core_f = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_F_YU_MASK;
core_r = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_R_YU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_R_YU_MASK;
core_od = rol32(corepll_reg2_val, MLXBF_I2C_COREPLL_CORE_OD_YU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_OD_YU_MASK;
/*
* Compute PLL output frequency as follow:
*
* CORE_F / 16384
* PLL_OUT_FREQ = PLL_IN_FREQ * ----------------------------
* (CORE_R + 1) * (CORE_OD + 1)
*
* Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency
* and PadFrequency, respectively.
*/
corepll_frequency = (pad_frequency * core_f) / MLNXBF_I2C_COREPLL_CONST;
corepll_frequency /= (++core_r) * (++core_od);
return corepll_frequency;
}
static int mlxbf_i2c_calculate_corepll_freq(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
const struct mlxbf_i2c_chip_info *chip = priv->chip;
struct mlxbf_i2c_resource *corepll_res;
struct device *dev = &pdev->dev;
u64 *freq = &priv->frequency;
int ret;
corepll_res = mlxbf_i2c_get_shared_resource(priv,
MLXBF_I2C_COREPLL_RES);
if (!corepll_res)
return -EPERM;
/*
* First, check whether the TYU core Clock frequency is set.
* The TYU core frequency is the same for all I2C busses; when
* the first device gets probed the frequency is determined and
* stored into a globally visible variable. So, first of all,
* check whether the frequency is already set. Here, we assume
* that the frequency is expected to be greater than 0.
*/
mutex_lock(corepll_res->lock);
if (!mlxbf_i2c_corepll_frequency) {
if (!chip->calculate_freq) {
mutex_unlock(corepll_res->lock);
return -EPERM;
}
ret = mlxbf_i2c_get_corepll(pdev, priv);
if (ret < 0) {
dev_err(dev, "Failed to get corePLL resource");
mutex_unlock(corepll_res->lock);
return ret;
}
mlxbf_i2c_corepll_frequency = chip->calculate_freq(corepll_res);
}
mutex_unlock(corepll_res->lock);
*freq = mlxbf_i2c_corepll_frequency;
return 0;
}
static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr)
{
u32 slave_reg, slave_reg_tmp, slave_reg_avail, slave_addr_mask;
u8 reg, reg_cnt, byte, addr_tmp, reg_avail, byte_avail;
bool avail, disabled;
disabled = false;
avail = false;
if (!priv)
return -EPERM;
reg_cnt = MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT >> 2;
slave_addr_mask = MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK;
/*
* Read the slave registers. There are 4 * 32-bit slave registers.
* Each slave register can hold up to 4 * 8-bit slave configuration
* (7-bit address, 1 status bit (1 if enabled, 0 if not)).
*/
for (reg = 0; reg < reg_cnt; reg++) {
slave_reg = mlxbf_i2c_read(priv->smbus->io,
MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);
/*
* Each register holds 4 slave addresses. So, we have to keep
* the byte order consistent with the value read in order to
* update the register correctly, if needed.
*/
slave_reg_tmp = slave_reg;
for (byte = 0; byte < 4; byte++) {
addr_tmp = slave_reg_tmp & GENMASK(7, 0);
/*
* Mark the first available slave address slot, i.e. its
* enabled bit should be unset. This slot might be used
* later on to register our slave.
*/
if (!avail && !MLXBF_I2C_SLAVE_ADDR_ENABLED(addr_tmp)) {
avail = true;
reg_avail = reg;
byte_avail = byte;
slave_reg_avail = slave_reg;
}
/*
* Parse slave address bytes and check whether the
* slave address already exists and it's enabled,
* i.e. most significant bit is set.
*/
if ((addr_tmp & slave_addr_mask) == addr) {
if (MLXBF_I2C_SLAVE_ADDR_ENABLED(addr_tmp))
return 0;
disabled = true;
break;
}
/* Parse next byte. */
slave_reg_tmp >>= 8;
}
/* Exit the loop if the slave address is found. */
if (disabled)
break;
}
if (!avail && !disabled)
return -EINVAL; /* No room for a new slave address. */
if (avail && !disabled) {
reg = reg_avail;
byte = byte_avail;
/* Set the slave address. */
slave_reg_avail &= ~(slave_addr_mask << (byte * 8));
slave_reg_avail |= addr << (byte * 8);
slave_reg = slave_reg_avail;
}
/* Enable the slave address and update the register. */
slave_reg |= (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT) << (byte * 8);
mlxbf_i2c_write(priv->smbus->io,
MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4, slave_reg);
return 0;
}
static int mlxbf_slave_disable(struct mlxbf_i2c_priv *priv)
{
u32 slave_reg, slave_reg_tmp, slave_addr_mask;
u8 addr, addr_tmp, reg, reg_cnt, slave_byte;
struct i2c_client *client = priv->slave;
bool exist;
exist = false;
addr = client->addr;
reg_cnt = MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT >> 2;
slave_addr_mask = MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK;
/*
* Read the slave registers. There are 4 * 32-bit slave registers.
* Each slave register can hold up to 4 * 8-bit slave configuration
* (7-bit address, 1 status bit (1 if enabled, 0 if not)).
*/
for (reg = 0; reg < reg_cnt; reg++) {
slave_reg = mlxbf_i2c_read(priv->smbus->io,
MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);
/* Check whether the address slots are empty. */
if (slave_reg == 0)
continue;
/*
* Each register holds 4 slave addresses. So, we have to keep
* the byte order consistent with the value read in order to
* update the register correctly, if needed.
*/
slave_reg_tmp = slave_reg;
slave_byte = 0;
while (slave_reg_tmp != 0) {
addr_tmp = slave_reg_tmp & slave_addr_mask;
/*
* Parse slave address bytes and check whether the
* slave address already exists.
*/
if (addr_tmp == addr) {
exist = true;
break;
}
/* Parse next byte. */
slave_reg_tmp >>= 8;
slave_byte += 1;
}
/* Exit the loop if the slave address is found. */
if (exist)
break;
}
if (!exist)
return 0; /* Slave is not registered, nothing to do. */
/* Cleanup the slave address slot. */
slave_reg &= ~(GENMASK(7, 0) << (slave_byte * 8));
mlxbf_i2c_write(priv->smbus->io,
MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4, slave_reg);
return 0;
}
static int mlxbf_i2c_init_coalesce(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct mlxbf_i2c_resource *coalesce_res;
struct resource *params;
resource_size_t size;
int ret = 0;
/*
* Unlike BlueField-1 platform, the coalesce registers is a dedicated
* resource in the next generations of BlueField.
*/
if (mlxbf_i2c_has_chip_type(priv, MLXBF_I2C_CHIP_TYPE_1)) {
coalesce_res = mlxbf_i2c_get_shared_resource(priv,
MLXBF_I2C_COALESCE_RES);
if (!coalesce_res)
return -EPERM;
/*
* The Cause Coalesce group in TYU space is shared among
* I2C busses. This function MUST be serialized to avoid
* racing when claiming the memory region.
*/
lockdep_assert_held(mlxbf_i2c_gpio_res->lock);
/* Check whether the memory map exist. */
if (coalesce_res->io) {
priv->coalesce = coalesce_res;
return 0;
}
params = coalesce_res->params;
size = resource_size(params);
if (!request_mem_region(params->start, size, params->name))
return -EFAULT;
coalesce_res->io = ioremap(params->start, size);
if (IS_ERR(coalesce_res->io)) {
release_mem_region(params->start, size);
return PTR_ERR(coalesce_res->io);
}
priv->coalesce = coalesce_res;
} else {
ret = mlxbf_i2c_init_resource(pdev, &priv->coalesce,
MLXBF_I2C_COALESCE_RES);
}
return ret;
}
static int mlxbf_i2c_release_coalesce(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct mlxbf_i2c_resource *coalesce_res;
struct device *dev = &pdev->dev;
struct resource *params;
resource_size_t size;
coalesce_res = priv->coalesce;
if (coalesce_res->io) {
params = coalesce_res->params;
size = resource_size(params);
if (mlxbf_i2c_has_chip_type(priv, MLXBF_I2C_CHIP_TYPE_1)) {
mutex_lock(coalesce_res->lock);
iounmap(coalesce_res->io);
release_mem_region(params->start, size);
mutex_unlock(coalesce_res->lock);
} else {
devm_release_mem_region(dev, params->start, size);
}
}
return 0;
}
static int mlxbf_i2c_init_slave(struct platform_device *pdev,
struct mlxbf_i2c_priv *priv)
{
struct device *dev = &pdev->dev;
u32 int_reg;
int ret;
/* Reset FSM. */
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_FSM, 0);
/*
* Enable slave cause interrupt bits. Drive
* MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE and
* MLXBF_I2C_CAUSE_WRITE_SUCCESS, these are enabled when an external
* masters issue a Read and Write, respectively. But, clear all
* interrupts first.
*/
mlxbf_i2c_write(priv->slv_cause->io,
MLXBF_I2C_CAUSE_OR_CLEAR, ~0);
int_reg = MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE;
int_reg |= MLXBF_I2C_CAUSE_WRITE_SUCCESS;
mlxbf_i2c_write(priv->slv_cause->io,
MLXBF_I2C_CAUSE_OR_EVTEN0, int_reg);
/* Finally, set the 'ready' bit to start handling transactions. */
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1);
/* Initialize the cause coalesce resource. */
ret = mlxbf_i2c_init_coalesce(pdev, priv);
if (ret < 0) {
dev_err(dev, "failed to initialize cause coalesce\n");
return ret;
}
return 0;
}
static bool mlxbf_i2c_has_coalesce(struct mlxbf_i2c_priv *priv, bool *read,
bool *write)
{
const struct mlxbf_i2c_chip_info *chip = priv->chip;
u32 coalesce0_reg, cause_reg;
u8 slave_shift, is_set;
*write = false;
*read = false;
slave_shift = chip->type != MLXBF_I2C_CHIP_TYPE_1 ?
MLXBF_I2C_CAUSE_YU_SLAVE_BIT :
priv->bus + MLXBF_I2C_CAUSE_TYU_SLAVE_BIT;
coalesce0_reg = mlxbf_i2c_read(priv->coalesce->io,
MLXBF_I2C_CAUSE_COALESCE_0);
is_set = coalesce0_reg & (1 << slave_shift);
if (!is_set)
return false;
/* Check the source of the interrupt, i.e. whether a Read or Write. */
cause_reg = mlxbf_i2c_read(priv->slv_cause->io,
MLXBF_I2C_CAUSE_ARBITER);
if (cause_reg & MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE)
*read = true;
else if (cause_reg & MLXBF_I2C_CAUSE_WRITE_SUCCESS)
*write = true;
/* Clear cause bits. */
mlxbf_i2c_write(priv->slv_cause->io, MLXBF_I2C_CAUSE_OR_CLEAR, ~0x0);
return true;
}
static bool mlxbf_smbus_slave_wait_for_idle(struct mlxbf_i2c_priv *priv,
u32 timeout)
{
u32 mask = MLXBF_I2C_CAUSE_S_GW_BUSY_FALL;
u32 addr = MLXBF_I2C_CAUSE_ARBITER;
if (mlxbf_smbus_poll(priv->slv_cause->io, addr, mask, false, timeout))
return true;
return false;
}
/* Send byte to 'external' smbus master. */
static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
{
u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 };
u8 write_size, pec_en, addr, byte, value, byte_cnt, desc_size;
struct i2c_client *slave = priv->slave;
u32 control32, data32;
int ret;
if (!slave)
return -EINVAL;
addr = 0;
byte = 0;
desc_size = MLXBF_I2C_SLAVE_DATA_DESC_SIZE;
/*
* Read bytes received from the external master. These bytes should
* be located in the first data descriptor register of the slave GW.
* These bytes are the slave address byte and the internal register
* address, if supplied.
*/
if (recv_bytes > 0) {
data32 = mlxbf_i2c_read_data(priv->smbus->io,
MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
/* Parse the received bytes. */
switch (recv_bytes) {
case 2:
byte = (data32 >> 8) & GENMASK(7, 0);
fallthrough;
case 1:
addr = (data32 & GENMASK(7, 0)) >> 1;
}
/* Check whether it's our slave address. */
if (slave->addr != addr)
return -EINVAL;
}
/*
* I2C read transactions may start by a WRITE followed by a READ.
* Indeed, most slave devices would expect the internal address
* following the slave address byte. So, write that byte first,
* and then, send the requested data bytes to the master.
*/
if (recv_bytes > 1) {
i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
value = byte;
ret = i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED,
&value);
i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
if (ret < 0)
return ret;
}
/*
* Now, send data to the master; currently, the driver supports
* READ_BYTE, READ_WORD and BLOCK READ protocols. Note that the
* hardware can send up to 128 bytes per transfer. That is the
* size of its data registers.
*/
i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
for (byte_cnt = 0; byte_cnt < desc_size; byte_cnt++) {
data_desc[byte_cnt] = value;
i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value);
}
/* Send a stop condition to the backend. */
i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
/* Handle the actual transfer. */
/* Set the number of bytes to write to master. */
write_size = (byte_cnt - 1) & 0x7f;
/* Write data to Slave GW data descriptor. */
mlxbf_i2c_smbus_write_data(priv, data_desc, byte_cnt,
MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
pec_en = 0; /* Disable PEC since it is not supported. */
/* Prepare control word. */
control32 = MLXBF_I2C_SLAVE_ENABLE;
control32 |= rol32(write_size, MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT);
control32 |= rol32(pec_en, MLXBF_I2C_SLAVE_SEND_PEC_SHIFT);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_GW, control32);
/*
* Wait until the transfer is completed; the driver will wait
* until the GW is idle, a cause will rise on fall of GW busy.
*/
mlxbf_smbus_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT);
/* Release the Slave GW. */
mlxbf_i2c_write(priv->smbus->io,
MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES, 0x0);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_PEC, 0x0);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1);
return 0;
}
/* Receive bytes from 'external' smbus master. */
static int mlxbf_smbus_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
{
u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 };
struct i2c_client *slave = priv->slave;
u8 value, byte, addr;
int ret = 0;
if (!slave)
return -EINVAL;
/* Read data from Slave GW data descriptor. */
mlxbf_i2c_smbus_read_data(priv, data_desc, recv_bytes,
MLXBF_I2C_SLAVE_DATA_DESC_ADDR);
/* Check whether its our slave address. */
addr = data_desc[0] >> 1;
if (slave->addr != addr)
return -EINVAL;
/*
* Notify the slave backend; another I2C master wants to write data
* to us. This event is sent once the slave address and the write bit
* is detected.
*/
i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
/* Send the received data to the slave backend. */
for (byte = 1; byte < recv_bytes; byte++) {
value = data_desc[byte];
ret = i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED,
&value);
if (ret < 0)
break;
}
/* Send a stop condition to the backend. */
i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
/* Release the Slave GW. */
mlxbf_i2c_write(priv->smbus->io,
MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES, 0x0);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_PEC, 0x0);
mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1);
return ret;
}
static irqreturn_t mlxbf_smbus_irq(int irq, void *ptr)
{
struct mlxbf_i2c_priv *priv = ptr;
bool read, write, irq_is_set;
u32 rw_bytes_reg;
u8 recv_bytes;
/*
* Read TYU interrupt register and determine the source of the
* interrupt. Based on the source of the interrupt one of the
* following actions are performed:
* - Receive data and send response to master.
* - Send data and release slave GW.
*
* Handle read/write transaction only. CRmaster and Iarp requests
* are ignored for now.
*/
irq_is_set = mlxbf_i2c_has_coalesce(priv, &read, &write);
if (!irq_is_set || (!read && !write)) {
/* Nothing to do here, interrupt was not from this device. */
return IRQ_NONE;
}
/*
* The MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES includes the number of
* bytes from/to master. These are defined by 8-bits each. If the lower
* 8 bits are set, then the master expect to read N bytes from the
* slave, if the higher 8 bits are sent then the slave expect N bytes
* from the master.
*/
rw_bytes_reg = mlxbf_i2c_read(priv->smbus->io,
MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);
recv_bytes = (rw_bytes_reg >> 8) & GENMASK(7, 0);
/*
* For now, the slave supports 128 bytes transfer. Discard remaining
* data bytes if the master wrote more than
* MLXBF_I2C_SLAVE_DATA_DESC_SIZE, i.e, the actual size of the slave
* data descriptor.
*
* Note that we will never expect to transfer more than 128 bytes; as
* specified in the SMBus standard, block transactions cannot exceed
* 32 bytes.
*/
recv_bytes = recv_bytes > MLXBF_I2C_SLAVE_DATA_DESC_SIZE ?
MLXBF_I2C_SLAVE_DATA_DESC_SIZE : recv_bytes;
if (read)
mlxbf_smbus_irq_send(priv, recv_bytes);
else
mlxbf_smbus_irq_recv(priv, recv_bytes);
return IRQ_HANDLED;
}
/* Return negative errno on error. */
static s32 mlxbf_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data)
{
struct mlxbf_i2c_smbus_request request = { 0 };
struct mlxbf_i2c_priv *priv;
bool read, pec;
u8 byte_cnt;
request.slave = addr;
read = (read_write == I2C_SMBUS_READ);
pec = flags & I2C_FUNC_SMBUS_PEC;
switch (size) {
case I2C_SMBUS_QUICK:
mlxbf_i2c_smbus_quick_command(&request, read);
dev_dbg(&adap->dev, "smbus quick, slave 0x%02x\n", addr);
break;
case I2C_SMBUS_BYTE:
mlxbf_i2c_smbus_byte_func(&request,
read ? &data->byte : &command, read,
pec);
dev_dbg(&adap->dev, "smbus %s byte, slave 0x%02x.\n",
read ? "read" : "write", addr);
break;
case I2C_SMBUS_BYTE_DATA:
mlxbf_i2c_smbus_data_byte_func(&request, &command, &data->byte,
read, pec);
dev_dbg(&adap->dev, "smbus %s byte data at 0x%02x, slave 0x%02x.\n",
read ? "read" : "write", command, addr);
break;
case I2C_SMBUS_WORD_DATA:
mlxbf_i2c_smbus_data_word_func(&request, &command,
(u8 *)&data->word, read, pec);
dev_dbg(&adap->dev, "smbus %s word data at 0x%02x, slave 0x%02x.\n",
read ? "read" : "write", command, addr);
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
byte_cnt = data->block[0];
mlxbf_i2c_smbus_i2c_block_func(&request, &command, data->block,
&byte_cnt, read, pec);
dev_dbg(&adap->dev, "i2c %s block data, %d bytes at 0x%02x, slave 0x%02x.\n",
read ? "read" : "write", byte_cnt, command, addr);
break;
case I2C_SMBUS_BLOCK_DATA:
byte_cnt = read ? I2C_SMBUS_BLOCK_MAX : data->block[0];
mlxbf_i2c_smbus_block_func(&request, &command, data->block,
&byte_cnt, read, pec);
dev_dbg(&adap->dev, "smbus %s block data, %d bytes at 0x%02x, slave 0x%02x.\n",
read ? "read" : "write", byte_cnt, command, addr);
break;
case I2C_FUNC_SMBUS_PROC_CALL:
mlxbf_i2c_smbus_process_call_func(&request, &command,
(u8 *)&data->word, pec);
dev_dbg(&adap->dev, "process call, wr/rd at 0x%02x, slave 0x%02x.\n",
command, addr);
break;
case I2C_FUNC_SMBUS_BLOCK_PROC_CALL:
byte_cnt = data->block[0];
mlxbf_i2c_smbus_blk_process_call_func(&request, &command,
data->block, &byte_cnt,
pec);
dev_dbg(&adap->dev, "block process call, wr/rd %d bytes, slave 0x%02x.\n",
byte_cnt, addr);
break;
default:
dev_dbg(&adap->dev, "Unsupported I2C/SMBus command %d\n",
size);
return -EOPNOTSUPP;
}
priv = i2c_get_adapdata(adap);
return mlxbf_i2c_smbus_start_transaction(priv, &request);
}
static int mlxbf_i2c_reg_slave(struct i2c_client *slave)
{
struct mlxbf_i2c_priv *priv = i2c_get_adapdata(slave->adapter);
int ret;
if (priv->slave)
return -EBUSY;
/*
* Do not support ten bit chip address and do not use Packet Error
* Checking (PEC).
*/
if (slave->flags & (I2C_CLIENT_TEN | I2C_CLIENT_PEC))
return -EAFNOSUPPORT;
ret = mlxbf_slave_enable(priv, slave->addr);
if (ret < 0)
return ret;
priv->slave = slave;
return 0;
}
static int mlxbf_i2c_unreg_slave(struct i2c_client *slave)
{
struct mlxbf_i2c_priv *priv = i2c_get_adapdata(slave->adapter);
int ret;
WARN_ON(!priv->slave);
/* Unregister slave, i.e. disable the slave address in hardware. */
ret = mlxbf_slave_disable(priv);
if (ret < 0)
return ret;
priv->slave = NULL;
return 0;
}
static u32 mlxbf_i2c_functionality(struct i2c_adapter *adap)
{
return MLXBF_I2C_FUNC_ALL;
}
static struct mlxbf_i2c_chip_info mlxbf_i2c_chip[] = {
[MLXBF_I2C_CHIP_TYPE_1] = {
.type = MLXBF_I2C_CHIP_TYPE_1,
.shared_res = {
[0] = &mlxbf_i2c_coalesce_res[MLXBF_I2C_CHIP_TYPE_1],
[1] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_1],
[2] = &mlxbf_i2c_gpio_res[MLXBF_I2C_CHIP_TYPE_1]
},
.calculate_freq = mlxbf_calculate_freq_from_tyu
},
[MLXBF_I2C_CHIP_TYPE_2] = {
.type = MLXBF_I2C_CHIP_TYPE_2,
.shared_res = {
[0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_2]
},
.calculate_freq = mlxbf_calculate_freq_from_yu
}
};
static const struct i2c_algorithm mlxbf_i2c_algo = {
.smbus_xfer = mlxbf_i2c_smbus_xfer,
.functionality = mlxbf_i2c_functionality,
.reg_slave = mlxbf_i2c_reg_slave,
.unreg_slave = mlxbf_i2c_unreg_slave,
};
static struct i2c_adapter_quirks mlxbf_i2c_quirks = {
.max_read_len = MLXBF_I2C_MASTER_DATA_R_LENGTH,
.max_write_len = MLXBF_I2C_MASTER_DATA_W_LENGTH,
};
static const struct of_device_id mlxbf_i2c_dt_ids[] = {
{
.compatible = "mellanox,i2c-mlxbf1",
.data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1]
},
{
.compatible = "mellanox,i2c-mlxbf2",
.data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2]
},
{},
};
MODULE_DEVICE_TABLE(of, mlxbf_i2c_dt_ids);
static const struct acpi_device_id mlxbf_i2c_acpi_ids[] = {
{ "MLNXBF03", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1] },
{ "MLNXBF23", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2] },
{},
};
MODULE_DEVICE_TABLE(acpi, mlxbf_i2c_acpi_ids);
static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
{
const struct acpi_device_id *aid;
struct acpi_device *adev;
unsigned long bus_id = 0;
const char *uid;
int ret;
if (acpi_disabled)
return -ENOENT;
adev = ACPI_COMPANION(dev);
if (!adev)
return -ENXIO;
aid = acpi_match_device(mlxbf_i2c_acpi_ids, dev);
if (!aid)
return -ENODEV;
priv->chip = (struct mlxbf_i2c_chip_info *)aid->driver_data;
uid = acpi_device_uid(adev);
if (!uid || !(*uid)) {
dev_err(dev, "Cannot retrieve UID\n");
return -ENODEV;
}
ret = kstrtoul(uid, 0, &bus_id);
if (!ret)
priv->bus = bus_id;
return ret;
}
static int mlxbf_i2c_of_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
{
const struct of_device_id *oid;
int bus_id = -1;
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
oid = of_match_node(mlxbf_i2c_dt_ids, dev->of_node);
if (!oid)
return -ENODEV;
priv->chip = oid->data;
bus_id = of_alias_get_id(dev->of_node, "i2c");
if (bus_id >= 0)
priv->bus = bus_id;
}
if (bus_id < 0) {
dev_err(dev, "Cannot get bus id");
return bus_id;
}
return 0;
}
static int mlxbf_i2c_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mlxbf_i2c_priv *priv;
struct i2c_adapter *adap;
int irq, ret;
priv = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
ret = mlxbf_i2c_acpi_probe(dev, priv);
if (ret < 0 && ret != -ENOENT && ret != -ENXIO)
ret = mlxbf_i2c_of_probe(dev, priv);
if (ret < 0)
return ret;
ret = mlxbf_i2c_init_resource(pdev, &priv->smbus,
MLXBF_I2C_SMBUS_RES);
if (ret < 0) {
dev_err(dev, "Cannot fetch smbus resource info");
return ret;
}
ret = mlxbf_i2c_init_resource(pdev, &priv->mst_cause,
MLXBF_I2C_MST_CAUSE_RES);
if (ret < 0) {
dev_err(dev, "Cannot fetch cause master resource info");
return ret;
}
ret = mlxbf_i2c_init_resource(pdev, &priv->slv_cause,
MLXBF_I2C_SLV_CAUSE_RES);
if (ret < 0) {
dev_err(dev, "Cannot fetch cause slave resource info");
return ret;
}
adap = &priv->adap;
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_HWMON;
adap->algo = &mlxbf_i2c_algo;
adap->quirks = &mlxbf_i2c_quirks;
adap->dev.parent = dev;
adap->dev.of_node = dev->of_node;
adap->nr = priv->bus;
snprintf(adap->name, sizeof(adap->name), "i2c%d", adap->nr);
i2c_set_adapdata(adap, priv);
/* Read Core PLL frequency. */
ret = mlxbf_i2c_calculate_corepll_freq(pdev, priv);
if (ret < 0) {
dev_err(dev, "cannot get core clock frequency\n");
/* Set to default value. */
priv->frequency = MLXBF_I2C_COREPLL_FREQ;
}
/*
* Initialize master.
* Note that a physical bus might be shared among Linux and firmware
* (e.g., ATF). Thus, the bus should be initialized and ready and
* bus initialization would be unnecessary. This requires additional
* knowledge about physical busses. But, since an extra initialization
* does not really hurt, then keep the code as is.
*/
ret = mlxbf_i2c_init_master(pdev, priv);
if (ret < 0) {
dev_err(dev, "failed to initialize smbus master %d",
priv->bus);
return ret;
}
mlxbf_i2c_init_timings(pdev, priv);
mlxbf_i2c_init_slave(pdev, priv);
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(dev, irq, mlxbf_smbus_irq,
IRQF_ONESHOT | IRQF_SHARED | IRQF_PROBE_SHARED,
dev_name(dev), priv);
if (ret < 0) {
dev_err(dev, "Cannot get irq %d\n", irq);
return ret;
}
priv->irq = irq;
platform_set_drvdata(pdev, priv);
ret = i2c_add_numbered_adapter(adap);
if (ret < 0)
return ret;
mutex_lock(&mlxbf_i2c_bus_lock);
mlxbf_i2c_bus_count++;
mutex_unlock(&mlxbf_i2c_bus_lock);
return 0;
}
static int mlxbf_i2c_remove(struct platform_device *pdev)
{
struct mlxbf_i2c_priv *priv = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
struct resource *params;
params = priv->smbus->params;
devm_release_mem_region(dev, params->start, resource_size(params));
params = priv->mst_cause->params;
devm_release_mem_region(dev, params->start, resource_size(params));
params = priv->slv_cause->params;
devm_release_mem_region(dev, params->start, resource_size(params));
/*
* Release shared resources. This should be done when releasing
* the I2C controller.
*/
mutex_lock(&mlxbf_i2c_bus_lock);
if (--mlxbf_i2c_bus_count == 0) {
mlxbf_i2c_release_coalesce(pdev, priv);
mlxbf_i2c_release_corepll(pdev, priv);
mlxbf_i2c_release_gpio(pdev, priv);
}
mutex_unlock(&mlxbf_i2c_bus_lock);
devm_free_irq(dev, priv->irq, priv);
i2c_del_adapter(&priv->adap);
return 0;
}
static struct platform_driver mlxbf_i2c_driver = {
.probe = mlxbf_i2c_probe,
.remove = mlxbf_i2c_remove,
.driver = {
.name = "i2c-mlxbf",
.of_match_table = mlxbf_i2c_dt_ids,
.acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids),
},
};
static int __init mlxbf_i2c_init(void)
{
mutex_init(&mlxbf_i2c_coalesce_lock);
mutex_init(&mlxbf_i2c_corepll_lock);
mutex_init(&mlxbf_i2c_gpio_lock);
mutex_init(&mlxbf_i2c_bus_lock);
return platform_driver_register(&mlxbf_i2c_driver);
}
module_init(mlxbf_i2c_init);
static void __exit mlxbf_i2c_exit(void)
{
platform_driver_unregister(&mlxbf_i2c_driver);
mutex_destroy(&mlxbf_i2c_bus_lock);
mutex_destroy(&mlxbf_i2c_gpio_lock);
mutex_destroy(&mlxbf_i2c_corepll_lock);
mutex_destroy(&mlxbf_i2c_coalesce_lock);
}
module_exit(mlxbf_i2c_exit);
MODULE_DESCRIPTION("Mellanox BlueField I2C bus driver");
MODULE_AUTHOR("Khalil Blaiech <kblaiech@mellanox.com>");
MODULE_LICENSE("GPL v2");
...@@ -496,11 +496,10 @@ static irqreturn_t ...@@ -496,11 +496,10 @@ static irqreturn_t
mv64xxx_i2c_intr(int irq, void *dev_id) mv64xxx_i2c_intr(int irq, void *dev_id)
{ {
struct mv64xxx_i2c_data *drv_data = dev_id; struct mv64xxx_i2c_data *drv_data = dev_id;
unsigned long flags;
u32 status; u32 status;
irqreturn_t rc = IRQ_NONE; irqreturn_t rc = IRQ_NONE;
spin_lock_irqsave(&drv_data->lock, flags); spin_lock(&drv_data->lock);
if (drv_data->offload_enabled) if (drv_data->offload_enabled)
rc = mv64xxx_i2c_intr_offload(drv_data); rc = mv64xxx_i2c_intr_offload(drv_data);
...@@ -517,7 +516,7 @@ mv64xxx_i2c_intr(int irq, void *dev_id) ...@@ -517,7 +516,7 @@ mv64xxx_i2c_intr(int irq, void *dev_id)
rc = IRQ_HANDLED; rc = IRQ_HANDLED;
} }
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock(&drv_data->lock);
return rc; return rc;
} }
......
...@@ -125,8 +125,7 @@ static int gpu_i2c_read(struct gpu_i2c_dev *i2cd, u8 *data, u16 len) ...@@ -125,8 +125,7 @@ static int gpu_i2c_read(struct gpu_i2c_dev *i2cd, u8 *data, u16 len)
put_unaligned_be16(val, data); put_unaligned_be16(val, data);
break; break;
case 3: case 3:
put_unaligned_be16(val >> 8, data); put_unaligned_be24(val, data);
data[2] = val;
break; break;
case 4: case 4:
put_unaligned_be32(val, data); put_unaligned_be32(val, data);
......
...@@ -165,10 +165,9 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) ...@@ -165,10 +165,9 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
{ {
struct owl_i2c_dev *i2c_dev = _dev; struct owl_i2c_dev *i2c_dev = _dev;
struct i2c_msg *msg = i2c_dev->msg; struct i2c_msg *msg = i2c_dev->msg;
unsigned long flags;
unsigned int stat, fifostat; unsigned int stat, fifostat;
spin_lock_irqsave(&i2c_dev->lock, flags); spin_lock(&i2c_dev->lock);
i2c_dev->err = 0; i2c_dev->err = 0;
...@@ -214,7 +213,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) ...@@ -214,7 +213,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
OWL_I2C_STAT_IRQP, true); OWL_I2C_STAT_IRQP, true);
complete_all(&i2c_dev->msg_complete); complete_all(&i2c_dev->msg_complete);
spin_unlock_irqrestore(&i2c_dev->lock, flags); spin_unlock(&i2c_dev->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -210,9 +210,8 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev) ...@@ -210,9 +210,8 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev)
u32 dma; u32 dma;
u32 val; u32 val;
struct i2c_msg *cur; struct i2c_msg *cur;
unsigned long flags;
spin_lock_irqsave(&gi2c->lock, flags); spin_lock(&gi2c->lock);
m_stat = readl_relaxed(base + SE_GENI_M_IRQ_STATUS); m_stat = readl_relaxed(base + SE_GENI_M_IRQ_STATUS);
rx_st = readl_relaxed(base + SE_GENI_RX_FIFO_STATUS); rx_st = readl_relaxed(base + SE_GENI_RX_FIFO_STATUS);
dm_tx_st = readl_relaxed(base + SE_DMA_TX_IRQ_STAT); dm_tx_st = readl_relaxed(base + SE_DMA_TX_IRQ_STAT);
...@@ -294,7 +293,7 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev) ...@@ -294,7 +293,7 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev)
dm_rx_st & RX_DMA_DONE || dm_rx_st & RX_RESET_DONE) dm_rx_st & RX_DMA_DONE || dm_rx_st & RX_RESET_DONE)
complete(&gi2c->done); complete(&gi2c->done);
spin_unlock_irqrestore(&gi2c->lock, flags); spin_unlock(&gi2c->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -19,7 +19,9 @@ ...@@ -19,7 +19,9 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -105,10 +107,11 @@ ...@@ -105,10 +107,11 @@
#define ID_ARBLOST (1 << 3) #define ID_ARBLOST (1 << 3)
#define ID_NACK (1 << 4) #define ID_NACK (1 << 4)
/* persistent flags */ /* persistent flags */
#define ID_P_HOST_NOTIFY BIT(28)
#define ID_P_REP_AFTER_RD BIT(29) #define ID_P_REP_AFTER_RD BIT(29)
#define ID_P_NO_RXDMA BIT(30) /* HW forbids RXDMA sometimes */ #define ID_P_NO_RXDMA BIT(30) /* HW forbids RXDMA sometimes */
#define ID_P_PM_BLOCKED BIT(31) #define ID_P_PM_BLOCKED BIT(31)
#define ID_P_MASK GENMASK(31, 29) #define ID_P_MASK GENMASK(31, 28)
enum rcar_i2c_type { enum rcar_i2c_type {
I2C_RCAR_GEN1, I2C_RCAR_GEN1,
...@@ -140,14 +143,13 @@ struct rcar_i2c_priv { ...@@ -140,14 +143,13 @@ struct rcar_i2c_priv {
struct reset_control *rstc; struct reset_control *rstc;
int irq; int irq;
struct i2c_client *host_notify_client;
}; };
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent) #define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
#define rcar_i2c_is_recv(p) ((p)->msg->flags & I2C_M_RD) #define rcar_i2c_is_recv(p) ((p)->msg->flags & I2C_M_RD)
#define LOOP_TIMEOUT 1024
static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val) static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val)
{ {
writel(val, priv->io + reg); writel(val, priv->io + reg);
...@@ -221,18 +223,18 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv) ...@@ -221,18 +223,18 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
{ {
int i; int ret;
u32 val;
for (i = 0; i < LOOP_TIMEOUT; i++) {
/* make sure that bus is not busy */
if (!(rcar_i2c_read(priv, ICMCR) & FSDA))
return 0;
udelay(1);
}
ret = readl_poll_timeout(priv->io + ICMCR, val, !(val & FSDA), 10,
priv->adap.timeout);
if (ret) {
/* Waiting did not help, try to recover */ /* Waiting did not help, try to recover */
priv->recovery_icmcr = MDBS | OBPC | FSDA | FSCL; priv->recovery_icmcr = MDBS | OBPC | FSDA | FSCL;
return i2c_recover_bus(&priv->adap); ret = i2c_recover_bus(&priv->adap);
}
return ret;
} }
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv) static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
...@@ -760,20 +762,14 @@ static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv) ...@@ -760,20 +762,14 @@ static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv)
/* I2C is a special case, we need to poll the status of a reset */ /* I2C is a special case, we need to poll the status of a reset */
static int rcar_i2c_do_reset(struct rcar_i2c_priv *priv) static int rcar_i2c_do_reset(struct rcar_i2c_priv *priv)
{ {
int i, ret; int ret;
ret = reset_control_reset(priv->rstc); ret = reset_control_reset(priv->rstc);
if (ret) if (ret)
return ret; return ret;
for (i = 0; i < LOOP_TIMEOUT; i++) { return read_poll_timeout_atomic(reset_control_status, ret, ret == 0, 1,
ret = reset_control_status(priv->rstc); 100, false, priv->rstc);
if (ret == 0)
return 0;
udelay(1);
}
return -ETIMEDOUT;
} }
static int rcar_i2c_master_xfer(struct i2c_adapter *adap, static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
...@@ -884,14 +880,21 @@ static int rcar_unreg_slave(struct i2c_client *slave) ...@@ -884,14 +880,21 @@ static int rcar_unreg_slave(struct i2c_client *slave)
static u32 rcar_i2c_func(struct i2c_adapter *adap) static u32 rcar_i2c_func(struct i2c_adapter *adap)
{ {
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
/* /*
* This HW can't do: * This HW can't do:
* I2C_SMBUS_QUICK (setting FSB during START didn't work) * I2C_SMBUS_QUICK (setting FSB during START didn't work)
* I2C_M_NOSTART (automatically sends address after START) * I2C_M_NOSTART (automatically sends address after START)
* I2C_M_IGNORE_NAK (automatically sends STOP after NAK) * I2C_M_IGNORE_NAK (automatically sends STOP after NAK)
*/ */
return I2C_FUNC_I2C | I2C_FUNC_SLAVE | u32 func = I2C_FUNC_I2C | I2C_FUNC_SLAVE |
(I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
if (priv->flags & ID_P_HOST_NOTIFY)
func |= I2C_FUNC_SMBUS_HOST_NOTIFY;
return func;
} }
static const struct i2c_algorithm rcar_i2c_algo = { static const struct i2c_algorithm rcar_i2c_algo = {
...@@ -991,6 +994,8 @@ static int rcar_i2c_probe(struct platform_device *pdev) ...@@ -991,6 +994,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
else else
pm_runtime_put(dev); pm_runtime_put(dev);
if (of_property_read_bool(dev->of_node, "smbus"))
priv->flags |= ID_P_HOST_NOTIFY;
priv->irq = platform_get_irq(pdev, 0); priv->irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, dev_name(dev), priv); ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, dev_name(dev), priv);
...@@ -1005,10 +1010,20 @@ static int rcar_i2c_probe(struct platform_device *pdev) ...@@ -1005,10 +1010,20 @@ static int rcar_i2c_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto out_pm_disable; goto out_pm_disable;
if (priv->flags & ID_P_HOST_NOTIFY) {
priv->host_notify_client = i2c_new_slave_host_notify_device(adap);
if (IS_ERR(priv->host_notify_client)) {
ret = PTR_ERR(priv->host_notify_client);
goto out_del_device;
}
}
dev_info(dev, "probed\n"); dev_info(dev, "probed\n");
return 0; return 0;
out_del_device:
i2c_del_adapter(&priv->adap);
out_pm_put: out_pm_put:
pm_runtime_put(dev); pm_runtime_put(dev);
out_pm_disable: out_pm_disable:
...@@ -1021,6 +1036,8 @@ static int rcar_i2c_remove(struct platform_device *pdev) ...@@ -1021,6 +1036,8 @@ static int rcar_i2c_remove(struct platform_device *pdev)
struct rcar_i2c_priv *priv = platform_get_drvdata(pdev); struct rcar_i2c_priv *priv = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
if (priv->host_notify_client)
i2c_free_slave_host_notify_device(priv->host_notify_client);
i2c_del_adapter(&priv->adap); i2c_del_adapter(&priv->adap);
rcar_i2c_release_dma(priv); rcar_i2c_release_dma(priv);
if (priv->flags & ID_P_PM_BLOCKED) if (priv->flags & ID_P_PM_BLOCKED)
......
...@@ -1312,18 +1312,13 @@ static int rk3x_i2c_probe(struct platform_device *pdev) ...@@ -1312,18 +1312,13 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
i2c->pclk = devm_clk_get(&pdev->dev, "pclk"); i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
} }
if (IS_ERR(i2c->clk)) { if (IS_ERR(i2c->clk))
ret = PTR_ERR(i2c->clk); return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
if (ret != -EPROBE_DEFER) "Can't get bus clk\n");
dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
return ret; if (IS_ERR(i2c->pclk))
} return dev_err_probe(&pdev->dev, PTR_ERR(i2c->pclk),
if (IS_ERR(i2c->pclk)) { "Can't get periph clk\n");
ret = PTR_ERR(i2c->pclk);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
return ret;
}
ret = clk_prepare(i2c->clk); ret = clk_prepare(i2c->clk);
if (ret < 0) { if (ret < 0) {
......
...@@ -26,8 +26,9 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, ...@@ -26,8 +26,9 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
dma->chan_tx = dma_request_chan(dev, "tx"); dma->chan_tx = dma_request_chan(dev, "tx");
if (IS_ERR(dma->chan_tx)) { if (IS_ERR(dma->chan_tx)) {
ret = PTR_ERR(dma->chan_tx); ret = PTR_ERR(dma->chan_tx);
if (ret != -EPROBE_DEFER) if (ret != -ENODEV)
dev_err(dev, "can't request DMA tx channel\n"); ret = dev_err_probe(dev, ret,
"can't request DMA tx channel\n");
goto fail_al; goto fail_al;
} }
...@@ -46,8 +47,9 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, ...@@ -46,8 +47,9 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
dma->chan_rx = dma_request_chan(dev, "rx"); dma->chan_rx = dma_request_chan(dev, "rx");
if (IS_ERR(dma->chan_rx)) { if (IS_ERR(dma->chan_rx)) {
ret = PTR_ERR(dma->chan_rx); ret = PTR_ERR(dma->chan_rx);
if (ret != -EPROBE_DEFER) if (ret != -ENODEV)
dev_err(dev, "can't request DMA rx channel\n"); ret = dev_err_probe(dev, ret,
"can't request DMA rx channel\n");
goto fail_tx; goto fail_tx;
} }
...@@ -76,8 +78,6 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, ...@@ -76,8 +78,6 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
dma_release_channel(dma->chan_tx); dma_release_channel(dma->chan_tx);
fail_al: fail_al:
devm_kfree(dev, dma); devm_kfree(dev, dma);
if (ret != -EPROBE_DEFER)
dev_info(dev, "can't use DMA\n");
return ERR_PTR(ret); return ERR_PTR(ret);
} }
......
...@@ -797,10 +797,8 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) ...@@ -797,10 +797,8 @@ static int stm32f4_i2c_probe(struct platform_device *pdev)
rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(rst)) { if (IS_ERR(rst)) {
ret = PTR_ERR(rst); ret = dev_err_probe(&pdev->dev, PTR_ERR(rst),
if (ret != -EPROBE_DEFER) "Error: Missing reset ctrl\n");
dev_err(&pdev->dev, "Error: Missing reset ctrl\n");
goto clk_free; goto clk_free;
} }
reset_control_assert(rst); reset_control_assert(rst);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
...@@ -50,6 +51,7 @@ ...@@ -50,6 +51,7 @@
/* STM32F7 I2C control 1 */ /* STM32F7 I2C control 1 */
#define STM32F7_I2C_CR1_PECEN BIT(23) #define STM32F7_I2C_CR1_PECEN BIT(23)
#define STM32F7_I2C_CR1_SMBHEN BIT(20)
#define STM32F7_I2C_CR1_WUPEN BIT(18) #define STM32F7_I2C_CR1_WUPEN BIT(18)
#define STM32F7_I2C_CR1_SBC BIT(16) #define STM32F7_I2C_CR1_SBC BIT(16)
#define STM32F7_I2C_CR1_RXDMAEN BIT(15) #define STM32F7_I2C_CR1_RXDMAEN BIT(15)
...@@ -150,7 +152,12 @@ ...@@ -150,7 +152,12 @@
#define STM32F7_I2C_MAX_LEN 0xff #define STM32F7_I2C_MAX_LEN 0xff
#define STM32F7_I2C_DMA_LEN_MIN 0x16 #define STM32F7_I2C_DMA_LEN_MIN 0x16
#define STM32F7_I2C_MAX_SLAVE 0x2 enum {
STM32F7_SLAVE_HOSTNOTIFY,
STM32F7_SLAVE_7_10_BITS_ADDR,
STM32F7_SLAVE_7_BITS_ADDR,
STM32F7_I2C_MAX_SLAVE
};
#define STM32F7_I2C_DNF_DEFAULT 0 #define STM32F7_I2C_DNF_DEFAULT 0
#define STM32F7_I2C_DNF_MAX 16 #define STM32F7_I2C_DNF_MAX 16
...@@ -301,6 +308,8 @@ struct stm32f7_i2c_msg { ...@@ -301,6 +308,8 @@ struct stm32f7_i2c_msg {
* @fmp_creg: register address for clearing Fast Mode Plus bits * @fmp_creg: register address for clearing Fast Mode Plus bits
* @fmp_mask: mask for Fast Mode Plus bits in set register * @fmp_mask: mask for Fast Mode Plus bits in set register
* @wakeup_src: boolean to know if the device is a wakeup source * @wakeup_src: boolean to know if the device is a wakeup source
* @smbus_mode: states that the controller is configured in SMBus mode
* @host_notify_client: SMBus host-notify client
*/ */
struct stm32f7_i2c_dev { struct stm32f7_i2c_dev {
struct i2c_adapter adap; struct i2c_adapter adap;
...@@ -327,6 +336,8 @@ struct stm32f7_i2c_dev { ...@@ -327,6 +336,8 @@ struct stm32f7_i2c_dev {
u32 fmp_creg; u32 fmp_creg;
u32 fmp_mask; u32 fmp_mask;
bool wakeup_src; bool wakeup_src;
bool smbus_mode;
struct i2c_client *host_notify_client;
}; };
/* /*
...@@ -1321,11 +1332,20 @@ static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev, ...@@ -1321,11 +1332,20 @@ static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev,
int i; int i;
/* /*
* slave[0] supports 7-bit and 10-bit slave address * slave[STM32F7_SLAVE_HOSTNOTIFY] support only SMBus Host address (0x8)
* slave[1] supports 7-bit slave address only * slave[STM32F7_SLAVE_7_10_BITS_ADDR] supports 7-bit and 10-bit slave address
* slave[STM32F7_SLAVE_7_BITS_ADDR] supports 7-bit slave address only
*/ */
for (i = STM32F7_I2C_MAX_SLAVE - 1; i >= 0; i--) { if (i2c_dev->smbus_mode && (slave->addr == 0x08)) {
if (i == 1 && (slave->flags & I2C_CLIENT_TEN)) if (i2c_dev->slave[STM32F7_SLAVE_HOSTNOTIFY])
goto fail;
*id = STM32F7_SLAVE_HOSTNOTIFY;
return 0;
}
for (i = STM32F7_I2C_MAX_SLAVE - 1; i > STM32F7_SLAVE_HOSTNOTIFY; i--) {
if ((i == STM32F7_SLAVE_7_BITS_ADDR) &&
(slave->flags & I2C_CLIENT_TEN))
continue; continue;
if (!i2c_dev->slave[i]) { if (!i2c_dev->slave[i]) {
*id = i; *id = i;
...@@ -1333,6 +1353,7 @@ static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev, ...@@ -1333,6 +1353,7 @@ static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev,
} }
} }
fail:
dev_err(dev, "Slave 0x%x could not be registered\n", slave->addr); dev_err(dev, "Slave 0x%x could not be registered\n", slave->addr);
return -EINVAL; return -EINVAL;
...@@ -1776,7 +1797,13 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) ...@@ -1776,7 +1797,13 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
if (!stm32f7_i2c_is_slave_registered(i2c_dev)) if (!stm32f7_i2c_is_slave_registered(i2c_dev))
stm32f7_i2c_enable_wakeup(i2c_dev, true); stm32f7_i2c_enable_wakeup(i2c_dev, true);
if (id == 0) { switch (id) {
case 0:
/* Slave SMBus Host */
i2c_dev->slave[id] = slave;
break;
case 1:
/* Configure Own Address 1 */ /* Configure Own Address 1 */
oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1); oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1);
oar1 &= ~STM32F7_I2C_OAR1_MASK; oar1 &= ~STM32F7_I2C_OAR1_MASK;
...@@ -1789,7 +1816,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) ...@@ -1789,7 +1816,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
oar1 |= STM32F7_I2C_OAR1_OA1EN; oar1 |= STM32F7_I2C_OAR1_OA1EN;
i2c_dev->slave[id] = slave; i2c_dev->slave[id] = slave;
writel_relaxed(oar1, i2c_dev->base + STM32F7_I2C_OAR1); writel_relaxed(oar1, i2c_dev->base + STM32F7_I2C_OAR1);
} else if (id == 1) { break;
case 2:
/* Configure Own Address 2 */ /* Configure Own Address 2 */
oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2); oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
oar2 &= ~STM32F7_I2C_OAR2_MASK; oar2 &= ~STM32F7_I2C_OAR2_MASK;
...@@ -1802,7 +1831,10 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) ...@@ -1802,7 +1831,10 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
oar2 |= STM32F7_I2C_OAR2_OA2EN; oar2 |= STM32F7_I2C_OAR2_OA2EN;
i2c_dev->slave[id] = slave; i2c_dev->slave[id] = slave;
writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2); writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
} else { break;
default:
dev_err(dev, "I2C slave id not supported\n");
ret = -ENODEV; ret = -ENODEV;
goto pm_free; goto pm_free;
} }
...@@ -1843,10 +1875,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave) ...@@ -1843,10 +1875,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (id == 0) { if (id == 1) {
mask = STM32F7_I2C_OAR1_OA1EN; mask = STM32F7_I2C_OAR1_OA1EN;
stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask); stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
} else { } else if (id == 2) {
mask = STM32F7_I2C_OAR2_OA2EN; mask = STM32F7_I2C_OAR2_OA2EN;
stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR2, mask); stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR2, mask);
} }
...@@ -1911,14 +1943,51 @@ static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev, ...@@ -1911,14 +1943,51 @@ static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev,
&i2c_dev->fmp_mask); &i2c_dev->fmp_mask);
} }
static int stm32f7_i2c_enable_smbus_host(struct stm32f7_i2c_dev *i2c_dev)
{
struct i2c_adapter *adap = &i2c_dev->adap;
void __iomem *base = i2c_dev->base;
struct i2c_client *client;
client = i2c_new_slave_host_notify_device(adap);
if (IS_ERR(client))
return PTR_ERR(client);
i2c_dev->host_notify_client = client;
/* Enable SMBus Host address */
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_SMBHEN);
return 0;
}
static void stm32f7_i2c_disable_smbus_host(struct stm32f7_i2c_dev *i2c_dev)
{
void __iomem *base = i2c_dev->base;
if (i2c_dev->host_notify_client) {
/* Disable SMBus Host address */
stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1,
STM32F7_I2C_CR1_SMBHEN);
i2c_free_slave_host_notify_device(i2c_dev->host_notify_client);
}
}
static u32 stm32f7_i2c_func(struct i2c_adapter *adap) static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
{ {
return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE | struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
u32 func = I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC | I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC |
I2C_FUNC_SMBUS_I2C_BLOCK; I2C_FUNC_SMBUS_I2C_BLOCK;
if (i2c_dev->smbus_mode)
func |= I2C_FUNC_SMBUS_HOST_NOTIFY;
return func;
} }
static const struct i2c_algorithm stm32f7_i2c_algo = { static const struct i2c_algorithm stm32f7_i2c_algo = {
...@@ -1968,11 +2037,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -1968,11 +2037,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
"wakeup-source"); "wakeup-source");
i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2c_dev->clk)) { if (IS_ERR(i2c_dev->clk))
if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER) return dev_err_probe(&pdev->dev, PTR_ERR(i2c_dev->clk),
dev_err(&pdev->dev, "Failed to get controller clock\n"); "Failed to get controller clock\n");
return PTR_ERR(i2c_dev->clk);
}
ret = clk_prepare_enable(i2c_dev->clk); ret = clk_prepare_enable(i2c_dev->clk);
if (ret) { if (ret) {
...@@ -1982,10 +2049,8 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -1982,10 +2049,8 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
rst = devm_reset_control_get(&pdev->dev, NULL); rst = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(rst)) { if (IS_ERR(rst)) {
ret = PTR_ERR(rst); ret = dev_err_probe(&pdev->dev, PTR_ERR(rst),
if (ret != -EPROBE_DEFER) "Error: Missing reset ctrl\n");
dev_err(&pdev->dev, "Error: Missing reset ctrl\n");
goto clk_free; goto clk_free;
} }
reset_control_assert(rst); reset_control_assert(rst);
...@@ -2052,14 +2117,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -2052,14 +2117,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr, i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
STM32F7_I2C_TXDR, STM32F7_I2C_TXDR,
STM32F7_I2C_RXDR); STM32F7_I2C_RXDR);
if (PTR_ERR(i2c_dev->dma) == -ENODEV) if (IS_ERR(i2c_dev->dma)) {
i2c_dev->dma = NULL;
else if (IS_ERR(i2c_dev->dma)) {
ret = PTR_ERR(i2c_dev->dma); ret = PTR_ERR(i2c_dev->dma);
if (ret != -EPROBE_DEFER) /* DMA support is optional, only report other errors */
dev_err(&pdev->dev, if (ret != -ENODEV)
"Failed to request dma error %i\n", ret);
goto fmp_clear; goto fmp_clear;
dev_dbg(i2c_dev->dev, "No DMA option: fallback using interrupts\n");
i2c_dev->dma = NULL;
} }
if (i2c_dev->wakeup_src) { if (i2c_dev->wakeup_src) {
...@@ -2084,10 +2148,22 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -2084,10 +2148,22 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
stm32f7_i2c_hw_config(i2c_dev); stm32f7_i2c_hw_config(i2c_dev);
i2c_dev->smbus_mode = of_property_read_bool(pdev->dev.of_node, "smbus");
ret = i2c_add_adapter(adap); ret = i2c_add_adapter(adap);
if (ret) if (ret)
goto pm_disable; goto pm_disable;
if (i2c_dev->smbus_mode) {
ret = stm32f7_i2c_enable_smbus_host(i2c_dev);
if (ret) {
dev_err(i2c_dev->dev,
"failed to enable SMBus Host-Notify protocol (%d)\n",
ret);
goto i2c_adapter_remove;
}
}
dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr); dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
pm_runtime_mark_last_busy(i2c_dev->dev); pm_runtime_mark_last_busy(i2c_dev->dev);
...@@ -2095,6 +2171,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -2095,6 +2171,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
return 0; return 0;
i2c_adapter_remove:
i2c_del_adapter(adap);
pm_disable: pm_disable:
pm_runtime_put_noidle(i2c_dev->dev); pm_runtime_put_noidle(i2c_dev->dev);
pm_runtime_disable(i2c_dev->dev); pm_runtime_disable(i2c_dev->dev);
...@@ -2126,6 +2205,8 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) ...@@ -2126,6 +2205,8 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
{ {
struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
stm32f7_i2c_disable_smbus_host(i2c_dev);
i2c_del_adapter(&i2c_dev->adap); i2c_del_adapter(&i2c_dev->adap);
pm_runtime_get_sync(i2c_dev->dev); pm_runtime_get_sync(i2c_dev->dev);
......
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
/* configuration load timeout in microseconds */ /* configuration load timeout in microseconds */
#define I2C_CONFIG_LOAD_TIMEOUT 1000000 #define I2C_CONFIG_LOAD_TIMEOUT 1000000
/* Packet header size in bytes */ /* packet header size in bytes */
#define I2C_PACKET_HEADER_SIZE 12 #define I2C_PACKET_HEADER_SIZE 12
/* /*
...@@ -148,11 +148,10 @@ ...@@ -148,11 +148,10 @@
#define I2C_PIO_MODE_PREFERRED_LEN 32 #define I2C_PIO_MODE_PREFERRED_LEN 32
/* /*
* msg_end_type: The bus control which need to be send at end of transfer. * msg_end_type: The bus control which needs to be sent at end of transfer.
* @MSG_END_STOP: Send stop pulse at end of transfer. * @MSG_END_STOP: Send stop pulse.
* @MSG_END_REPEAT_START: Send repeat start at end of transfer. * @MSG_END_REPEAT_START: Send repeat-start.
* @MSG_END_CONTINUE: The following on message is coming and so do not send * @MSG_END_CONTINUE: Don't send stop or repeat-start.
* stop or repeat start.
*/ */
enum msg_end_type { enum msg_end_type {
MSG_END_STOP, MSG_END_STOP,
...@@ -161,13 +160,10 @@ enum msg_end_type { ...@@ -161,13 +160,10 @@ enum msg_end_type {
}; };
/** /**
* struct tegra_i2c_hw_feature : Different HW support on Tegra * struct tegra_i2c_hw_feature : per hardware generation features
* @has_continue_xfer_support: Continue transfer supports. * @has_continue_xfer_support: continue-transfer supported
* @has_per_pkt_xfer_complete_irq: Has enable/disable capability for transfer * @has_per_pkt_xfer_complete_irq: Has enable/disable capability for transfer
* complete interrupt per packet basis. * completion interrupt on per packet basis.
* @has_single_clk_source: The I2C controller has single clock source. Tegra30
* and earlier SoCs have two clock sources i.e. div-clk and
* fast-clk.
* @has_config_load_reg: Has the config load register to load the new * @has_config_load_reg: Has the config load register to load the new
* configuration. * configuration.
* @clk_divisor_hs_mode: Clock divisor in HS mode. * @clk_divisor_hs_mode: Clock divisor in HS mode.
...@@ -187,7 +183,7 @@ enum msg_end_type { ...@@ -187,7 +183,7 @@ enum msg_end_type {
* @has_mst_fifo: The I2C controller contains the new MST FIFO interface that * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that
* provides additional features and allows for longer messages to * provides additional features and allows for longer messages to
* be transferred in one go. * be transferred in one go.
* @quirks: i2c adapter quirks for limiting write/read transfer size and not * @quirks: I2C adapter quirks for limiting write/read transfer size and not
* allowing 0 length transfers. * allowing 0 length transfers.
* @supports_bus_clear: Bus Clear support to recover from bus hang during * @supports_bus_clear: Bus Clear support to recover from bus hang during
* SDA stuck low from device for some unknown reasons. * SDA stuck low from device for some unknown reasons.
...@@ -208,22 +204,21 @@ enum msg_end_type { ...@@ -208,22 +204,21 @@ enum msg_end_type {
struct tegra_i2c_hw_feature { struct tegra_i2c_hw_feature {
bool has_continue_xfer_support; bool has_continue_xfer_support;
bool has_per_pkt_xfer_complete_irq; bool has_per_pkt_xfer_complete_irq;
bool has_single_clk_source;
bool has_config_load_reg; bool has_config_load_reg;
int clk_divisor_hs_mode; u32 clk_divisor_hs_mode;
int clk_divisor_std_mode; u32 clk_divisor_std_mode;
int clk_divisor_fast_mode; u32 clk_divisor_fast_mode;
u16 clk_divisor_fast_plus_mode; u32 clk_divisor_fast_plus_mode;
bool has_multi_master_mode; bool has_multi_master_mode;
bool has_slcg_override_reg; bool has_slcg_override_reg;
bool has_mst_fifo; bool has_mst_fifo;
const struct i2c_adapter_quirks *quirks; const struct i2c_adapter_quirks *quirks;
bool supports_bus_clear; bool supports_bus_clear;
bool has_apb_dma; bool has_apb_dma;
u8 tlow_std_mode; u32 tlow_std_mode;
u8 thigh_std_mode; u32 thigh_std_mode;
u8 tlow_fast_fastplus_mode; u32 tlow_fast_fastplus_mode;
u8 thigh_fast_fastplus_mode; u32 thigh_fast_fastplus_mode;
u32 setup_hold_time_std_mode; u32 setup_hold_time_std_mode;
u32 setup_hold_time_fast_fast_plus_mode; u32 setup_hold_time_fast_fast_plus_mode;
u32 setup_hold_time_hs_mode; u32 setup_hold_time_hs_mode;
...@@ -236,7 +231,8 @@ struct tegra_i2c_hw_feature { ...@@ -236,7 +231,8 @@ struct tegra_i2c_hw_feature {
* @hw: Tegra I2C HW feature * @hw: Tegra I2C HW feature
* @adapter: core I2C layer adapter information * @adapter: core I2C layer adapter information
* @div_clk: clock reference for div clock of I2C controller * @div_clk: clock reference for div clock of I2C controller
* @fast_clk: clock reference for fast clock of I2C controller * @clocks: array of I2C controller clocks
* @nclocks: number of clocks in the array
* @rst: reset control for the I2C controller * @rst: reset control for the I2C controller
* @base: ioremapped registers cookie * @base: ioremapped registers cookie
* @base_phys: physical base address of the I2C controller * @base_phys: physical base address of the I2C controller
...@@ -248,101 +244,103 @@ struct tegra_i2c_hw_feature { ...@@ -248,101 +244,103 @@ struct tegra_i2c_hw_feature {
* @msg_err: error code for completed message * @msg_err: error code for completed message
* @msg_buf: pointer to current message data * @msg_buf: pointer to current message data
* @msg_buf_remaining: size of unsent data in the message buffer * @msg_buf_remaining: size of unsent data in the message buffer
* @msg_read: identifies read transfers * @msg_read: indicates that the transfer is a read access
* @bus_clk_rate: current I2C bus clock rate * @bus_clk_rate: current I2C bus clock rate
* @clk_divisor_non_hs_mode: clock divider for non-high-speed modes * @multimaster_mode: indicates that I2C controller is in multi-master mode
* @is_multimaster_mode: track if I2C controller is in multi-master mode
* @tx_dma_chan: DMA transmit channel * @tx_dma_chan: DMA transmit channel
* @rx_dma_chan: DMA receive channel * @rx_dma_chan: DMA receive channel
* @dma_phys: handle to DMA resources * @dma_phys: handle to DMA resources
* @dma_buf: pointer to allocated DMA buffer * @dma_buf: pointer to allocated DMA buffer
* @dma_buf_size: DMA buffer size * @dma_buf_size: DMA buffer size
* @is_curr_dma_xfer: indicates active DMA transfer * @dma_mode: indicates active DMA transfer
* @dma_complete: DMA completion notifier * @dma_complete: DMA completion notifier
* @is_curr_atomic_xfer: indicates active atomic transfer * @atomic_mode: indicates active atomic transfer
*/ */
struct tegra_i2c_dev { struct tegra_i2c_dev {
struct device *dev; struct device *dev;
const struct tegra_i2c_hw_feature *hw;
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct clk *div_clk;
struct clk *fast_clk; const struct tegra_i2c_hw_feature *hw;
struct clk *slow_clk;
struct reset_control *rst; struct reset_control *rst;
void __iomem *base; unsigned int cont_id;
unsigned int irq;
phys_addr_t base_phys; phys_addr_t base_phys;
int cont_id; void __iomem *base;
int irq;
int is_dvc; struct clk_bulk_data clocks[2];
bool is_vi; unsigned int nclocks;
struct clk *div_clk;
u32 bus_clk_rate;
struct completion msg_complete; struct completion msg_complete;
size_t msg_buf_remaining;
int msg_err; int msg_err;
u8 *msg_buf; u8 *msg_buf;
size_t msg_buf_remaining;
int msg_read; struct completion dma_complete;
u32 bus_clk_rate;
u16 clk_divisor_non_hs_mode;
bool is_multimaster_mode;
struct dma_chan *tx_dma_chan; struct dma_chan *tx_dma_chan;
struct dma_chan *rx_dma_chan; struct dma_chan *rx_dma_chan;
dma_addr_t dma_phys;
u32 *dma_buf;
unsigned int dma_buf_size; unsigned int dma_buf_size;
bool is_curr_dma_xfer; dma_addr_t dma_phys;
struct completion dma_complete; void *dma_buf;
bool is_curr_atomic_xfer;
};
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit); bool multimaster_mode;
bool atomic_mode;
bool dma_mode;
bool msg_read;
bool is_dvc;
bool is_vi;
};
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned long reg) unsigned int reg)
{ {
writel_relaxed(val, i2c_dev->base + reg); writel_relaxed(val, i2c_dev->base + reg);
} }
static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
{ {
return readl_relaxed(i2c_dev->base + reg); return readl_relaxed(i2c_dev->base + reg);
} }
/* /*
* i2c_writel and i2c_readl will offset the register if necessary to talk * If necessary, i2c_writel() and i2c_readl() will offset the register
* to the I2C block inside the DVC block * in order to talk to the I2C block inside the DVC block.
*/ */
static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
unsigned long reg)
{ {
if (i2c_dev->is_dvc) if (i2c_dev->is_dvc)
reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
else if (i2c_dev->is_vi) else if (i2c_dev->is_vi)
reg = 0xc00 + (reg << 2); reg = 0xc00 + (reg << 2);
return reg; return reg;
} }
static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
unsigned long reg)
{ {
writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
/* Read back register to make sure that register writes completed */ /* read back register to make sure that register writes completed */
if (reg != I2C_TX_FIFO) if (reg != I2C_TX_FIFO)
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
} }
static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
{ {
return readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); return readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
} }
static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data, static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
unsigned long reg, int len) unsigned int reg, unsigned int len)
{ {
writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
} }
static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data, static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
unsigned long reg, int len) unsigned int reg, unsigned int len)
{ {
readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
} }
...@@ -377,21 +375,27 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) ...@@ -377,21 +375,27 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
struct dma_chan *chan; struct dma_chan *chan;
dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len); dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len);
reinit_completion(&i2c_dev->dma_complete); reinit_completion(&i2c_dev->dma_complete);
dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan; chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan;
dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys, dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys,
len, dir, DMA_PREP_INTERRUPT | len, dir, DMA_PREP_INTERRUPT |
DMA_CTRL_ACK); DMA_CTRL_ACK);
if (!dma_desc) { if (!dma_desc) {
dev_err(i2c_dev->dev, "failed to get DMA descriptor\n"); dev_err(i2c_dev->dev, "failed to get %s DMA descriptor\n",
i2c_dev->msg_read ? "RX" : "TX");
return -EINVAL; return -EINVAL;
} }
dma_desc->callback = tegra_i2c_dma_complete; dma_desc->callback = tegra_i2c_dma_complete;
dma_desc->callback_param = i2c_dev; dma_desc->callback_param = i2c_dev;
dmaengine_submit(dma_desc); dmaengine_submit(dma_desc);
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
return 0; return 0;
} }
...@@ -417,15 +421,15 @@ static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev) ...@@ -417,15 +421,15 @@ static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev)
static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
{ {
struct dma_chan *chan; struct dma_chan *chan;
u32 *dma_buf;
dma_addr_t dma_phys; dma_addr_t dma_phys;
u32 *dma_buf;
int err; int err;
if (!i2c_dev->hw->has_apb_dma || i2c_dev->is_vi) if (!i2c_dev->hw->has_apb_dma || i2c_dev->is_vi)
return 0; return 0;
if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) { if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
dev_dbg(i2c_dev->dev, "Support for APB DMA not enabled!\n"); dev_dbg(i2c_dev->dev, "DMA support not enabled\n");
return 0; return 0;
} }
...@@ -445,16 +449,20 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) ...@@ -445,16 +449,20 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
i2c_dev->tx_dma_chan = chan; i2c_dev->tx_dma_chan = chan;
i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len +
I2C_PACKET_HEADER_SIZE;
dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size, dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
&dma_phys, GFP_KERNEL | __GFP_NOWARN); &dma_phys, GFP_KERNEL | __GFP_NOWARN);
if (!dma_buf) { if (!dma_buf) {
dev_err(i2c_dev->dev, "failed to allocate the DMA buffer\n"); dev_err(i2c_dev->dev, "failed to allocate DMA buffer\n");
err = -ENOMEM; err = -ENOMEM;
goto err_out; goto err_out;
} }
i2c_dev->dma_buf = dma_buf; i2c_dev->dma_buf = dma_buf;
i2c_dev->dma_phys = dma_phys; i2c_dev->dma_phys = dma_phys;
return 0; return 0;
err_out: err_out:
...@@ -468,171 +476,12 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) ...@@ -468,171 +476,12 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
return err; return err;
} }
static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
{
unsigned long timeout = jiffies + HZ;
unsigned int offset;
u32 mask, val;
if (i2c_dev->hw->has_mst_fifo) {
mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
I2C_MST_FIFO_CONTROL_RX_FLUSH;
offset = I2C_MST_FIFO_CONTROL;
} else {
mask = I2C_FIFO_CONTROL_TX_FLUSH |
I2C_FIFO_CONTROL_RX_FLUSH;
offset = I2C_FIFO_CONTROL;
}
val = i2c_readl(i2c_dev, offset);
val |= mask;
i2c_writel(i2c_dev, val, offset);
while (i2c_readl(i2c_dev, offset) & mask) {
if (time_after(jiffies, timeout)) {
dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
return -ETIMEDOUT;
}
usleep_range(1000, 2000);
}
return 0;
}
static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
int rx_fifo_avail;
u8 *buf = i2c_dev->msg_buf;
size_t buf_remaining = i2c_dev->msg_buf_remaining;
int words_to_transfer;
/*
* Catch overflow due to message fully sent
* before the check for RX FIFO availability.
*/
if (WARN_ON_ONCE(!(i2c_dev->msg_buf_remaining)))
return -EINVAL;
if (i2c_dev->hw->has_mst_fifo) {
val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val);
} else {
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val);
}
/* Rounds down to not include partial word at the end of buf */
words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
if (words_to_transfer > rx_fifo_avail)
words_to_transfer = rx_fifo_avail;
i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
rx_fifo_avail -= words_to_transfer;
/*
* If there is a partial word at the end of buf, handle it manually to
* prevent overwriting past the end of buf
*/
if (rx_fifo_avail > 0 && buf_remaining > 0) {
/*
* buf_remaining > 3 check not needed as rx_fifo_avail == 0
* when (words_to_transfer was > rx_fifo_avail) earlier
* in this function.
*/
val = i2c_readl(i2c_dev, I2C_RX_FIFO);
val = cpu_to_le32(val);
memcpy(buf, &val, buf_remaining);
buf_remaining = 0;
rx_fifo_avail--;
}
/* RX FIFO must be drained, otherwise it's an Overflow case. */
if (WARN_ON_ONCE(rx_fifo_avail))
return -EINVAL;
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf;
return 0;
}
static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
int tx_fifo_avail;
u8 *buf = i2c_dev->msg_buf;
size_t buf_remaining = i2c_dev->msg_buf_remaining;
int words_to_transfer;
if (i2c_dev->hw->has_mst_fifo) {
val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val);
} else {
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val);
}
/* Rounds down to not include partial word at the end of buf */
words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
/* It's very common to have < 4 bytes, so optimize that case. */
if (words_to_transfer) {
if (words_to_transfer > tx_fifo_avail)
words_to_transfer = tx_fifo_avail;
/*
* Update state before writing to FIFO. If this casues us
* to finish writing all bytes (AKA buf_remaining goes to 0) we
* have a potential for an interrupt (PACKET_XFER_COMPLETE is
* not maskable). We need to make sure that the isr sees
* buf_remaining as 0 and doesn't call us back re-entrantly.
*/
buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
tx_fifo_avail -= words_to_transfer;
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf +
words_to_transfer * BYTES_PER_FIFO_WORD;
barrier();
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
}
/*
* If there is a partial word at the end of buf, handle it manually to
* prevent reading past the end of buf, which could cross a page
* boundary and fault.
*/
if (tx_fifo_avail > 0 && buf_remaining > 0) {
/*
* buf_remaining > 3 check not needed as tx_fifo_avail == 0
* when (words_to_transfer was > tx_fifo_avail) earlier
* in this function for non-zero words_to_transfer.
*/
memcpy(&val, buf, buf_remaining);
val = le32_to_cpu(val);
/* Again update before writing to FIFO to make sure isr sees. */
i2c_dev->msg_buf_remaining = 0;
i2c_dev->msg_buf = NULL;
barrier();
i2c_writel(i2c_dev, val, I2C_TX_FIFO);
}
return 0;
}
/* /*
* One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller) * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller)
* block. This block is identical to the rest of the I2C blocks, except that * block. This block is identical to the rest of the I2C blocks, except that
* it only supports master mode, it has registers moved around, and it needs * it only supports master mode, it has registers moved around, and it needs
* some extra init to get it into I2C mode. The register moves are handled * some extra init to get it into I2C mode. The register moves are handled
* by i2c_readl and i2c_writel * by i2c_readl() and i2c_writel().
*/ */
static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
{ {
...@@ -648,140 +497,112 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) ...@@ -648,140 +497,112 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
dvc_writel(i2c_dev, val, DVC_CTRL_REG1); dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
} }
static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
{ {
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); u32 value;
int ret;
ret = pinctrl_pm_select_default_state(i2c_dev->dev);
if (ret)
return ret;
ret = clk_enable(i2c_dev->fast_clk); value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
if (ret < 0) { FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
dev_err(i2c_dev->dev, i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0);
"Enabling fast clk failed, err %d\n", ret);
return ret;
}
ret = clk_enable(i2c_dev->slow_clk); value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) |
if (ret < 0) { FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) |
dev_err(dev, "failed to enable slow clock: %d\n", ret); FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) |
goto disable_fast_clk; FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4);
} i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1);
ret = clk_enable(i2c_dev->div_clk); value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) |
if (ret < 0) { FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8);
dev_err(i2c_dev->dev, i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0);
"Enabling div clk failed, err %d\n", ret);
goto disable_slow_clk;
}
/* value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) |
* VI I2C device is attached to VE power domain which goes through FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) |
* power ON/OFF during PM runtime resume/suspend. So, controller FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11);
* should go through reset and need to re-initialize after power i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1);
* domain ON.
*/
if (i2c_dev->is_vi) {
ret = tegra_i2c_init(i2c_dev, true);
if (ret)
goto disable_div_clk;
}
return 0; value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND;
i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG);
disable_div_clk: i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT);
clk_disable(i2c_dev->div_clk);
disable_slow_clk:
clk_disable(i2c_dev->slow_clk);
disable_fast_clk:
clk_disable(i2c_dev->fast_clk);
return ret;
} }
static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev) static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev,
u32 reg, u32 mask, u32 delay_us,
u32 timeout_us)
{ {
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
u32 val;
clk_disable(i2c_dev->div_clk); if (!i2c_dev->atomic_mode)
clk_disable(i2c_dev->slow_clk); return readl_relaxed_poll_timeout(addr, val, !(val & mask),
clk_disable(i2c_dev->fast_clk); delay_us, timeout_us);
return pinctrl_pm_select_idle_state(i2c_dev->dev); return readl_relaxed_poll_timeout_atomic(addr, val, !(val & mask),
delay_us, timeout_us);
} }
static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
{ {
unsigned long reg_offset; u32 mask, val, offset;
void __iomem *addr;
u32 val;
int err; int err;
if (i2c_dev->hw->has_config_load_reg) { if (i2c_dev->hw->has_mst_fifo) {
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD); mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
addr = i2c_dev->base + reg_offset; I2C_MST_FIFO_CONTROL_RX_FLUSH;
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); offset = I2C_MST_FIFO_CONTROL;
} else {
mask = I2C_FIFO_CONTROL_TX_FLUSH |
I2C_FIFO_CONTROL_RX_FLUSH;
offset = I2C_FIFO_CONTROL;
}
if (i2c_dev->is_curr_atomic_xfer) val = i2c_readl(i2c_dev, offset);
err = readl_relaxed_poll_timeout_atomic( val |= mask;
addr, val, val == 0, 1000, i2c_writel(i2c_dev, val, offset);
I2C_CONFIG_LOAD_TIMEOUT);
else
err = readl_relaxed_poll_timeout(
addr, val, val == 0, 1000,
I2C_CONFIG_LOAD_TIMEOUT);
err = tegra_i2c_poll_register(i2c_dev, offset, mask, 1000, 1000000);
if (err) { if (err) {
dev_warn(i2c_dev->dev, dev_err(i2c_dev->dev, "failed to flush FIFO\n");
"timeout waiting for config load\n");
return err; return err;
} }
}
return 0; return 0;
} }
static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev) static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
{ {
u32 value; int err;
value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0);
value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) |
FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) |
FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) |
FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4);
i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1);
value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) | if (!i2c_dev->hw->has_config_load_reg)
FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8); return 0;
i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0);
value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) | i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) |
FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11);
i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1);
value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND; err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0xffffffff,
i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG); 1000, I2C_CONFIG_LOAD_TIMEOUT);
if (err) {
dev_err(i2c_dev->dev, "failed to load config\n");
return err;
}
i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT); return 0;
} }
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
{ {
u32 val; u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode;
int err; int err;
u32 clk_divisor, clk_multiplier;
u32 tsu_thd;
u8 tlow, thigh;
reset_control_assert(i2c_dev->rst); /*
udelay(2); * The reset shouldn't ever fail in practice. The failure will be a
reset_control_deassert(i2c_dev->rst); * sign of a severe problem that needs to be resolved. Still we don't
* want to fail the initialization completely because this may break
* kernel boot up since voltage regulators use I2C. Hence, we will
* emit a noisy warning on error, which won't stay unnoticed and
* won't hose machine entirely.
*/
err = reset_control_reset(i2c_dev->rst);
WARN_ON_ONCE(err);
if (i2c_dev->is_dvc) if (i2c_dev->is_dvc)
tegra_dvc_init(i2c_dev); tegra_dvc_init(i2c_dev);
...@@ -798,24 +619,33 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) ...@@ -798,24 +619,33 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
if (i2c_dev->is_vi) if (i2c_dev->is_vi)
tegra_i2c_vi_init(i2c_dev); tegra_i2c_vi_init(i2c_dev);
/* Make sure clock divisor programmed correctly */ switch (i2c_dev->bus_clk_rate) {
clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE, case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:
i2c_dev->hw->clk_divisor_hs_mode) | default:
FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE,
i2c_dev->clk_divisor_non_hs_mode);
i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR);
if (i2c_dev->bus_clk_rate > I2C_MAX_STANDARD_MODE_FREQ &&
i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ) {
tlow = i2c_dev->hw->tlow_fast_fastplus_mode; tlow = i2c_dev->hw->tlow_fast_fastplus_mode;
thigh = i2c_dev->hw->thigh_fast_fastplus_mode; thigh = i2c_dev->hw->thigh_fast_fastplus_mode;
tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode; tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode;
} else {
if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ)
non_hs_mode = i2c_dev->hw->clk_divisor_fast_plus_mode;
else
non_hs_mode = i2c_dev->hw->clk_divisor_fast_mode;
break;
case 0 ... I2C_MAX_STANDARD_MODE_FREQ:
tlow = i2c_dev->hw->tlow_std_mode; tlow = i2c_dev->hw->tlow_std_mode;
thigh = i2c_dev->hw->thigh_std_mode; thigh = i2c_dev->hw->thigh_std_mode;
tsu_thd = i2c_dev->hw->setup_hold_time_std_mode; tsu_thd = i2c_dev->hw->setup_hold_time_std_mode;
non_hs_mode = i2c_dev->hw->clk_divisor_std_mode;
break;
} }
/* make sure clock divisor programmed correctly */
clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
i2c_dev->hw->clk_divisor_hs_mode) |
FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE, non_hs_mode);
i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR);
if (i2c_dev->hw->has_interface_timing_reg) { if (i2c_dev->hw->has_interface_timing_reg) {
val = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, thigh) | val = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, thigh) |
FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, tlow); FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, tlow);
...@@ -823,23 +653,20 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) ...@@ -823,23 +653,20 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
} }
/* /*
* configure setup and hold times only when tsu_thd is non-zero. * Configure setup and hold times only when tsu_thd is non-zero.
* otherwise, preserve the chip default values * Otherwise, preserve the chip default values.
*/ */
if (i2c_dev->hw->has_interface_timing_reg && tsu_thd) if (i2c_dev->hw->has_interface_timing_reg && tsu_thd)
i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1); i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
if (!clk_reinit) { clk_multiplier = (tlow + thigh + 2) * (non_hs_mode + 1);
clk_multiplier = (tlow + thigh + 2);
clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1);
err = clk_set_rate(i2c_dev->div_clk, err = clk_set_rate(i2c_dev->div_clk,
i2c_dev->bus_clk_rate * clk_multiplier); i2c_dev->bus_clk_rate * clk_multiplier);
if (err) { if (err) {
dev_err(i2c_dev->dev, dev_err(i2c_dev->dev, "failed to set div-clk rate: %d\n", err);
"failed changing clock rate: %d\n", err);
return err; return err;
} }
}
if (!i2c_dev->is_dvc && !i2c_dev->is_vi) { if (!i2c_dev->is_dvc && !i2c_dev->is_vi) {
u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
...@@ -854,7 +681,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) ...@@ -854,7 +681,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
if (err) if (err)
return err; return err;
if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg) if (i2c_dev->multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE); i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
err = tegra_i2c_wait_for_config_load(i2c_dev); err = tegra_i2c_wait_for_config_load(i2c_dev);
...@@ -870,7 +697,7 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev) ...@@ -870,7 +697,7 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
/* /*
* NACK interrupt is generated before the I2C controller generates * NACK interrupt is generated before the I2C controller generates
* the STOP condition on the bus. So wait for 2 clock periods * the STOP condition on the bus. So, wait for 2 clock periods
* before disabling the controller so that the STOP condition has * before disabling the controller so that the STOP condition has
* been delivered properly. * been delivered properly.
*/ */
...@@ -883,16 +710,145 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev) ...@@ -883,16 +710,145 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
return tegra_i2c_wait_for_config_load(i2c_dev); return tegra_i2c_wait_for_config_load(i2c_dev);
} }
static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
{
size_t buf_remaining = i2c_dev->msg_buf_remaining;
unsigned int words_to_transfer, rx_fifo_avail;
u8 *buf = i2c_dev->msg_buf;
u32 val;
/*
* Catch overflow due to message fully sent before the check for
* RX FIFO availability.
*/
if (WARN_ON_ONCE(!(i2c_dev->msg_buf_remaining)))
return -EINVAL;
if (i2c_dev->hw->has_mst_fifo) {
val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val);
} else {
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val);
}
/* round down to exclude partial word at the end of buffer */
words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
if (words_to_transfer > rx_fifo_avail)
words_to_transfer = rx_fifo_avail;
i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
rx_fifo_avail -= words_to_transfer;
/*
* If there is a partial word at the end of buffer, handle it
* manually to prevent overwriting past the end of buffer.
*/
if (rx_fifo_avail > 0 && buf_remaining > 0) {
/*
* buf_remaining > 3 check not needed as rx_fifo_avail == 0
* when (words_to_transfer was > rx_fifo_avail) earlier
* in this function.
*/
val = i2c_readl(i2c_dev, I2C_RX_FIFO);
val = cpu_to_le32(val);
memcpy(buf, &val, buf_remaining);
buf_remaining = 0;
rx_fifo_avail--;
}
/* RX FIFO must be drained, otherwise it's an Overflow case. */
if (WARN_ON_ONCE(rx_fifo_avail))
return -EINVAL;
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf;
return 0;
}
static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
{
size_t buf_remaining = i2c_dev->msg_buf_remaining;
unsigned int words_to_transfer, tx_fifo_avail;
u8 *buf = i2c_dev->msg_buf;
u32 val;
if (i2c_dev->hw->has_mst_fifo) {
val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val);
} else {
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val);
}
/* round down to exclude partial word at the end of buffer */
words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
/*
* This hunk pushes 4 bytes at a time into the TX FIFO.
*
* It's very common to have < 4 bytes, hence there is no word
* to push if we have less than 4 bytes to transfer.
*/
if (words_to_transfer) {
if (words_to_transfer > tx_fifo_avail)
words_to_transfer = tx_fifo_avail;
/*
* Update state before writing to FIFO. Note that this may
* cause us to finish writing all bytes (AKA buf_remaining
* goes to 0), hence we have a potential for an interrupt
* (PACKET_XFER_COMPLETE is not maskable), but GIC interrupt
* is disabled at this point.
*/
buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
tx_fifo_avail -= words_to_transfer;
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
}
/*
* If there is a partial word at the end of buffer, handle it manually
* to prevent reading past the end of buffer, which could cross a page
* boundary and fault.
*/
if (tx_fifo_avail > 0 && buf_remaining > 0) {
/*
* buf_remaining > 3 check not needed as tx_fifo_avail == 0
* when (words_to_transfer was > tx_fifo_avail) earlier
* in this function for non-zero words_to_transfer.
*/
memcpy(&val, buf, buf_remaining);
val = le32_to_cpu(val);
i2c_dev->msg_buf_remaining = 0;
i2c_dev->msg_buf = NULL;
i2c_writel(i2c_dev, val, I2C_TX_FIFO);
}
return 0;
}
static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) 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; const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
struct tegra_i2c_dev *i2c_dev = dev_id; struct tegra_i2c_dev *i2c_dev = dev_id;
u32 status;
status = i2c_readl(i2c_dev, I2C_INT_STATUS); status = i2c_readl(i2c_dev, I2C_INT_STATUS);
if (status == 0) { if (status == 0) {
dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n", dev_warn(i2c_dev->dev, "IRQ status 0 %08x %08x %08x\n",
i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
i2c_readl(i2c_dev, I2C_STATUS), i2c_readl(i2c_dev, I2C_STATUS),
i2c_readl(i2c_dev, I2C_CNFG)); i2c_readl(i2c_dev, I2C_CNFG));
...@@ -900,7 +856,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -900,7 +856,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
goto err; goto err;
} }
if (unlikely(status & status_err)) { if (status & status_err) {
tegra_i2c_disable_packet_mode(i2c_dev); tegra_i2c_disable_packet_mode(i2c_dev);
if (status & I2C_INT_NO_ACK) if (status & I2C_INT_NO_ACK)
i2c_dev->msg_err |= I2C_ERR_NO_ACK; i2c_dev->msg_err |= I2C_ERR_NO_ACK;
...@@ -910,13 +866,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -910,13 +866,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
} }
/* /*
* I2C transfer is terminated during the bus clear so skip * I2C transfer is terminated during the bus clear, so skip
* processing the other interrupts. * processing the other interrupts.
*/ */
if (i2c_dev->hw->supports_bus_clear && (status & I2C_INT_BUS_CLR_DONE)) if (i2c_dev->hw->supports_bus_clear && (status & I2C_INT_BUS_CLR_DONE))
goto err; goto err;
if (!i2c_dev->is_curr_dma_xfer) { if (!i2c_dev->dma_mode) {
if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) {
if (tegra_i2c_empty_rx_fifo(i2c_dev)) { if (tegra_i2c_empty_rx_fifo(i2c_dev)) {
/* /*
...@@ -946,11 +902,12 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -946,11 +902,12 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
* During message read XFER_COMPLETE interrupt is triggered prior to * During message read XFER_COMPLETE interrupt is triggered prior to
* DMA completion and during message write XFER_COMPLETE interrupt is * DMA completion and during message write XFER_COMPLETE interrupt is
* triggered after DMA completion. * triggered after DMA completion.
* PACKETS_XFER_COMPLETE indicates completion of all bytes of transfer. *
* PACKETS_XFER_COMPLETE indicates completion of all bytes of transfer,
* so forcing msg_buf_remaining to 0 in DMA mode. * so forcing msg_buf_remaining to 0 in DMA mode.
*/ */
if (status & I2C_INT_PACKET_XFER_COMPLETE) { if (status & I2C_INT_PACKET_XFER_COMPLETE) {
if (i2c_dev->is_curr_dma_xfer) if (i2c_dev->dma_mode)
i2c_dev->msg_buf_remaining = 0; i2c_dev->msg_buf_remaining = 0;
/* /*
* Underflow error condition: XFER_COMPLETE before message * Underflow error condition: XFER_COMPLETE before message
...@@ -964,17 +921,23 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -964,17 +921,23 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
} }
goto done; goto done;
err: err:
/* An error occurred, mask all interrupts */ /* mask all interrupts on error */
tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST | tegra_i2c_mask_irq(i2c_dev,
I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ | I2C_INT_NO_ACK |
I2C_INT_ARBITRATION_LOST |
I2C_INT_PACKET_XFER_COMPLETE |
I2C_INT_TX_FIFO_DATA_REQ |
I2C_INT_RX_FIFO_DATA_REQ); I2C_INT_RX_FIFO_DATA_REQ);
if (i2c_dev->hw->supports_bus_clear) if (i2c_dev->hw->supports_bus_clear)
tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
i2c_writel(i2c_dev, status, I2C_INT_STATUS); i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc) if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
if (i2c_dev->is_curr_dma_xfer) { if (i2c_dev->dma_mode) {
if (i2c_dev->msg_read) if (i2c_dev->msg_read)
dmaengine_terminate_async(i2c_dev->rx_dma_chan); dmaengine_terminate_async(i2c_dev->rx_dma_chan);
else else
...@@ -991,19 +954,17 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -991,19 +954,17 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
size_t len) size_t len)
{ {
u32 val, reg;
u8 dma_burst;
struct dma_slave_config slv_config = {0}; struct dma_slave_config slv_config = {0};
u32 val, reg, dma_burst, reg_offset;
struct dma_chan *chan; struct dma_chan *chan;
int ret; int err;
unsigned long reg_offset;
if (i2c_dev->hw->has_mst_fifo) if (i2c_dev->hw->has_mst_fifo)
reg = I2C_MST_FIFO_CONTROL; reg = I2C_MST_FIFO_CONTROL;
else else
reg = I2C_FIFO_CONTROL; reg = I2C_FIFO_CONTROL;
if (i2c_dev->is_curr_dma_xfer) { if (i2c_dev->dma_mode) {
if (len & 0xF) if (len & 0xF)
dma_burst = 1; dma_burst = 1;
else if (len & 0x10) else if (len & 0x10)
...@@ -1014,6 +975,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, ...@@ -1014,6 +975,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
if (i2c_dev->msg_read) { if (i2c_dev->msg_read) {
chan = i2c_dev->rx_dma_chan; chan = i2c_dev->rx_dma_chan;
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO); reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO);
slv_config.src_addr = i2c_dev->base_phys + reg_offset; slv_config.src_addr = i2c_dev->base_phys + reg_offset;
slv_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slv_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slv_config.src_maxburst = dma_burst; slv_config.src_maxburst = dma_burst;
...@@ -1025,6 +987,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, ...@@ -1025,6 +987,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
} else { } else {
chan = i2c_dev->tx_dma_chan; chan = i2c_dev->tx_dma_chan;
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO); reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO);
slv_config.dst_addr = i2c_dev->base_phys + reg_offset; slv_config.dst_addr = i2c_dev->base_phys + reg_offset;
slv_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slv_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slv_config.dst_maxburst = dma_burst; slv_config.dst_maxburst = dma_burst;
...@@ -1036,13 +999,13 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, ...@@ -1036,13 +999,13 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
} }
slv_config.device_fc = true; slv_config.device_fc = true;
ret = dmaengine_slave_config(chan, &slv_config); err = dmaengine_slave_config(chan, &slv_config);
if (ret < 0) { if (err) {
dev_err(i2c_dev->dev, "DMA slave config failed: %d\n", dev_err(i2c_dev->dev, "DMA config failed: %d\n", err);
ret);
dev_err(i2c_dev->dev, "falling back to PIO\n"); dev_err(i2c_dev->dev, "falling back to PIO\n");
tegra_i2c_release_dma(i2c_dev); tegra_i2c_release_dma(i2c_dev);
i2c_dev->is_curr_dma_xfer = false; i2c_dev->dma_mode = false;
} else { } else {
goto out; goto out;
} }
...@@ -1058,8 +1021,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, ...@@ -1058,8 +1021,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
i2c_writel(i2c_dev, val, reg); i2c_writel(i2c_dev, val, reg);
} }
static unsigned long static unsigned long tegra_i2c_poll_completion(struct tegra_i2c_dev *i2c_dev,
tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
struct completion *complete, struct completion *complete,
unsigned int timeout_ms) unsigned int timeout_ms)
{ {
...@@ -1085,16 +1047,14 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev, ...@@ -1085,16 +1047,14 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
return 0; return 0;
} }
static unsigned long static unsigned long tegra_i2c_wait_completion(struct tegra_i2c_dev *i2c_dev,
tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
struct completion *complete, struct completion *complete,
unsigned int timeout_ms) unsigned int timeout_ms)
{ {
unsigned long ret; unsigned long ret;
if (i2c_dev->is_curr_atomic_xfer) { if (i2c_dev->atomic_mode) {
ret = tegra_i2c_poll_completion_timeout(i2c_dev, complete, ret = tegra_i2c_poll_completion(i2c_dev, complete, timeout_ms);
timeout_ms);
} else { } else {
enable_irq(i2c_dev->irq); enable_irq(i2c_dev->irq);
ret = wait_for_completion_timeout(complete, ret = wait_for_completion_timeout(complete,
...@@ -1112,8 +1072,7 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev, ...@@ -1112,8 +1072,7 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
* needs to be checked after timeout. * needs to be checked after timeout.
*/ */
if (ret == 0) if (ret == 0)
ret = tegra_i2c_poll_completion_timeout(i2c_dev, ret = tegra_i2c_poll_completion(i2c_dev, complete, 0);
complete, 0);
} }
return ret; return ret;
...@@ -1122,60 +1081,134 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev, ...@@ -1122,60 +1081,134 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap) static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
{ {
struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
u32 val, time_left;
int err; int err;
unsigned long time_left;
u32 reg;
reinit_completion(&i2c_dev->msg_complete); reinit_completion(&i2c_dev->msg_complete);
reg = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
val = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
I2C_BC_TERMINATE; I2C_BC_TERMINATE;
i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG); i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
if (i2c_dev->hw->has_config_load_reg) {
err = tegra_i2c_wait_for_config_load(i2c_dev); err = tegra_i2c_wait_for_config_load(i2c_dev);
if (err) if (err)
return err; return err;
}
reg |= I2C_BC_ENABLE; val |= I2C_BC_ENABLE;
i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG); i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
time_left = tegra_i2c_wait_completion_timeout( time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete, 50);
i2c_dev, &i2c_dev->msg_complete, 50); tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
if (time_left == 0) { if (time_left == 0) {
dev_err(i2c_dev->dev, "timed out for bus clear\n"); dev_err(i2c_dev->dev, "failed to clear bus\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
reg = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS); val = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS);
if (!(reg & I2C_BC_STATUS)) { if (!(val & I2C_BC_STATUS)) {
dev_err(i2c_dev->dev, dev_err(i2c_dev->dev, "un-recovered arbitration lost\n");
"un-recovered arbitration lost\n");
return -EIO; return -EIO;
} }
return -EAGAIN; return -EAGAIN;
} }
static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg, struct i2c_msg *msg,
enum msg_end_type end_state) enum msg_end_type end_state)
{ {
u32 *dma_buf = i2c_dev->dma_buf;
u32 packet_header; u32 packet_header;
u32 int_mask;
unsigned long time_left; packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) |
FIELD_PREP(PACKET_HEADER0_PROTOCOL,
PACKET_HEADER0_PROTOCOL_I2C) |
FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
if (i2c_dev->dma_mode && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = msg->len - 1;
if (i2c_dev->dma_mode && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = I2C_HEADER_IE_ENABLE;
if (end_state == MSG_END_CONTINUE)
packet_header |= I2C_HEADER_CONTINUE_XFER;
else if (end_state == MSG_END_REPEAT_START)
packet_header |= I2C_HEADER_REPEAT_START;
if (msg->flags & I2C_M_TEN) {
packet_header |= msg->addr;
packet_header |= I2C_HEADER_10BIT_ADDR;
} else {
packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
}
if (msg->flags & I2C_M_IGNORE_NAK)
packet_header |= I2C_HEADER_CONT_ON_NAK;
if (msg->flags & I2C_M_RD)
packet_header |= I2C_HEADER_READ;
if (i2c_dev->dma_mode && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
}
static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg)
{
if (i2c_dev->msg_err == I2C_ERR_NONE)
return 0;
tegra_i2c_init(i2c_dev);
/* start recovery upon arbitration loss in single master mode */
if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) {
if (!i2c_dev->multimaster_mode)
return i2c_recover_bus(&i2c_dev->adapter);
return -EAGAIN;
}
if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
if (msg->flags & I2C_M_IGNORE_NAK)
return 0;
return -EREMOTEIO;
}
return -EIO;
}
static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg,
enum msg_end_type end_state)
{
unsigned long time_left, xfer_time = 100;
size_t xfer_size; size_t xfer_size;
u32 *buffer = NULL; u32 int_mask;
int err = 0; int err;
bool dma;
u16 xfer_time = 100;
tegra_i2c_flush_fifos(i2c_dev); err = tegra_i2c_flush_fifos(i2c_dev);
if (err)
return err;
i2c_dev->msg_buf = msg->buf; i2c_dev->msg_buf = msg->buf;
i2c_dev->msg_buf_remaining = msg->len; i2c_dev->msg_buf_remaining = msg->len;
i2c_dev->msg_err = I2C_ERR_NONE; i2c_dev->msg_err = I2C_ERR_NONE;
i2c_dev->msg_read = (msg->flags & I2C_M_RD); i2c_dev->msg_read = !!(msg->flags & I2C_M_RD);
reinit_completion(&i2c_dev->msg_complete); reinit_completion(&i2c_dev->msg_complete);
if (i2c_dev->msg_read) if (i2c_dev->msg_read)
...@@ -1184,11 +1217,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -1184,11 +1217,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
xfer_size = msg->len + I2C_PACKET_HEADER_SIZE; xfer_size = msg->len + I2C_PACKET_HEADER_SIZE;
xfer_size = ALIGN(xfer_size, BYTES_PER_FIFO_WORD); xfer_size = ALIGN(xfer_size, BYTES_PER_FIFO_WORD);
i2c_dev->is_curr_dma_xfer = (xfer_size > I2C_PIO_MODE_PREFERRED_LEN) &&
i2c_dev->dma_buf && i2c_dev->dma_mode = xfer_size > I2C_PIO_MODE_PREFERRED_LEN &&
!i2c_dev->is_curr_atomic_xfer; i2c_dev->dma_buf && !i2c_dev->atomic_mode;
tegra_i2c_config_fifo_trig(i2c_dev, xfer_size); tegra_i2c_config_fifo_trig(i2c_dev, xfer_size);
dma = i2c_dev->is_curr_dma_xfer;
/* /*
* Transfer time in mSec = Total bits / transfer rate * Transfer time in mSec = Total bits / transfer rate
* Total bits = 9 bits per byte (including ACK bit) + Start & stop bits * Total bits = 9 bits per byte (including ACK bit) + Start & stop bits
...@@ -1198,79 +1232,37 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -1198,79 +1232,37 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
tegra_i2c_unmask_irq(i2c_dev, int_mask); tegra_i2c_unmask_irq(i2c_dev, int_mask);
if (dma) {
if (i2c_dev->dma_mode) {
if (i2c_dev->msg_read) { if (i2c_dev->msg_read) {
dma_sync_single_for_device(i2c_dev->dev, dma_sync_single_for_device(i2c_dev->dev,
i2c_dev->dma_phys, i2c_dev->dma_phys,
xfer_size, xfer_size, DMA_FROM_DEVICE);
DMA_FROM_DEVICE);
err = tegra_i2c_dma_submit(i2c_dev, xfer_size); err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
if (err < 0) { if (err)
dev_err(i2c_dev->dev,
"starting RX DMA failed, err %d\n",
err);
return err; return err;
}
} else { } else {
dma_sync_single_for_cpu(i2c_dev->dev, dma_sync_single_for_cpu(i2c_dev->dev,
i2c_dev->dma_phys, i2c_dev->dma_phys,
xfer_size, xfer_size, DMA_TO_DEVICE);
DMA_TO_DEVICE);
buffer = i2c_dev->dma_buf;
} }
} }
packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) | tegra_i2c_push_packet_header(i2c_dev, msg, end_state);
FIELD_PREP(PACKET_HEADER0_PROTOCOL,
PACKET_HEADER0_PROTOCOL_I2C) |
FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
if (dma && !i2c_dev->msg_read)
*buffer++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = msg->len - 1;
if (dma && !i2c_dev->msg_read)
*buffer++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = I2C_HEADER_IE_ENABLE;
if (end_state == MSG_END_CONTINUE)
packet_header |= I2C_HEADER_CONTINUE_XFER;
else if (end_state == MSG_END_REPEAT_START)
packet_header |= I2C_HEADER_REPEAT_START;
if (msg->flags & I2C_M_TEN) {
packet_header |= msg->addr;
packet_header |= I2C_HEADER_10BIT_ADDR;
} else {
packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
}
if (msg->flags & I2C_M_IGNORE_NAK)
packet_header |= I2C_HEADER_CONT_ON_NAK;
if (msg->flags & I2C_M_RD)
packet_header |= I2C_HEADER_READ;
if (dma && !i2c_dev->msg_read)
*buffer++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
if (!i2c_dev->msg_read) { if (!i2c_dev->msg_read) {
if (dma) { if (i2c_dev->dma_mode) {
memcpy(buffer, msg->buf, msg->len); memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE,
msg->buf, msg->len);
dma_sync_single_for_device(i2c_dev->dev, dma_sync_single_for_device(i2c_dev->dev,
i2c_dev->dma_phys, i2c_dev->dma_phys,
xfer_size, xfer_size, DMA_TO_DEVICE);
DMA_TO_DEVICE);
err = tegra_i2c_dma_submit(i2c_dev, xfer_size); err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
if (err < 0) { if (err)
dev_err(i2c_dev->dev,
"starting TX DMA failed, err %d\n",
err);
return err; return err;
}
} else { } else {
tegra_i2c_fill_tx_fifo(i2c_dev); tegra_i2c_fill_tx_fifo(i2c_dev);
} }
...@@ -1278,7 +1270,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -1278,7 +1270,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
if (i2c_dev->hw->has_per_pkt_xfer_complete_irq) if (i2c_dev->hw->has_per_pkt_xfer_complete_irq)
int_mask |= I2C_INT_PACKET_XFER_COMPLETE; int_mask |= I2C_INT_PACKET_XFER_COMPLETE;
if (!dma) {
if (!i2c_dev->dma_mode) {
if (msg->flags & I2C_M_RD) if (msg->flags & I2C_M_RD)
int_mask |= I2C_INT_RX_FIFO_DATA_REQ; int_mask |= I2C_INT_RX_FIFO_DATA_REQ;
else if (i2c_dev->msg_buf_remaining) else if (i2c_dev->msg_buf_remaining)
...@@ -1286,12 +1279,13 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -1286,12 +1279,13 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
} }
tegra_i2c_unmask_irq(i2c_dev, int_mask); tegra_i2c_unmask_irq(i2c_dev, int_mask);
dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n", dev_dbg(i2c_dev->dev, "unmasked IRQ: %02x\n",
i2c_readl(i2c_dev, I2C_INT_MASK)); i2c_readl(i2c_dev, I2C_INT_MASK));
if (dma) { if (i2c_dev->dma_mode) {
time_left = tegra_i2c_wait_completion_timeout( time_left = tegra_i2c_wait_completion(i2c_dev,
i2c_dev, &i2c_dev->dma_complete, xfer_time); &i2c_dev->dma_complete,
xfer_time);
/* /*
* Synchronize DMA first, since dmaengine_terminate_sync() * Synchronize DMA first, since dmaengine_terminate_sync()
...@@ -1307,29 +1301,28 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -1307,29 +1301,28 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
i2c_dev->tx_dma_chan); i2c_dev->tx_dma_chan);
if (!time_left && !completion_done(&i2c_dev->dma_complete)) { if (!time_left && !completion_done(&i2c_dev->dma_complete)) {
dev_err(i2c_dev->dev, "DMA transfer timeout\n"); dev_err(i2c_dev->dev, "DMA transfer timed out\n");
tegra_i2c_init(i2c_dev, true); tegra_i2c_init(i2c_dev);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) { if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) {
dma_sync_single_for_cpu(i2c_dev->dev, dma_sync_single_for_cpu(i2c_dev->dev,
i2c_dev->dma_phys, i2c_dev->dma_phys,
xfer_size, xfer_size, DMA_FROM_DEVICE);
DMA_FROM_DEVICE);
memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf, memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf, msg->len);
msg->len);
} }
} }
time_left = tegra_i2c_wait_completion_timeout( time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete,
i2c_dev, &i2c_dev->msg_complete, xfer_time); xfer_time);
tegra_i2c_mask_irq(i2c_dev, int_mask); tegra_i2c_mask_irq(i2c_dev, int_mask);
if (time_left == 0) { if (time_left == 0) {
dev_err(i2c_dev->dev, "i2c transfer timed out\n"); dev_err(i2c_dev->dev, "I2C transfer timed out\n");
tegra_i2c_init(i2c_dev, true); tegra_i2c_init(i2c_dev);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -1337,37 +1330,25 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -1337,37 +1330,25 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
time_left, completion_done(&i2c_dev->msg_complete), time_left, completion_done(&i2c_dev->msg_complete),
i2c_dev->msg_err); i2c_dev->msg_err);
i2c_dev->is_curr_dma_xfer = false; i2c_dev->dma_mode = false;
if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
return 0;
tegra_i2c_init(i2c_dev, true); err = tegra_i2c_error_recover(i2c_dev, msg);
/* start recovery upon arbitration loss in single master mode */ if (err)
if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) { return err;
if (!i2c_dev->is_multimaster_mode)
return i2c_recover_bus(&i2c_dev->adapter);
return -EAGAIN;
}
if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
if (msg->flags & I2C_M_IGNORE_NAK)
return 0; return 0;
return -EREMOTEIO;
}
return -EIO;
} }
static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
int num) int num)
{ {
struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
int i; int i, ret;
int ret;
ret = pm_runtime_get_sync(i2c_dev->dev); ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0) { if (ret < 0) {
dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret); dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret);
pm_runtime_put_noidle(i2c_dev->dev);
return ret; return ret;
} }
...@@ -1375,6 +1356,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ...@@ -1375,6 +1356,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
enum msg_end_type end_type = MSG_END_STOP; enum msg_end_type end_type = MSG_END_STOP;
if (i < (num - 1)) { if (i < (num - 1)) {
/* check whether follow up message is coming */
if (msgs[i + 1].flags & I2C_M_NOSTART) if (msgs[i + 1].flags & I2C_M_NOSTART)
end_type = MSG_END_CONTINUE; end_type = MSG_END_CONTINUE;
else else
...@@ -1396,9 +1378,9 @@ static int tegra_i2c_xfer_atomic(struct i2c_adapter *adap, ...@@ -1396,9 +1378,9 @@ static int tegra_i2c_xfer_atomic(struct i2c_adapter *adap,
struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
int ret; int ret;
i2c_dev->is_curr_atomic_xfer = true; i2c_dev->atomic_mode = true;
ret = tegra_i2c_xfer(adap, msgs, num); ret = tegra_i2c_xfer(adap, msgs, num);
i2c_dev->is_curr_atomic_xfer = false; i2c_dev->atomic_mode = false;
return ret; return ret;
} }
...@@ -1411,22 +1393,8 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap) ...@@ -1411,22 +1393,8 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
if (i2c_dev->hw->has_continue_xfer_support) if (i2c_dev->hw->has_continue_xfer_support)
ret |= I2C_FUNC_NOSTART; ret |= I2C_FUNC_NOSTART;
return ret;
}
static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
{
struct device_node *np = i2c_dev->dev->of_node;
int ret;
bool multi_mode;
ret = of_property_read_u32(np, "clock-frequency",
&i2c_dev->bus_clk_rate);
if (ret)
i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; /* default clock rate */
multi_mode = of_property_read_bool(np, "multi-master"); return ret;
i2c_dev->is_multimaster_mode = multi_mode;
} }
static const struct i2c_algorithm tegra_i2c_algo = { static const struct i2c_algorithm tegra_i2c_algo = {
...@@ -1454,7 +1422,6 @@ static struct i2c_bus_recovery_info tegra_i2c_recovery_info = { ...@@ -1454,7 +1422,6 @@ static struct i2c_bus_recovery_info tegra_i2c_recovery_info = {
static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
.has_continue_xfer_support = false, .has_continue_xfer_support = false,
.has_per_pkt_xfer_complete_irq = false, .has_per_pkt_xfer_complete_irq = false,
.has_single_clk_source = false,
.clk_divisor_hs_mode = 3, .clk_divisor_hs_mode = 3,
.clk_divisor_std_mode = 0, .clk_divisor_std_mode = 0,
.clk_divisor_fast_mode = 0, .clk_divisor_fast_mode = 0,
...@@ -1479,7 +1446,6 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { ...@@ -1479,7 +1446,6 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
.has_continue_xfer_support = true, .has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = false, .has_per_pkt_xfer_complete_irq = false,
.has_single_clk_source = false,
.clk_divisor_hs_mode = 3, .clk_divisor_hs_mode = 3,
.clk_divisor_std_mode = 0, .clk_divisor_std_mode = 0,
.clk_divisor_fast_mode = 0, .clk_divisor_fast_mode = 0,
...@@ -1504,7 +1470,6 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { ...@@ -1504,7 +1470,6 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
.has_continue_xfer_support = true, .has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true, .has_per_pkt_xfer_complete_irq = true,
.has_single_clk_source = true,
.clk_divisor_hs_mode = 1, .clk_divisor_hs_mode = 1,
.clk_divisor_std_mode = 0x19, .clk_divisor_std_mode = 0x19,
.clk_divisor_fast_mode = 0x19, .clk_divisor_fast_mode = 0x19,
...@@ -1529,7 +1494,6 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { ...@@ -1529,7 +1494,6 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
.has_continue_xfer_support = true, .has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true, .has_per_pkt_xfer_complete_irq = true,
.has_single_clk_source = true,
.clk_divisor_hs_mode = 1, .clk_divisor_hs_mode = 1,
.clk_divisor_std_mode = 0x19, .clk_divisor_std_mode = 0x19,
.clk_divisor_fast_mode = 0x19, .clk_divisor_fast_mode = 0x19,
...@@ -1554,7 +1518,6 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { ...@@ -1554,7 +1518,6 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
.has_continue_xfer_support = true, .has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true, .has_per_pkt_xfer_complete_irq = true,
.has_single_clk_source = true,
.clk_divisor_hs_mode = 1, .clk_divisor_hs_mode = 1,
.clk_divisor_std_mode = 0x19, .clk_divisor_std_mode = 0x19,
.clk_divisor_fast_mode = 0x19, .clk_divisor_fast_mode = 0x19,
...@@ -1579,7 +1542,6 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { ...@@ -1579,7 +1542,6 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
static const struct tegra_i2c_hw_feature tegra186_i2c_hw = { static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
.has_continue_xfer_support = true, .has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true, .has_per_pkt_xfer_complete_irq = true,
.has_single_clk_source = true,
.clk_divisor_hs_mode = 1, .clk_divisor_hs_mode = 1,
.clk_divisor_std_mode = 0x16, .clk_divisor_std_mode = 0x16,
.clk_divisor_fast_mode = 0x19, .clk_divisor_fast_mode = 0x19,
...@@ -1604,7 +1566,6 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = { ...@@ -1604,7 +1566,6 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
.has_continue_xfer_support = true, .has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true, .has_per_pkt_xfer_complete_irq = true,
.has_single_clk_source = true,
.clk_divisor_hs_mode = 1, .clk_divisor_hs_mode = 1,
.clk_divisor_std_mode = 0x4f, .clk_divisor_std_mode = 0x4f,
.clk_divisor_fast_mode = 0x3c, .clk_divisor_fast_mode = 0x3c,
...@@ -1626,7 +1587,6 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { ...@@ -1626,7 +1587,6 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
.has_interface_timing_reg = true, .has_interface_timing_reg = true,
}; };
/* Match table for of_platform binding */
static const struct of_device_id tegra_i2c_of_match[] = { static const struct of_device_id tegra_i2c_of_match[] = {
{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, }, { .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
{ .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, }, { .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, },
...@@ -1641,223 +1601,196 @@ static const struct of_device_id tegra_i2c_of_match[] = { ...@@ -1641,223 +1601,196 @@ static const struct of_device_id tegra_i2c_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
static int tegra_i2c_probe(struct platform_device *pdev) static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
{ {
struct device *dev = &pdev->dev; struct device_node *np = i2c_dev->dev->of_node;
struct tegra_i2c_dev *i2c_dev; bool multi_mode;
struct resource *res; int err;
struct clk *div_clk;
struct clk *fast_clk; err = of_property_read_u32(np, "clock-frequency",
void __iomem *base; &i2c_dev->bus_clk_rate);
phys_addr_t base_phys; if (err)
int irq; i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); multi_mode = of_property_read_bool(np, "multi-master");
base_phys = res->start; i2c_dev->multimaster_mode = multi_mode;
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
if (!res) { i2c_dev->is_dvc = true;
dev_err(&pdev->dev, "no irq resource\n");
return -EINVAL; if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
} i2c_dev->is_vi = true;
irq = res->start; }
static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
{
int err;
i2c_dev->clocks[i2c_dev->nclocks++].id = "div-clk";
if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw)
i2c_dev->clocks[i2c_dev->nclocks++].id = "fast-clk";
if (i2c_dev->is_vi)
i2c_dev->clocks[i2c_dev->nclocks++].id = "slow";
err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks,
i2c_dev->clocks);
if (err)
return err;
div_clk = devm_clk_get(&pdev->dev, "div-clk"); err = clk_bulk_prepare(i2c_dev->nclocks, i2c_dev->clocks);
if (IS_ERR(div_clk)) { if (err)
if (PTR_ERR(div_clk) != -EPROBE_DEFER) return err;
dev_err(&pdev->dev, "missing controller clock\n");
i2c_dev->div_clk = i2c_dev->clocks[0].clk;
if (!i2c_dev->multimaster_mode)
return 0;
return PTR_ERR(div_clk); err = clk_enable(i2c_dev->div_clk);
if (err) {
dev_err(i2c_dev->dev, "failed to enable div-clk: %d\n", err);
goto unprepare_clocks;
} }
return 0;
unprepare_clocks:
clk_bulk_unprepare(i2c_dev->nclocks, i2c_dev->clocks);
return err;
}
static void tegra_i2c_release_clocks(struct tegra_i2c_dev *i2c_dev)
{
if (i2c_dev->multimaster_mode)
clk_disable(i2c_dev->div_clk);
clk_bulk_unprepare(i2c_dev->nclocks, i2c_dev->clocks);
}
static int tegra_i2c_init_hardware(struct tegra_i2c_dev *i2c_dev)
{
int ret;
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0)
dev_err(i2c_dev->dev, "runtime resume failed: %d\n", ret);
else
ret = tegra_i2c_init(i2c_dev);
pm_runtime_put(i2c_dev->dev);
return ret;
}
static int tegra_i2c_probe(struct platform_device *pdev)
{
struct tegra_i2c_dev *i2c_dev;
struct resource *res;
int err;
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev) if (!i2c_dev)
return -ENOMEM; return -ENOMEM;
i2c_dev->base = base; platform_set_drvdata(pdev, i2c_dev);
i2c_dev->base_phys = base_phys;
i2c_dev->div_clk = div_clk; init_completion(&i2c_dev->msg_complete);
i2c_dev->adapter.algo = &tegra_i2c_algo; init_completion(&i2c_dev->dma_complete);
i2c_dev->adapter.retries = 1;
i2c_dev->adapter.timeout = 6 * HZ; i2c_dev->hw = of_device_get_match_data(&pdev->dev);
i2c_dev->irq = irq;
i2c_dev->cont_id = pdev->id; i2c_dev->cont_id = pdev->id;
i2c_dev->dev = &pdev->dev; i2c_dev->dev = &pdev->dev;
i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c"); i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(i2c_dev->rst)) { if (IS_ERR(i2c_dev->base))
dev_err(&pdev->dev, "missing controller reset\n"); return PTR_ERR(i2c_dev->base);
return PTR_ERR(i2c_dev->rst);
}
tegra_i2c_parse_dt(i2c_dev);
i2c_dev->hw = of_device_get_match_data(&pdev->dev); i2c_dev->base_phys = res->start;
i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
"nvidia,tegra20-i2c-dvc");
i2c_dev->is_vi = of_device_is_compatible(dev->of_node,
"nvidia,tegra210-i2c-vi");
i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
i2c_dev->dma_buf_size = i2c_dev->adapter.quirks->max_write_len +
I2C_PACKET_HEADER_SIZE;
init_completion(&i2c_dev->msg_complete);
init_completion(&i2c_dev->dma_complete);
if (!i2c_dev->hw->has_single_clk_source) { err = platform_get_irq(pdev, 0);
fast_clk = devm_clk_get(&pdev->dev, "fast-clk"); if (err < 0)
if (IS_ERR(fast_clk)) { return err;
dev_err(&pdev->dev, "missing fast clock\n");
return PTR_ERR(fast_clk);
}
i2c_dev->fast_clk = fast_clk;
}
if (i2c_dev->is_vi) { i2c_dev->irq = err;
i2c_dev->slow_clk = devm_clk_get(dev, "slow");
if (IS_ERR(i2c_dev->slow_clk)) {
if (PTR_ERR(i2c_dev->slow_clk) != -EPROBE_DEFER)
dev_err(dev, "failed to get slow clock: %ld\n",
PTR_ERR(i2c_dev->slow_clk));
return PTR_ERR(i2c_dev->slow_clk); /* interrupt will be enabled during of transfer time */
} irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN);
}
platform_set_drvdata(pdev, i2c_dev); err = devm_request_irq(i2c_dev->dev, i2c_dev->irq, tegra_i2c_isr,
IRQF_NO_SUSPEND, dev_name(i2c_dev->dev),
i2c_dev);
if (err)
return err;
ret = clk_prepare(i2c_dev->fast_clk); i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c");
if (ret < 0) { if (IS_ERR(i2c_dev->rst)) {
dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret); dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst),
return ret; "failed to get reset control\n");
return PTR_ERR(i2c_dev->rst);
} }
ret = clk_prepare(i2c_dev->slow_clk); tegra_i2c_parse_dt(i2c_dev);
if (ret < 0) {
dev_err(dev, "failed to prepare slow clock: %d\n", ret);
goto unprepare_fast_clk;
}
if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ && err = tegra_i2c_init_clocks(i2c_dev);
i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ) if (err)
i2c_dev->clk_divisor_non_hs_mode = return err;
i2c_dev->hw->clk_divisor_fast_plus_mode;
else if (i2c_dev->bus_clk_rate > I2C_MAX_STANDARD_MODE_FREQ &&
i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_FREQ)
i2c_dev->clk_divisor_non_hs_mode =
i2c_dev->hw->clk_divisor_fast_mode;
else
i2c_dev->clk_divisor_non_hs_mode =
i2c_dev->hw->clk_divisor_std_mode;
ret = clk_prepare(i2c_dev->div_clk); err = tegra_i2c_init_dma(i2c_dev);
if (ret < 0) { if (err)
dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret); goto release_clocks;
goto unprepare_slow_clk;
}
/* /*
* VI I2C is in VE power domain which is not always on and not * VI I2C is in VE power domain which is not always ON and not
* an IRQ safe. So, IRQ safe device can't be attached to a non-IRQ * IRQ-safe. Thus, IRQ-safe device shouldn't be attached to a
* safe domain as it prevents powering off the PM domain. * non IRQ-safe domain because this prevents powering off the power
* Also, VI I2C device don't need to use runtime IRQ safe as it will * domain.
* not be used for atomic transfers. *
* VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't
* be used for atomic transfers.
*/ */
if (!i2c_dev->is_vi) if (!i2c_dev->is_vi)
pm_runtime_irq_safe(&pdev->dev); pm_runtime_irq_safe(i2c_dev->dev);
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;
}
} else {
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "runtime resume failed\n");
goto disable_rpm;
}
}
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 put_rpm;
}
}
if (i2c_dev->hw->supports_bus_clear)
i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
ret = tegra_i2c_init_dma(i2c_dev);
if (ret < 0)
goto disable_div_clk;
ret = tegra_i2c_init(i2c_dev, false);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize i2c controller\n");
goto release_dma;
}
irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN); pm_runtime_enable(i2c_dev->dev);
ret = devm_request_irq(&pdev->dev, i2c_dev->irq, tegra_i2c_isr, err = tegra_i2c_init_hardware(i2c_dev);
IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c_dev); if (err)
if (ret) { goto release_rpm;
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
goto release_dma;
}
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
i2c_dev->adapter.dev.of_node = i2c_dev->dev->of_node;
i2c_dev->adapter.dev.parent = i2c_dev->dev;
i2c_dev->adapter.retries = 1;
i2c_dev->adapter.timeout = 6 * HZ;
i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
i2c_dev->adapter.owner = THIS_MODULE; i2c_dev->adapter.owner = THIS_MODULE;
i2c_dev->adapter.class = I2C_CLASS_DEPRECATED; i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
strlcpy(i2c_dev->adapter.name, dev_name(&pdev->dev), i2c_dev->adapter.algo = &tegra_i2c_algo;
sizeof(i2c_dev->adapter.name));
i2c_dev->adapter.dev.parent = &pdev->dev;
i2c_dev->adapter.nr = pdev->id; 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 (i2c_dev->hw->supports_bus_clear)
if (ret) i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
goto release_dma;
pm_runtime_put(&pdev->dev);
return 0;
release_dma:
tegra_i2c_release_dma(i2c_dev);
disable_div_clk:
if (i2c_dev->is_multimaster_mode)
clk_disable(i2c_dev->div_clk);
put_rpm: strlcpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev),
if (pm_runtime_enabled(&pdev->dev)) sizeof(i2c_dev->adapter.name));
pm_runtime_put_sync(&pdev->dev);
else
tegra_i2c_runtime_suspend(&pdev->dev);
disable_rpm: err = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (pm_runtime_enabled(&pdev->dev)) if (err)
pm_runtime_disable(&pdev->dev); goto release_rpm;
unprepare_div_clk: return 0;
clk_unprepare(i2c_dev->div_clk);
unprepare_slow_clk: release_rpm:
clk_unprepare(i2c_dev->slow_clk); pm_runtime_disable(i2c_dev->dev);
unprepare_fast_clk: tegra_i2c_release_dma(i2c_dev);
clk_unprepare(i2c_dev->fast_clk); release_clocks:
tegra_i2c_release_clocks(i2c_dev);
return ret; return err;
} }
static int tegra_i2c_remove(struct platform_device *pdev) static int tegra_i2c_remove(struct platform_device *pdev)
...@@ -1865,33 +1798,69 @@ static int tegra_i2c_remove(struct platform_device *pdev) ...@@ -1865,33 +1798,69 @@ static int tegra_i2c_remove(struct platform_device *pdev)
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c_dev->adapter); i2c_del_adapter(&i2c_dev->adapter);
pm_runtime_disable(i2c_dev->dev);
if (i2c_dev->is_multimaster_mode) tegra_i2c_release_dma(i2c_dev);
clk_disable(i2c_dev->div_clk); tegra_i2c_release_clocks(i2c_dev);
return 0;
}
static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int err;
pm_runtime_disable(&pdev->dev); err = pinctrl_pm_select_default_state(dev);
if (!pm_runtime_status_suspended(&pdev->dev)) if (err)
tegra_i2c_runtime_suspend(&pdev->dev); return err;
clk_unprepare(i2c_dev->div_clk); err = clk_bulk_enable(i2c_dev->nclocks, i2c_dev->clocks);
clk_unprepare(i2c_dev->slow_clk); if (err)
clk_unprepare(i2c_dev->fast_clk); return err;
/*
* VI I2C device is attached to VE power domain which goes through
* power ON/OFF during runtime PM resume/suspend, meaning that
* controller needs to be re-initialized after power ON.
*/
if (i2c_dev->is_vi) {
err = tegra_i2c_init(i2c_dev);
if (err)
goto disable_clocks;
}
tegra_i2c_release_dma(i2c_dev);
return 0; return 0;
disable_clocks:
clk_bulk_disable(i2c_dev->nclocks, i2c_dev->clocks);
return err;
}
static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
clk_bulk_disable(i2c_dev->nclocks, i2c_dev->clocks);
return pinctrl_pm_select_idle_state(dev);
} }
static int __maybe_unused tegra_i2c_suspend(struct device *dev) static int __maybe_unused tegra_i2c_suspend(struct device *dev)
{ {
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int err = 0; int err;
i2c_mark_adapter_suspended(&i2c_dev->adapter); i2c_mark_adapter_suspended(&i2c_dev->adapter);
if (!pm_runtime_status_suspended(dev)) if (!pm_runtime_status_suspended(dev)) {
err = tegra_i2c_runtime_suspend(dev); err = tegra_i2c_runtime_suspend(dev);
if (err)
return err; return err;
}
return 0;
} }
static int __maybe_unused tegra_i2c_resume(struct device *dev) static int __maybe_unused tegra_i2c_resume(struct device *dev)
...@@ -1907,7 +1876,7 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev) ...@@ -1907,7 +1876,7 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
if (err) if (err)
return err; return err;
err = tegra_i2c_init(i2c_dev, false); err = tegra_i2c_init(i2c_dev);
if (err) if (err)
return err; return err;
...@@ -1942,9 +1911,8 @@ static struct platform_driver tegra_i2c_driver = { ...@@ -1942,9 +1911,8 @@ static struct platform_driver tegra_i2c_driver = {
.pm = &tegra_i2c_pm, .pm = &tegra_i2c_pm,
}, },
}; };
module_platform_driver(tegra_i2c_driver); module_platform_driver(tegra_i2c_driver);
MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver"); MODULE_DESCRIPTION("NVIDIA Tegra I2C Bus Controller driver");
MODULE_AUTHOR("Colin Cross"); MODULE_AUTHOR("Colin Cross");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -54,11 +54,12 @@ enum xiic_endian { ...@@ -54,11 +54,12 @@ enum xiic_endian {
* @lock: Mutual exclusion * @lock: Mutual exclusion
* @tx_pos: Current pos in TX message * @tx_pos: Current pos in TX message
* @nmsgs: Number of messages in tx_msg * @nmsgs: Number of messages in tx_msg
* @state: See STATE_
* @rx_msg: Current RX message * @rx_msg: Current RX message
* @rx_pos: Position within current RX message * @rx_pos: Position within current RX message
* @endianness: big/little-endian byte order * @endianness: big/little-endian byte order
* @clk: Pointer to AXI4-lite input clock * @clk: Pointer to AXI4-lite input clock
* @state: See STATE_
* @singlemaster: Indicates bus is single master
*/ */
struct xiic_i2c { struct xiic_i2c {
struct device *dev; struct device *dev;
...@@ -69,11 +70,12 @@ struct xiic_i2c { ...@@ -69,11 +70,12 @@ struct xiic_i2c {
struct mutex lock; struct mutex lock;
unsigned int tx_pos; unsigned int tx_pos;
unsigned int nmsgs; unsigned int nmsgs;
enum xilinx_i2c_state state;
struct i2c_msg *rx_msg; struct i2c_msg *rx_msg;
int rx_pos; int rx_pos;
enum xiic_endian endianness; enum xiic_endian endianness;
struct clk *clk; struct clk *clk;
enum xilinx_i2c_state state;
bool singlemaster;
}; };
...@@ -526,6 +528,15 @@ static int xiic_busy(struct xiic_i2c *i2c) ...@@ -526,6 +528,15 @@ static int xiic_busy(struct xiic_i2c *i2c)
if (i2c->tx_msg) if (i2c->tx_msg)
return -EBUSY; return -EBUSY;
/* In single master mode bus can only be busy, when in use by this
* driver. If the register indicates bus being busy for some reason we
* should ignore it, since bus will never be released and i2c will be
* stuck forever.
*/
if (i2c->singlemaster) {
return 0;
}
/* for instance if previous transfer was terminated due to TX error /* for instance if previous transfer was terminated due to TX error
* it might be that the bus is on it's way to become available * it might be that the bus is on it's way to become available
* give it at most 3 ms to wake * give it at most 3 ms to wake
...@@ -811,6 +822,9 @@ static int xiic_i2c_probe(struct platform_device *pdev) ...@@ -811,6 +822,9 @@ static int xiic_i2c_probe(struct platform_device *pdev)
goto err_clk_dis; goto err_clk_dis;
} }
i2c->singlemaster =
of_property_read_bool(pdev->dev.of_node, "single-master");
/* /*
* Detect endianness * Detect endianness
* Try to reset the TX FIFO. Then check the EMPTY flag. If it is not * Try to reset the TX FIFO. Then check the EMPTY flag. If it is not
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* I2C slave mode testunit
*
* Copyright (C) 2020 by Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
* Copyright (C) 2020 by Renesas Electronics Corporation
*/
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/workqueue.h> /* FIXME: is system_long_wq the best choice? */
#define TU_CUR_VERSION 0x01
enum testunit_cmds {
TU_CMD_READ_BYTES = 1, /* save 0 for ABORT, RESET or similar */
TU_CMD_HOST_NOTIFY,
TU_NUM_CMDS
};
enum testunit_regs {
TU_REG_CMD,
TU_REG_DATAL,
TU_REG_DATAH,
TU_REG_DELAY,
TU_NUM_REGS
};
enum testunit_flags {
TU_FLAG_IN_PROCESS,
};
struct testunit_data {
unsigned long flags;
u8 regs[TU_NUM_REGS];
u8 reg_idx;
struct i2c_client *client;
struct delayed_work worker;
};
static void i2c_slave_testunit_work(struct work_struct *work)
{
struct testunit_data *tu = container_of(work, struct testunit_data, worker.work);
struct i2c_msg msg;
u8 msgbuf[256];
int ret = 0;
msg.addr = I2C_CLIENT_END;
msg.buf = msgbuf;
switch (tu->regs[TU_REG_CMD]) {
case TU_CMD_READ_BYTES:
msg.addr = tu->regs[TU_REG_DATAL];
msg.flags = I2C_M_RD;
msg.len = tu->regs[TU_REG_DATAH];
break;
case TU_CMD_HOST_NOTIFY:
msg.addr = 0x08;
msg.flags = 0;
msg.len = 3;
msgbuf[0] = tu->client->addr;
msgbuf[1] = tu->regs[TU_REG_DATAL];
msgbuf[2] = tu->regs[TU_REG_DATAH];
break;
default:
break;
}
if (msg.addr != I2C_CLIENT_END) {
ret = i2c_transfer(tu->client->adapter, &msg, 1);
/* convert '0 msgs transferred' to errno */
ret = (ret == 0) ? -EIO : ret;
}
if (ret < 0)
dev_err(&tu->client->dev, "CMD%02X failed (%d)\n", tu->regs[TU_REG_CMD], ret);
clear_bit(TU_FLAG_IN_PROCESS, &tu->flags);
}
static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
enum i2c_slave_event event, u8 *val)
{
struct testunit_data *tu = i2c_get_clientdata(client);
int ret = 0;
switch (event) {
case I2C_SLAVE_WRITE_RECEIVED:
if (test_bit(TU_FLAG_IN_PROCESS, &tu->flags))
return -EBUSY;
if (tu->reg_idx < TU_NUM_REGS)
tu->regs[tu->reg_idx] = *val;
else
ret = -EMSGSIZE;
if (tu->reg_idx <= TU_NUM_REGS)
tu->reg_idx++;
/* TU_REG_CMD always written at this point */
if (tu->regs[TU_REG_CMD] >= TU_NUM_CMDS)
ret = -EINVAL;
break;
case I2C_SLAVE_STOP:
if (tu->reg_idx == TU_NUM_REGS) {
set_bit(TU_FLAG_IN_PROCESS, &tu->flags);
queue_delayed_work(system_long_wq, &tu->worker,
msecs_to_jiffies(10 * tu->regs[TU_REG_DELAY]));
}
fallthrough;
case I2C_SLAVE_WRITE_REQUESTED:
tu->reg_idx = 0;
break;
case I2C_SLAVE_READ_REQUESTED:
case I2C_SLAVE_READ_PROCESSED:
*val = TU_CUR_VERSION;
break;
}
return ret;
}
static int i2c_slave_testunit_probe(struct i2c_client *client)
{
struct testunit_data *tu;
tu = devm_kzalloc(&client->dev, sizeof(struct testunit_data), GFP_KERNEL);
if (!tu)
return -ENOMEM;
tu->client = client;
i2c_set_clientdata(client, tu);
INIT_DELAYED_WORK(&tu->worker, i2c_slave_testunit_work);
return i2c_slave_register(client, i2c_slave_testunit_slave_cb);
};
static int i2c_slave_testunit_remove(struct i2c_client *client)
{
struct testunit_data *tu = i2c_get_clientdata(client);
cancel_delayed_work_sync(&tu->worker);
i2c_slave_unregister(client);
return 0;
}
static const struct i2c_device_id i2c_slave_testunit_id[] = {
{ "slave-testunit", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, i2c_slave_testunit_id);
static struct i2c_driver i2c_slave_testunit_driver = {
.driver = {
.name = "i2c-slave-testunit",
},
.probe_new = i2c_slave_testunit_probe,
.remove = i2c_slave_testunit_remove,
.id_table = i2c_slave_testunit_id,
};
module_i2c_driver(i2c_slave_testunit_driver);
MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
MODULE_DESCRIPTION("I2C slave mode test unit");
MODULE_LICENSE("GPL v2");
...@@ -197,6 +197,113 @@ EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert); ...@@ -197,6 +197,113 @@ EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);
module_i2c_driver(smbalert_driver); module_i2c_driver(smbalert_driver);
#if IS_ENABLED(CONFIG_I2C_SLAVE)
#define SMBUS_HOST_NOTIFY_LEN 3
struct i2c_slave_host_notify_status {
u8 index;
u8 addr;
};
static int i2c_slave_host_notify_cb(struct i2c_client *client,
enum i2c_slave_event event, u8 *val)
{
struct i2c_slave_host_notify_status *status = client->dev.platform_data;
switch (event) {
case I2C_SLAVE_WRITE_RECEIVED:
/* We only retrieve the first byte received (addr)
* since there is currently no support to retrieve the data
* parameter from the client.
*/
if (status->index == 0)
status->addr = *val;
if (status->index < U8_MAX)
status->index++;
break;
case I2C_SLAVE_STOP:
if (status->index == SMBUS_HOST_NOTIFY_LEN)
i2c_handle_smbus_host_notify(client->adapter,
status->addr);
fallthrough;
case I2C_SLAVE_WRITE_REQUESTED:
status->index = 0;
break;
case I2C_SLAVE_READ_REQUESTED:
case I2C_SLAVE_READ_PROCESSED:
*val = 0xff;
break;
}
return 0;
}
/**
* i2c_new_slave_host_notify_device - get a client for SMBus host-notify support
* @adapter: the target adapter
* Context: can sleep
*
* Setup handling of the SMBus host-notify protocol on a given I2C bus segment.
*
* Handling is done by creating a device and its callback and handling data
* received via the SMBus host-notify address (0x8)
*
* This returns the client, which should be ultimately freed using
* i2c_free_slave_host_notify_device(); or an ERRPTR to indicate an error.
*/
struct i2c_client *i2c_new_slave_host_notify_device(struct i2c_adapter *adapter)
{
struct i2c_board_info host_notify_board_info = {
I2C_BOARD_INFO("smbus_host_notify", 0x08),
.flags = I2C_CLIENT_SLAVE,
};
struct i2c_slave_host_notify_status *status;
struct i2c_client *client;
int ret;
status = kzalloc(sizeof(struct i2c_slave_host_notify_status),
GFP_KERNEL);
if (!status)
return ERR_PTR(-ENOMEM);
host_notify_board_info.platform_data = status;
client = i2c_new_client_device(adapter, &host_notify_board_info);
if (IS_ERR(client)) {
kfree(status);
return client;
}
ret = i2c_slave_register(client, i2c_slave_host_notify_cb);
if (ret) {
i2c_unregister_device(client);
kfree(status);
return ERR_PTR(ret);
}
return client;
}
EXPORT_SYMBOL_GPL(i2c_new_slave_host_notify_device);
/**
* i2c_free_slave_host_notify_device - free the client for SMBus host-notify
* support
* @client: the client to free
* Context: can sleep
*
* Free the i2c_client allocated via i2c_new_slave_host_notify_device
*/
void i2c_free_slave_host_notify_device(struct i2c_client *client)
{
if (IS_ERR_OR_NULL(client))
return;
i2c_slave_unregister(client);
kfree(client->dev.platform_data);
i2c_unregister_device(client);
}
EXPORT_SYMBOL_GPL(i2c_free_slave_host_notify_device);
#endif
/* /*
* SPD is not part of SMBus but we include it here for convenience as the * SPD is not part of SMBus but we include it here for convenience as the
* target systems are the same. * target systems are the same.
......
...@@ -85,18 +85,14 @@ static int i2c_mux_probe(struct platform_device *pdev) ...@@ -85,18 +85,14 @@ static int i2c_mux_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
mux->control = devm_mux_control_get(dev, NULL); mux->control = devm_mux_control_get(dev, NULL);
if (IS_ERR(mux->control)) { if (IS_ERR(mux->control))
if (PTR_ERR(mux->control) != -EPROBE_DEFER) return dev_err_probe(dev, PTR_ERR(mux->control),
dev_err(dev, "failed to get control-mux\n"); "failed to get control-mux\n");
return PTR_ERR(mux->control);
}
parent = mux_parent_adapter(dev); parent = mux_parent_adapter(dev);
if (IS_ERR(parent)) { if (IS_ERR(parent))
if (PTR_ERR(parent) != -EPROBE_DEFER) return dev_err_probe(dev, PTR_ERR(parent),
dev_err(dev, "failed to get i2c-parent adapter\n"); "failed to get i2c-parent adapter\n");
return PTR_ERR(parent);
}
children = of_get_child_count(np); children = of_get_child_count(np);
......
...@@ -171,13 +171,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) ...@@ -171,13 +171,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
sizeof(mux->data)); sizeof(mux->data));
} else { } else {
ret = i2c_mux_reg_probe_dt(mux, pdev); ret = i2c_mux_reg_probe_dt(mux, pdev);
if (ret == -EPROBE_DEFER) if (ret < 0)
return ret; return dev_err_probe(&pdev->dev, ret,
"Error parsing device tree");
if (ret < 0) {
dev_err(&pdev->dev, "Error parsing device tree");
return ret;
}
} }
parent = i2c_get_adapter(mux->data.parent); parent = i2c_get_adapter(mux->data.parent);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/capability.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -89,6 +90,7 @@ struct at24_data { ...@@ -89,6 +90,7 @@ struct at24_data {
struct nvmem_device *nvmem; struct nvmem_device *nvmem;
struct regulator *vcc_reg; struct regulator *vcc_reg;
void (*read_post)(unsigned int off, char *buf, size_t count);
/* /*
* Some chips tie up multiple I2C addresses; dummy devices reserve * Some chips tie up multiple I2C addresses; dummy devices reserve
...@@ -121,6 +123,7 @@ MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)"); ...@@ -121,6 +123,7 @@ MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)");
struct at24_chip_data { struct at24_chip_data {
u32 byte_len; u32 byte_len;
u8 flags; u8 flags;
void (*read_post)(unsigned int off, char *buf, size_t count);
}; };
#define AT24_CHIP_DATA(_name, _len, _flags) \ #define AT24_CHIP_DATA(_name, _len, _flags) \
...@@ -128,6 +131,32 @@ struct at24_chip_data { ...@@ -128,6 +131,32 @@ struct at24_chip_data {
.byte_len = _len, .flags = _flags, \ .byte_len = _len, .flags = _flags, \
} }
#define AT24_CHIP_DATA_CB(_name, _len, _flags, _read_post) \
static const struct at24_chip_data _name = { \
.byte_len = _len, .flags = _flags, \
.read_post = _read_post, \
}
static void at24_read_post_vaio(unsigned int off, char *buf, size_t count)
{
int i;
if (capable(CAP_SYS_ADMIN))
return;
/*
* Hide VAIO private settings to regular users:
* - BIOS passwords: bytes 0x00 to 0x0f
* - UUID: bytes 0x10 to 0x1f
* - Serial number: 0xc0 to 0xdf
*/
for (i = 0; i < count; i++) {
if ((off + i <= 0x1f) ||
(off + i >= 0xc0 && off + i <= 0xdf))
buf[i] = 0;
}
}
/* needs 8 addresses as A0-A2 are ignored */ /* needs 8 addresses as A0-A2 are ignored */
AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR); AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR);
/* old variants can't be handled with this generic entry! */ /* old variants can't be handled with this generic entry! */
...@@ -144,6 +173,10 @@ AT24_CHIP_DATA(at24_data_24mac602, 64 / 8, ...@@ -144,6 +173,10 @@ AT24_CHIP_DATA(at24_data_24mac602, 64 / 8,
/* spd is a 24c02 in memory DIMMs */ /* spd is a 24c02 in memory DIMMs */
AT24_CHIP_DATA(at24_data_spd, 2048 / 8, AT24_CHIP_DATA(at24_data_spd, 2048 / 8,
AT24_FLAG_READONLY | AT24_FLAG_IRUGO); AT24_FLAG_READONLY | AT24_FLAG_IRUGO);
/* 24c02_vaio is a 24c02 on some Sony laptops */
AT24_CHIP_DATA_CB(at24_data_24c02_vaio, 2048 / 8,
AT24_FLAG_READONLY | AT24_FLAG_IRUGO,
at24_read_post_vaio);
AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0); AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0);
AT24_CHIP_DATA(at24_data_24cs04, 16, AT24_CHIP_DATA(at24_data_24cs04, 16,
AT24_FLAG_SERIAL | AT24_FLAG_READONLY); AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
...@@ -177,6 +210,7 @@ static const struct i2c_device_id at24_ids[] = { ...@@ -177,6 +210,7 @@ static const struct i2c_device_id at24_ids[] = {
{ "24mac402", (kernel_ulong_t)&at24_data_24mac402 }, { "24mac402", (kernel_ulong_t)&at24_data_24mac402 },
{ "24mac602", (kernel_ulong_t)&at24_data_24mac602 }, { "24mac602", (kernel_ulong_t)&at24_data_24mac602 },
{ "spd", (kernel_ulong_t)&at24_data_spd }, { "spd", (kernel_ulong_t)&at24_data_spd },
{ "24c02-vaio", (kernel_ulong_t)&at24_data_24c02_vaio },
{ "24c04", (kernel_ulong_t)&at24_data_24c04 }, { "24c04", (kernel_ulong_t)&at24_data_24c04 },
{ "24cs04", (kernel_ulong_t)&at24_data_24cs04 }, { "24cs04", (kernel_ulong_t)&at24_data_24cs04 },
{ "24c08", (kernel_ulong_t)&at24_data_24c08 }, { "24c08", (kernel_ulong_t)&at24_data_24c08 },
...@@ -388,7 +422,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) ...@@ -388,7 +422,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
struct at24_data *at24; struct at24_data *at24;
struct device *dev; struct device *dev;
char *buf = val; char *buf = val;
int ret; int i, ret;
at24 = priv; at24 = priv;
dev = at24_base_client_dev(at24); dev = at24_base_client_dev(at24);
...@@ -411,22 +445,22 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) ...@@ -411,22 +445,22 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
*/ */
mutex_lock(&at24->lock); mutex_lock(&at24->lock);
while (count) { for (i = 0; count; i += ret, count -= ret) {
ret = at24_regmap_read(at24, buf, off, count); ret = at24_regmap_read(at24, buf + i, off + i, count);
if (ret < 0) { if (ret < 0) {
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(dev); pm_runtime_put(dev);
return ret; return ret;
} }
buf += ret;
off += ret;
count -= ret;
} }
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(dev); pm_runtime_put(dev);
if (unlikely(at24->read_post))
at24->read_post(off, buf, i);
return 0; return 0;
} }
...@@ -654,6 +688,7 @@ static int at24_probe(struct i2c_client *client) ...@@ -654,6 +688,7 @@ static int at24_probe(struct i2c_client *client)
at24->byte_len = byte_len; at24->byte_len = byte_len;
at24->page_size = page_size; at24->page_size = page_size;
at24->flags = flags; at24->flags = flags;
at24->read_post = cdata->read_post;
at24->num_addresses = num_addresses; at24->num_addresses = num_addresses;
at24->offset_adj = at24_get_offset_adj(flags, byte_len); at24->offset_adj = at24_get_offset_adj(flags, byte_len);
at24->client[0].client = client; at24->client[0].client = client;
...@@ -678,8 +713,30 @@ static int at24_probe(struct i2c_client *client) ...@@ -678,8 +713,30 @@ static int at24_probe(struct i2c_client *client)
return err; return err;
} }
/*
* If the 'label' property is not present for the AT24 EEPROM,
* then nvmem_config.id is initialised to NVMEM_DEVID_AUTO,
* and this will append the 'devid' to the name of the NVMEM
* device. This is purely legacy and the AT24 driver has always
* defaulted to this. However, if the 'label' property is
* present then this means that the name is specified by the
* firmware and this name should be used verbatim and so it is
* not necessary to append the 'devid'.
*/
if (device_property_present(dev, "label")) {
nvmem_config.id = NVMEM_DEVID_NONE;
err = device_property_read_string(dev, "label",
&nvmem_config.name);
if (err)
return err;
} else {
nvmem_config.id = NVMEM_DEVID_AUTO;
nvmem_config.name = dev_name(dev); nvmem_config.name = dev_name(dev);
}
nvmem_config.type = NVMEM_TYPE_EEPROM;
nvmem_config.dev = dev; nvmem_config.dev = dev;
nvmem_config.id = NVMEM_DEVID_AUTO;
nvmem_config.read_only = !writable; nvmem_config.read_only = !writable;
nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO); nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
nvmem_config.owner = THIS_MODULE; nvmem_config.owner = THIS_MODULE;
......
...@@ -76,7 +76,7 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, ...@@ -76,7 +76,7 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
{ {
struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj)); struct i2c_client *client = kobj_to_i2c_client(kobj);
struct eeprom_data *data = i2c_get_clientdata(client); struct eeprom_data *data = i2c_get_clientdata(client);
u8 slice; u8 slice;
......
...@@ -38,6 +38,18 @@ static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap) ...@@ -38,6 +38,18 @@ static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)
return 0; return 0;
} }
#endif #endif
#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_I2C_SLAVE)
struct i2c_client *i2c_new_slave_host_notify_device(struct i2c_adapter *adapter);
void i2c_free_slave_host_notify_device(struct i2c_client *client);
#else
static inline struct i2c_client *i2c_new_slave_host_notify_device(struct i2c_adapter *adapter)
{
return ERR_PTR(-ENOSYS);
}
static inline void i2c_free_slave_host_notify_device(struct i2c_client *client)
{
}
#endif
#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_DMI) #if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_DMI)
void i2c_register_spd(struct i2c_adapter *adap); void i2c_register_spd(struct i2c_adapter *adap);
......
...@@ -344,7 +344,7 @@ const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, ...@@ -344,7 +344,7 @@ const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj) static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
{ {
struct device * const dev = container_of(kobj, struct device, kobj); struct device * const dev = kobj_to_dev(kobj);
return to_i2c_client(dev); return to_i2c_client(dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment