Commit 9d0d8867 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull i2c updates from Wolfram Sang:
 "A bit smaller this time with mostly usual driver updates. Slave
  support for imx stands out a little"

* 'i2c/for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (30 commits)
  i2c: remove check that can never be true
  i2c: Warn when device removing fails
  dt-bindings: i2c: Update DT binding docs to support SiFive FU740 SoC
  dt-bindings: i2c: Add compatible string for AM64 SoC
  i2c: designware: Make register offsets all of the same width
  i2c: designware: Switch header to use BIT() and GENMASK()
  i2c: pxa: move to generic GPIO recovery
  i2c: sh_mobile: Mark adapter suspended during suspend
  i2c: owl: Add compatible for the Actions Semi S500 I2C controller
  dt-bindings: i2c: owl: Convert Actions Semi Owl binding to a schema
  i2c: imx: support slave mode for imx I2C driver
  i2c: ismt: Adding support for I2C_SMBUS_BLOCK_PROC_CALL
  i2c: ocores: Avoid false-positive error log message.
  Revert "i2c: qcom-geni: Disable DMA processing on the Lenovo Yoga C630"
  i2c: mxs: Remove unneeded platform_device_id
  i2c: pca-platform: drop two members from driver data that are assigned to only
  i2c: imx: Remove unused .id_table support
  i2c: nvidia-gpu: drop empty stub for runtime pm
  dt-bindings: i2c: mellanox,i2c-mlxbf: convert txt to YAML schema
  i2c: mv64xxx: Add bus error recovery
  ...
parents 605ea5aa 4e970a0a
...@@ -5,8 +5,12 @@ Required properties: ...@@ -5,8 +5,12 @@ Required properties:
"aeroflexgaisler,i2cmst" "aeroflexgaisler,i2cmst"
"sifive,fu540-c000-i2c", "sifive,i2c0" "sifive,fu540-c000-i2c", "sifive,i2c0"
For Opencore based I2C IP block reimplemented in For Opencore based I2C IP block reimplemented in
FU540-C000 SoC. Please refer to sifive-blocks-ip-versioning.txt FU540-C000 SoC.
for additional details. "sifive,fu740-c000-i2c", "sifive,i2c0"
For Opencore based I2C IP block reimplemented in
FU740-C000 SoC.
Please refer to sifive-blocks-ip-versioning.txt for
additional details.
- reg : bus address start and address range size of device - reg : bus address start and address range size of device
- clocks : handle to the controller clock; see the note below. - clocks : handle to the controller clock; see the note below.
Mutually exclusive with opencores,ip-clock-frequency Mutually exclusive with opencores,ip-clock-frequency
......
...@@ -8,6 +8,7 @@ Required properties : ...@@ -8,6 +8,7 @@ Required properties :
"ti,omap4-i2c" for OMAP4+ SoCs "ti,omap4-i2c" for OMAP4+ SoCs
"ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs "ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs
"ti,j721e-i2c", "ti,omap4-i2c" for J721E SoCs "ti,j721e-i2c", "ti,omap4-i2c" for J721E SoCs
"ti,am64-i2c", "ti,omap4-i2c" for AM64 SoCs
- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based) - ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
- #address-cells = <1>; - #address-cells = <1>;
- #size-cells = <0>; - #size-cells = <0>;
......
Actions Semiconductor Owl I2C controller
Required properties:
- compatible : Should be one of the following:
- "actions,s700-i2c" for S700 SoC
- "actions,s900-i2c" for S900 SoC
- reg : Offset and length of the register set for the device.
- #address-cells : Should be 1.
- #size-cells : Should be 0.
- interrupts : A single interrupt specifier.
- clocks : Phandle of the clock feeding the I2C controller.
Optional properties:
- clock-frequency : Desired I2C bus clock frequency in Hz. As only Normal and
Fast modes are supported, possible values are 100000 and
400000.
Examples:
i2c0: i2c@e0170000 {
compatible = "actions,s900-i2c";
reg = <0 0xe0170000 0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clock CLK_I2C0>;
clock-frequency = <100000>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/i2c-owl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Actions Semi Owl I2C Controller
maintainers:
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
description: |
This I2C controller is found in the Actions Semi Owl SoCs:
S500, S700 and S900.
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
enum:
- actions,s500-i2c # Actions Semi S500 compatible SoCs
- actions,s700-i2c # Actions Semi S700 compatible SoCs
- actions,s900-i2c # Actions Semi S900 compatible SoCs
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
description: Phandle of the clock feeding the I2C controller.
minItems: 1
clock-frequency:
description: |
Desired I2C bus clock frequency in Hz. As only Standard and Fast
modes are supported, possible values are 100000 and 400000.
enum: [100000, 400000]
required:
- compatible
- reg
- interrupts
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/actions,s900-cmu.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
i2c@e0170000 {
compatible = "actions,s900-i2c";
reg = <0xe0170000 0x1000>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cmu CLK_I2C0>;
clock-frequency = <100000>;
};
...
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>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/mellanox,i2c-mlxbf.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mellanox I2C SMBus on BlueField SoCs
maintainers:
- Khalil Blaiech <kblaiech@nvidia.com>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
enum:
- mellanox,i2c-mlxbf1
- mellanox,i2c-mlxbf2
reg:
minItems: 3
maxItems: 4
items:
- description: Smbus block registers
- description: Cause master registers
- description: Cause slave registers
- description: Cause coalesce registers
interrupts:
maxItems: 1
clock-frequency:
enum: [ 100000, 400000, 1000000 ]
description:
bus frequency used to configure timing registers;
The frequency is expressed in Hz. Default is 100000.
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
if:
properties:
compatible:
contains:
enum:
- mellanox,i2c-mlxbf1
then:
properties:
reg:
maxItems: 3
examples:
- |
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>;
};
...@@ -1502,7 +1502,7 @@ S: Maintained ...@@ -1502,7 +1502,7 @@ S: Maintained
F: Documentation/devicetree/bindings/arm/actions.yaml F: Documentation/devicetree/bindings/arm/actions.yaml
F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
F: Documentation/devicetree/bindings/dma/owl-dma.yaml F: Documentation/devicetree/bindings/dma/owl-dma.yaml
F: Documentation/devicetree/bindings/i2c/i2c-owl.txt F: Documentation/devicetree/bindings/i2c/i2c-owl.yaml
F: Documentation/devicetree/bindings/interrupt-controller/actions,owl-sirq.yaml F: Documentation/devicetree/bindings/interrupt-controller/actions,owl-sirq.yaml
F: Documentation/devicetree/bindings/mmc/owl-mmc.yaml F: Documentation/devicetree/bindings/mmc/owl-mmc.yaml
F: Documentation/devicetree/bindings/pinctrl/actions,* F: Documentation/devicetree/bindings/pinctrl/actions,*
...@@ -11254,6 +11254,7 @@ MELLANOX BLUEFIELD I2C DRIVER ...@@ -11254,6 +11254,7 @@ MELLANOX BLUEFIELD I2C DRIVER
M: Khalil Blaiech <kblaiech@nvidia.com> M: Khalil Blaiech <kblaiech@nvidia.com>
L: linux-i2c@vger.kernel.org L: linux-i2c@vger.kernel.org
S: Supported S: Supported
F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml
F: drivers/i2c/busses/i2c-mlxbf.c F: drivers/i2c/busses/i2c-mlxbf.c
MELLANOX ETHERNET DRIVER (mlx4_en) MELLANOX ETHERNET DRIVER (mlx4_en)
......
...@@ -675,6 +675,7 @@ config I2C_IMG ...@@ -675,6 +675,7 @@ config I2C_IMG
config I2C_IMX config I2C_IMX
tristate "IMX I2C interface" tristate "IMX I2C interface"
depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE
select I2C_SLAVE
help help
Say Y here if you want to use the IIC bus controller on Say Y here if you want to use the IIC bus controller on
the Freescale i.MX/MXC, Layerscape or ColdFire processors. the Freescale i.MX/MXC, Layerscape or ColdFire processors.
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/dma-atmel.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include "i2c-at91.h" #include "i2c-at91.h"
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_data/dma-atmel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */
...@@ -123,7 +122,6 @@ struct at91_twi_pdata { ...@@ -123,7 +122,6 @@ struct at91_twi_pdata {
bool has_adv_dig_filtr; bool has_adv_dig_filtr;
bool has_ana_filtr; bool has_ana_filtr;
bool has_clear_cmd; bool has_clear_cmd;
struct at_dma_slave dma_slave;
}; };
struct at91_twi_dma { struct at91_twi_dma {
......
...@@ -25,25 +25,25 @@ ...@@ -25,25 +25,25 @@
I2C_FUNC_SMBUS_BLOCK_DATA | \ I2C_FUNC_SMBUS_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK) I2C_FUNC_SMBUS_I2C_BLOCK)
#define DW_IC_CON_MASTER 0x1 #define DW_IC_CON_MASTER BIT(0)
#define DW_IC_CON_SPEED_STD 0x2 #define DW_IC_CON_SPEED_STD (1 << 1)
#define DW_IC_CON_SPEED_FAST 0x4 #define DW_IC_CON_SPEED_FAST (2 << 1)
#define DW_IC_CON_SPEED_HIGH 0x6 #define DW_IC_CON_SPEED_HIGH (3 << 1)
#define DW_IC_CON_SPEED_MASK 0x6 #define DW_IC_CON_SPEED_MASK GENMASK(2, 1)
#define DW_IC_CON_10BITADDR_SLAVE 0x8 #define DW_IC_CON_10BITADDR_SLAVE BIT(3)
#define DW_IC_CON_10BITADDR_MASTER 0x10 #define DW_IC_CON_10BITADDR_MASTER BIT(4)
#define DW_IC_CON_RESTART_EN 0x20 #define DW_IC_CON_RESTART_EN BIT(5)
#define DW_IC_CON_SLAVE_DISABLE 0x40 #define DW_IC_CON_SLAVE_DISABLE BIT(6)
#define DW_IC_CON_STOP_DET_IFADDRESSED 0x80 #define DW_IC_CON_STOP_DET_IFADDRESSED BIT(7)
#define DW_IC_CON_TX_EMPTY_CTRL 0x100 #define DW_IC_CON_TX_EMPTY_CTRL BIT(8)
#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL 0x200 #define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9)
/* /*
* Registers offset * Registers offset
*/ */
#define DW_IC_CON 0x0 #define DW_IC_CON 0x00
#define DW_IC_TAR 0x4 #define DW_IC_TAR 0x04
#define DW_IC_SAR 0x8 #define DW_IC_SAR 0x08
#define DW_IC_DATA_CMD 0x10 #define DW_IC_DATA_CMD 0x10
#define DW_IC_SS_SCL_HCNT 0x14 #define DW_IC_SS_SCL_HCNT 0x14
#define DW_IC_SS_SCL_LCNT 0x18 #define DW_IC_SS_SCL_LCNT 0x18
...@@ -81,19 +81,19 @@ ...@@ -81,19 +81,19 @@
#define DW_IC_COMP_TYPE 0xfc #define DW_IC_COMP_TYPE 0xfc
#define DW_IC_COMP_TYPE_VALUE 0x44570140 #define DW_IC_COMP_TYPE_VALUE 0x44570140
#define DW_IC_INTR_RX_UNDER 0x001 #define DW_IC_INTR_RX_UNDER BIT(0)
#define DW_IC_INTR_RX_OVER 0x002 #define DW_IC_INTR_RX_OVER BIT(1)
#define DW_IC_INTR_RX_FULL 0x004 #define DW_IC_INTR_RX_FULL BIT(2)
#define DW_IC_INTR_TX_OVER 0x008 #define DW_IC_INTR_TX_OVER BIT(3)
#define DW_IC_INTR_TX_EMPTY 0x010 #define DW_IC_INTR_TX_EMPTY BIT(4)
#define DW_IC_INTR_RD_REQ 0x020 #define DW_IC_INTR_RD_REQ BIT(5)
#define DW_IC_INTR_TX_ABRT 0x040 #define DW_IC_INTR_TX_ABRT BIT(6)
#define DW_IC_INTR_RX_DONE 0x080 #define DW_IC_INTR_RX_DONE BIT(7)
#define DW_IC_INTR_ACTIVITY 0x100 #define DW_IC_INTR_ACTIVITY BIT(8)
#define DW_IC_INTR_STOP_DET 0x200 #define DW_IC_INTR_STOP_DET BIT(9)
#define DW_IC_INTR_START_DET 0x400 #define DW_IC_INTR_START_DET BIT(10)
#define DW_IC_INTR_GEN_CALL 0x800 #define DW_IC_INTR_GEN_CALL BIT(11)
#define DW_IC_INTR_RESTART_DET 0x1000 #define DW_IC_INTR_RESTART_DET BIT(12)
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \ #define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
DW_IC_INTR_TX_ABRT | \ DW_IC_INTR_TX_ABRT | \
...@@ -105,13 +105,13 @@ ...@@ -105,13 +105,13 @@
DW_IC_INTR_RX_UNDER | \ DW_IC_INTR_RX_UNDER | \
DW_IC_INTR_RD_REQ) DW_IC_INTR_RD_REQ)
#define DW_IC_STATUS_ACTIVITY 0x1 #define DW_IC_STATUS_ACTIVITY BIT(0)
#define DW_IC_STATUS_TFE BIT(2) #define DW_IC_STATUS_TFE BIT(2)
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5) #define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6) #define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
#define DW_IC_SDA_HOLD_RX_SHIFT 16 #define DW_IC_SDA_HOLD_RX_SHIFT 16
#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT) #define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16)
#define DW_IC_ERR_TX_ABRT 0x1 #define DW_IC_ERR_TX_ABRT 0x1
...@@ -154,20 +154,20 @@ ...@@ -154,20 +154,20 @@
#define ABRT_SLAVE_ARBLOST 14 #define ABRT_SLAVE_ARBLOST 14
#define ABRT_SLAVE_RD_INTX 15 #define ABRT_SLAVE_RD_INTX 15
#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK) #define DW_IC_TX_ABRT_7B_ADDR_NOACK BIT(ABRT_7B_ADDR_NOACK)
#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK) #define DW_IC_TX_ABRT_10ADDR1_NOACK BIT(ABRT_10ADDR1_NOACK)
#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK) #define DW_IC_TX_ABRT_10ADDR2_NOACK BIT(ABRT_10ADDR2_NOACK)
#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK) #define DW_IC_TX_ABRT_TXDATA_NOACK BIT(ABRT_TXDATA_NOACK)
#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK) #define DW_IC_TX_ABRT_GCALL_NOACK BIT(ABRT_GCALL_NOACK)
#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ) #define DW_IC_TX_ABRT_GCALL_READ BIT(ABRT_GCALL_READ)
#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET) #define DW_IC_TX_ABRT_SBYTE_ACKDET BIT(ABRT_SBYTE_ACKDET)
#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT) #define DW_IC_TX_ABRT_SBYTE_NORSTRT BIT(ABRT_SBYTE_NORSTRT)
#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT) #define DW_IC_TX_ABRT_10B_RD_NORSTRT BIT(ABRT_10B_RD_NORSTRT)
#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS) #define DW_IC_TX_ABRT_MASTER_DIS BIT(ABRT_MASTER_DIS)
#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST) #define DW_IC_TX_ARB_LOST BIT(ARB_LOST)
#define DW_IC_RX_ABRT_SLAVE_RD_INTX (1UL << ABRT_SLAVE_RD_INTX) #define DW_IC_RX_ABRT_SLAVE_RD_INTX BIT(ABRT_SLAVE_RD_INTX)
#define DW_IC_RX_ABRT_SLAVE_ARBLOST (1UL << ABRT_SLAVE_ARBLOST) #define DW_IC_RX_ABRT_SLAVE_ARBLOST BIT(ABRT_SLAVE_ARBLOST)
#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO (1UL << ABRT_SLAVE_FLUSH_TXFIFO) #define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO BIT(ABRT_SLAVE_FLUSH_TXFIFO)
#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \ #define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
DW_IC_TX_ABRT_10ADDR1_NOACK | \ DW_IC_TX_ABRT_10ADDR1_NOACK | \
...@@ -288,12 +288,12 @@ struct dw_i2c_dev { ...@@ -288,12 +288,12 @@ struct dw_i2c_dev {
bool suspended; bool suspended;
}; };
#define ACCESS_INTR_MASK 0x00000001 #define ACCESS_INTR_MASK BIT(0)
#define ACCESS_NO_IRQ_SUSPEND 0x00000002 #define ACCESS_NO_IRQ_SUSPEND BIT(1)
#define MODEL_MSCC_OCELOT 0x00000100 #define MODEL_MSCC_OCELOT BIT(8)
#define MODEL_BAIKAL_BT1 0x00000200 #define MODEL_BAIKAL_BT1 BIT(9)
#define MODEL_MASK 0x00000f00 #define MODEL_MASK GENMASK(11, 8)
int i2c_dw_init_regmap(struct dw_i2c_dev *dev); int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset); u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
......
...@@ -778,11 +778,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev) ...@@ -778,11 +778,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
init_completion(&i2c->msg_complete); init_completion(&i2c->msg_complete);
i2c->irq = ret = platform_get_irq(pdev, 0); i2c->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) { if (ret < 0)
dev_err(&pdev->dev, "cannot find HS-I2C IRQ\n");
ret = -EINVAL;
goto err_clk; goto err_clk;
}
ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq, ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq,
IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c); IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt> * Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
* *
* Copyright 2013 Freescale Semiconductor, Inc. * Copyright 2013 Freescale Semiconductor, Inc.
* Copyright 2020 NXP
* *
*/ */
...@@ -73,6 +74,11 @@ ...@@ -73,6 +74,11 @@
#define IMX_I2C_I2SR 0x03 /* i2c status */ #define IMX_I2C_I2SR 0x03 /* i2c status */
#define IMX_I2C_I2DR 0x04 /* i2c transfer data */ #define IMX_I2C_I2DR 0x04 /* i2c transfer data */
/*
* All of the layerscape series SoCs support IBIC register.
*/
#define IMX_I2C_IBIC 0x05 /* i2c bus interrupt config */
#define IMX_I2C_REGSHIFT 2 #define IMX_I2C_REGSHIFT 2
#define VF610_I2C_REGSHIFT 0 #define VF610_I2C_REGSHIFT 0
...@@ -91,6 +97,7 @@ ...@@ -91,6 +97,7 @@
#define I2CR_MSTA 0x20 #define I2CR_MSTA 0x20
#define I2CR_IIEN 0x40 #define I2CR_IIEN 0x40
#define I2CR_IEN 0x80 #define I2CR_IEN 0x80
#define IBIC_BIIE 0x80 /* Bus idle interrupt enable */
/* register bits different operating codes definition: /* register bits different operating codes definition:
* 1) I2SR: Interrupt flags clear operation differ between SoCs: * 1) I2SR: Interrupt flags clear operation differ between SoCs:
...@@ -201,6 +208,7 @@ struct imx_i2c_struct { ...@@ -201,6 +208,7 @@ struct imx_i2c_struct {
struct pinctrl_state *pinctrl_pins_gpio; struct pinctrl_state *pinctrl_pins_gpio;
struct imx_i2c_dma *dma; struct imx_i2c_dma *dma;
struct i2c_client *slave;
}; };
static const struct imx_i2c_hwdata imx1_i2c_hwdata = { static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
...@@ -233,19 +241,6 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = { ...@@ -233,19 +241,6 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
}; };
static const struct platform_device_id imx_i2c_devtype[] = {
{
.name = "imx1-i2c",
.driver_data = (kernel_ulong_t)&imx1_i2c_hwdata,
}, {
.name = "imx21-i2c",
.driver_data = (kernel_ulong_t)&imx21_i2c_hwdata,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
static const struct of_device_id i2c_imx_dt_ids[] = { static const struct of_device_id i2c_imx_dt_ids[] = {
{ .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, }, { .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, },
{ .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, }, { .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
...@@ -265,6 +260,11 @@ static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx) ...@@ -265,6 +260,11 @@ static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
return i2c_imx->hwdata->devtype == IMX1_I2C; return i2c_imx->hwdata->devtype == IMX1_I2C;
} }
static inline int is_vf610_i2c(struct imx_i2c_struct *i2c_imx)
{
return i2c_imx->hwdata->devtype == VF610_I2C;
}
static inline void imx_i2c_write_reg(unsigned int val, static inline void imx_i2c_write_reg(unsigned int val,
struct imx_i2c_struct *i2c_imx, unsigned int reg) struct imx_i2c_struct *i2c_imx, unsigned int reg)
{ {
...@@ -277,6 +277,27 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx, ...@@ -277,6 +277,27 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift)); return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
} }
static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
{
unsigned int temp;
/*
* i2sr_clr_opcode is the value to clear all interrupts. Here we want to
* clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
* toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
*/
temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
}
/* Set up i2c controller register and i2c status register to default value. */
static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
{
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
i2c_imx, IMX_I2C_I2CR);
i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);
}
/* Functions for DMA support */ /* Functions for DMA support */
static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
dma_addr_t phy_addr) dma_addr_t phy_addr)
...@@ -412,19 +433,6 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) ...@@ -412,19 +433,6 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
dma->chan_using = NULL; dma->chan_using = NULL;
} }
static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
{
unsigned int temp;
/*
* i2sr_clr_opcode is the value to clear all interrupts. Here we want to
* clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
* toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
*/
temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
}
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic) static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
{ {
unsigned long orig_jiffies = jiffies; unsigned long orig_jiffies = jiffies;
...@@ -638,18 +646,165 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic) ...@@ -638,18 +646,165 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
} }
static irqreturn_t i2c_imx_isr(int irq, void *dev_id) /*
* Enable bus idle interrupts
* Note: IBIC register will be cleared after disabled i2c module.
* All of layerscape series SoCs support IBIC register.
*/
static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx)
{ {
struct imx_i2c_struct *i2c_imx = dev_id; if (is_vf610_i2c(i2c_imx)) {
unsigned int temp; unsigned int temp;
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_IBIC);
if (temp & I2SR_IIF) { temp |= IBIC_BIIE;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_IBIC);
}
}
static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
unsigned int status, unsigned int ctl)
{
u8 value;
if (status & I2SR_IAL) { /* Arbitration lost */
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
if (!(status & I2SR_IAAS))
return IRQ_HANDLED;
}
if (status & I2SR_IAAS) { /* Addressed as a slave */
if (status & I2SR_SRW) { /* Master wants to read from us*/
dev_dbg(&i2c_imx->adapter.dev, "read requested");
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
/* Slave transmit */
ctl |= I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
/* Send data */
imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
} else { /* Master wants to write to us */
dev_dbg(&i2c_imx->adapter.dev, "write requested");
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
/* Slave receive */
ctl &= ~I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
/* Dummy read */
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
}
} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
if (status & I2SR_IBB) { /* No STOP signal detected */
value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
} else { /* STOP signal is detected */
dev_dbg(&i2c_imx->adapter.dev,
"STOP signal detected");
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
}
} else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */
ctl |= I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value);
imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
} else { /* Transmit mode received NAK */
ctl &= ~I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
}
return IRQ_HANDLED;
}
static void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)
{
int temp;
/* Set slave addr. */
imx_i2c_write_reg((i2c_imx->slave->addr << 1), i2c_imx, IMX_I2C_IADR);
i2c_imx_reset_regs(i2c_imx);
/* Enable module */
temp = i2c_imx->hwdata->i2cr_ien_opcode;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
/* Enable interrupt from i2c module */
temp |= I2CR_IIEN;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
i2c_imx_enable_bus_idle(i2c_imx);
}
static int i2c_imx_reg_slave(struct i2c_client *client)
{
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
int ret;
if (i2c_imx->slave)
return -EBUSY;
i2c_imx->slave = client;
/* Resume */
ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
if (ret < 0) {
dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller");
return ret;
}
i2c_imx_slave_init(i2c_imx);
return 0;
}
static int i2c_imx_unreg_slave(struct i2c_client *client)
{
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
int ret;
if (!i2c_imx->slave)
return -EINVAL;
/* Reset slave address. */
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
i2c_imx_reset_regs(i2c_imx);
i2c_imx->slave = NULL;
/* Suspend */
ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
if (ret < 0)
dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
return ret;
}
static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status)
{
/* save status register */ /* save status register */
i2c_imx->i2csr = temp; i2c_imx->i2csr = status;
i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
wake_up(&i2c_imx->queue); wake_up(&i2c_imx->queue);
return IRQ_HANDLED; return IRQ_HANDLED;
}
static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
{
struct imx_i2c_struct *i2c_imx = dev_id;
unsigned int ctl, status;
status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (status & I2SR_IIF) {
i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
if (i2c_imx->slave && !(ctl & I2CR_MSTA))
return i2c_imx_slave_isr(i2c_imx, status, ctl);
return i2c_imx_master_isr(i2c_imx, status);
} }
return IRQ_NONE; return IRQ_NONE;
...@@ -1027,6 +1182,10 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter, ...@@ -1027,6 +1182,10 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg", (result < 0) ? "error" : "success msg",
(result < 0) ? result : num); (result < 0) ? result : num);
/* After data is transferred, switch to slave mode(as a receiver) */
if (i2c_imx->slave)
i2c_imx_slave_init(i2c_imx);
return (result < 0) ? result : num; return (result < 0) ? result : num;
} }
...@@ -1140,6 +1299,8 @@ static const struct i2c_algorithm i2c_imx_algo = { ...@@ -1140,6 +1299,8 @@ static const struct i2c_algorithm i2c_imx_algo = {
.master_xfer = i2c_imx_xfer, .master_xfer = i2c_imx_xfer,
.master_xfer_atomic = i2c_imx_xfer_atomic, .master_xfer_atomic = i2c_imx_xfer_atomic,
.functionality = i2c_imx_func, .functionality = i2c_imx_func,
.reg_slave = i2c_imx_reg_slave,
.unreg_slave = i2c_imx_unreg_slave,
}; };
static int i2c_imx_probe(struct platform_device *pdev) static int i2c_imx_probe(struct platform_device *pdev)
...@@ -1169,11 +1330,7 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1169,11 +1330,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
match = device_get_match_data(&pdev->dev); match = device_get_match_data(&pdev->dev);
if (match)
i2c_imx->hwdata = match; i2c_imx->hwdata = match;
else
i2c_imx->hwdata = (struct imx_i2c_hwdata *)
platform_get_device_id(pdev)->driver_data;
/* Setup i2c_imx driver structure */ /* Setup i2c_imx driver structure */
strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
...@@ -1233,10 +1390,7 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1233,10 +1390,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb); clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk)); i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
/* Set up chip registers to defaults */ i2c_imx_reset_regs(i2c_imx);
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
/* Init optional bus recovery function */ /* Init optional bus recovery function */
ret = i2c_imx_init_recovery_info(i2c_imx, pdev); ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
...@@ -1344,7 +1498,6 @@ static struct platform_driver i2c_imx_driver = { ...@@ -1344,7 +1498,6 @@ static struct platform_driver i2c_imx_driver = {
.of_match_table = i2c_imx_dt_ids, .of_match_table = i2c_imx_dt_ids,
.acpi_match_table = i2c_imx_acpi_ids, .acpi_match_table = i2c_imx_acpi_ids,
}, },
.id_table = imx_i2c_devtype,
}; };
static int __init i2c_adap_imx_init(void) static int __init i2c_adap_imx_init(void)
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
* Features supported by this driver: * Features supported by this driver:
* Hardware PEC yes * Hardware PEC yes
* Block buffer yes * Block buffer yes
* Block process call transaction no * Block process call transaction yes
* Slave mode no * Slave mode no
*/ */
...@@ -332,7 +332,8 @@ static int ismt_process_desc(const struct ismt_desc *desc, ...@@ -332,7 +332,8 @@ static int ismt_process_desc(const struct ismt_desc *desc,
if (desc->status & ISMT_DESC_SCS) { if (desc->status & ISMT_DESC_SCS) {
if (read_write == I2C_SMBUS_WRITE && if (read_write == I2C_SMBUS_WRITE &&
size != I2C_SMBUS_PROC_CALL) size != I2C_SMBUS_PROC_CALL &&
size != I2C_SMBUS_BLOCK_PROC_CALL)
return 0; return 0;
switch (size) { switch (size) {
...@@ -345,6 +346,7 @@ static int ismt_process_desc(const struct ismt_desc *desc, ...@@ -345,6 +346,7 @@ static int ismt_process_desc(const struct ismt_desc *desc,
data->word = dma_buffer[0] | (dma_buffer[1] << 8); data->word = dma_buffer[0] | (dma_buffer[1] << 8);
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_PROC_CALL:
if (desc->rxbytes != dma_buffer[0] + 1) if (desc->rxbytes != dma_buffer[0] + 1)
return -EMSGSIZE; return -EMSGSIZE;
...@@ -518,6 +520,18 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, ...@@ -518,6 +520,18 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
} }
break; break;
case I2C_SMBUS_BLOCK_PROC_CALL:
dev_dbg(dev, "I2C_SMBUS_BLOCK_PROC_CALL\n");
dma_size = I2C_SMBUS_BLOCK_MAX;
desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 1);
desc->wr_len_cmd = data->block[0] + 1;
desc->rd_len = dma_size;
desc->control |= ISMT_DESC_BLK;
dma_direction = DMA_BIDIRECTIONAL;
dma_buffer[0] = command;
memcpy(&dma_buffer[1], &data->block[1], data->block[0]);
break;
case I2C_SMBUS_I2C_BLOCK_DATA: case I2C_SMBUS_I2C_BLOCK_DATA:
/* Make sure the length is valid */ /* Make sure the length is valid */
if (data->block[0] < 1) if (data->block[0] < 1)
...@@ -624,6 +638,7 @@ static u32 ismt_func(struct i2c_adapter *adap) ...@@ -624,6 +638,7 @@ static u32 ismt_func(struct i2c_adapter *adap)
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PROC_CALL |
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_I2C_BLOCK |
I2C_FUNC_SMBUS_PEC; I2C_FUNC_SMBUS_PEC;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mv643xx_i2c.h> #include <linux/mv643xx_i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -147,6 +148,7 @@ struct mv64xxx_i2c_data { ...@@ -147,6 +148,7 @@ struct mv64xxx_i2c_data {
bool irq_clear_inverted; bool irq_clear_inverted;
/* Clk div is 2 to the power n, not 2 to the power n + 1 */ /* Clk div is 2 to the power n, not 2 to the power n + 1 */
bool clk_n_base_0; bool clk_n_base_0;
struct i2c_bus_recovery_info rinfo;
}; };
static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
...@@ -325,7 +327,8 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) ...@@ -325,7 +327,8 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
drv_data->msg->flags); drv_data->msg->flags);
drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
mv64xxx_i2c_hw_init(drv_data); mv64xxx_i2c_hw_init(drv_data);
drv_data->rc = -EIO; i2c_recover_bus(&drv_data->adapter);
drv_data->rc = -EAGAIN;
} }
} }
...@@ -561,6 +564,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) ...@@ -561,6 +564,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
"time_left: %d\n", drv_data->block, "time_left: %d\n", drv_data->block,
(int)time_left); (int)time_left);
mv64xxx_i2c_hw_init(drv_data); mv64xxx_i2c_hw_init(drv_data);
i2c_recover_bus(&drv_data->adapter);
} }
} else } else
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock_irqrestore(&drv_data->lock, flags);
...@@ -870,6 +874,25 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, ...@@ -870,6 +874,25 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
} }
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
static int mv64xxx_i2c_init_recovery_info(struct mv64xxx_i2c_data *drv_data,
struct device *dev)
{
struct i2c_bus_recovery_info *rinfo = &drv_data->rinfo;
rinfo->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(rinfo->pinctrl)) {
if (PTR_ERR(rinfo->pinctrl) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "can't get pinctrl, bus recovery not supported\n");
return PTR_ERR(rinfo->pinctrl);
} else if (!rinfo->pinctrl) {
return -ENODEV;
}
drv_data->adapter.bus_recovery_info = rinfo;
return 0;
}
static int static int
mv64xxx_i2c_probe(struct platform_device *pd) mv64xxx_i2c_probe(struct platform_device *pd)
{ {
...@@ -926,6 +949,10 @@ mv64xxx_i2c_probe(struct platform_device *pd) ...@@ -926,6 +949,10 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_reset; goto exit_reset;
} }
rc = mv64xxx_i2c_init_recovery_info(drv_data, &pd->dev);
if (rc == -EPROBE_DEFER)
goto exit_reset;
drv_data->adapter.dev.parent = &pd->dev; drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE; drv_data->adapter.owner = THIS_MODULE;
......
...@@ -781,28 +781,15 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) ...@@ -781,28 +781,15 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
return 0; return 0;
} }
static const struct platform_device_id mxs_i2c_devtype[] = {
{
.name = "imx23-i2c",
.driver_data = MXS_I2C_V1,
}, {
.name = "imx28-i2c",
.driver_data = MXS_I2C_V2,
}, { /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, mxs_i2c_devtype);
static const struct of_device_id mxs_i2c_dt_ids[] = { static const struct of_device_id mxs_i2c_dt_ids[] = {
{ .compatible = "fsl,imx23-i2c", .data = &mxs_i2c_devtype[0], }, { .compatible = "fsl,imx23-i2c", .data = (void *)MXS_I2C_V1, },
{ .compatible = "fsl,imx28-i2c", .data = &mxs_i2c_devtype[1], }, { .compatible = "fsl,imx28-i2c", .data = (void *)MXS_I2C_V2, },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids);
static int mxs_i2c_probe(struct platform_device *pdev) static int mxs_i2c_probe(struct platform_device *pdev)
{ {
const struct of_device_id *of_id =
of_match_device(mxs_i2c_dt_ids, &pdev->dev);
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct mxs_i2c_dev *i2c; struct mxs_i2c_dev *i2c;
struct i2c_adapter *adap; struct i2c_adapter *adap;
...@@ -812,10 +799,7 @@ static int mxs_i2c_probe(struct platform_device *pdev) ...@@ -812,10 +799,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)
if (!i2c) if (!i2c)
return -ENOMEM; return -ENOMEM;
if (of_id) { i2c->dev_type = (enum mxs_i2c_devtype)of_device_get_match_data(&pdev->dev);
const struct platform_device_id *device_id = of_id->data;
i2c->dev_type = device_id->driver_data;
}
i2c->regs = devm_platform_ioremap_resource(pdev, 0); i2c->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(i2c->regs)) if (IS_ERR(i2c->regs))
......
...@@ -353,15 +353,7 @@ static void gpu_i2c_remove(struct pci_dev *pdev) ...@@ -353,15 +353,7 @@ static void gpu_i2c_remove(struct pci_dev *pdev)
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
} }
/* #define gpu_i2c_suspend NULL
* We need gpu_i2c_suspend() even if it is stub, for runtime pm to work
* correctly. Without it, lspci shows runtime pm status as "D0" for the card.
* Documentation/power/pci.rst also insists for driver to provide this.
*/
static __maybe_unused int gpu_i2c_suspend(struct device *dev)
{
return 0;
}
static __maybe_unused int gpu_i2c_resume(struct device *dev) static __maybe_unused int gpu_i2c_resume(struct device *dev)
{ {
......
...@@ -83,7 +83,6 @@ struct ocores_i2c { ...@@ -83,7 +83,6 @@ struct ocores_i2c {
#define TYPE_OCORES 0 #define TYPE_OCORES 0
#define TYPE_GRLIB 1 #define TYPE_GRLIB 1
#define TYPE_SIFIVE_REV0 2
#define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */ #define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */
...@@ -476,11 +475,9 @@ static const struct of_device_id ocores_i2c_match[] = { ...@@ -476,11 +475,9 @@ static const struct of_device_id ocores_i2c_match[] = {
}, },
{ {
.compatible = "sifive,fu540-c000-i2c", .compatible = "sifive,fu540-c000-i2c",
.data = (void *)TYPE_SIFIVE_REV0,
}, },
{ {
.compatible = "sifive,i2c0", .compatible = "sifive,i2c0",
.data = (void *)TYPE_SIFIVE_REV0,
}, },
{}, {},
}; };
...@@ -606,7 +603,6 @@ static int ocores_i2c_probe(struct platform_device *pdev) ...@@ -606,7 +603,6 @@ static int ocores_i2c_probe(struct platform_device *pdev)
{ {
struct ocores_i2c *i2c; struct ocores_i2c *i2c;
struct ocores_i2c_platform_data *pdata; struct ocores_i2c_platform_data *pdata;
const struct of_device_id *match;
struct resource *res; struct resource *res;
int irq; int irq;
int ret; int ret;
...@@ -686,17 +682,20 @@ static int ocores_i2c_probe(struct platform_device *pdev) ...@@ -686,17 +682,20 @@ static int ocores_i2c_probe(struct platform_device *pdev)
init_waitqueue_head(&i2c->wait); init_waitqueue_head(&i2c->wait);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq_optional(pdev, 0);
if (irq == -ENXIO) {
ocores_algorithm.master_xfer = ocores_xfer_polling;
/* /*
* Set in OCORES_FLAG_BROKEN_IRQ to enable workaround for * Since the SoC does have an interrupt, its DT has an interrupt
* FU540-C000 SoC in polling mode. * property - But this should be bypassed as the IRQ logic in this
* SoC is broken.
*/ */
match = of_match_node(ocores_i2c_match, pdev->dev.of_node); if (of_device_is_compatible(pdev->dev.of_node,
if (match && (long)match->data == TYPE_SIFIVE_REV0) "sifive,fu540-c000-i2c")) {
i2c->flags |= OCORES_FLAG_BROKEN_IRQ; i2c->flags |= OCORES_FLAG_BROKEN_IRQ;
irq = -ENXIO;
}
if (irq == -ENXIO) {
ocores_algorithm.master_xfer = ocores_xfer_polling;
} else { } else {
if (irq < 0) if (irq < 0)
return irq; return irq;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -76,6 +77,7 @@ ...@@ -76,6 +77,7 @@
#define OWL_I2C_FIFOCTL_TFR BIT(2) #define OWL_I2C_FIFOCTL_TFR BIT(2)
/* I2Cc_FIFOSTAT Bit Mask */ /* I2Cc_FIFOSTAT Bit Mask */
#define OWL_I2C_FIFOSTAT_CECB BIT(0)
#define OWL_I2C_FIFOSTAT_RNB BIT(1) #define OWL_I2C_FIFOSTAT_RNB BIT(1)
#define OWL_I2C_FIFOSTAT_RFE BIT(2) #define OWL_I2C_FIFOSTAT_RFE BIT(2)
#define OWL_I2C_FIFOSTAT_TFF BIT(5) #define OWL_I2C_FIFOSTAT_TFF BIT(5)
...@@ -83,7 +85,8 @@ ...@@ -83,7 +85,8 @@
#define OWL_I2C_FIFOSTAT_RFD GENMASK(15, 8) #define OWL_I2C_FIFOSTAT_RFD GENMASK(15, 8)
/* I2C bus timeout */ /* I2C bus timeout */
#define OWL_I2C_TIMEOUT msecs_to_jiffies(4 * 1000) #define OWL_I2C_TIMEOUT_MS (4 * 1000)
#define OWL_I2C_TIMEOUT msecs_to_jiffies(OWL_I2C_TIMEOUT_MS)
#define OWL_I2C_MAX_RETRIES 50 #define OWL_I2C_MAX_RETRIES 50
...@@ -161,14 +164,11 @@ static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev) ...@@ -161,14 +164,11 @@ static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev)
writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV); writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV);
} }
static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) static void owl_i2c_xfer_data(struct owl_i2c_dev *i2c_dev)
{ {
struct owl_i2c_dev *i2c_dev = _dev;
struct i2c_msg *msg = i2c_dev->msg; struct i2c_msg *msg = i2c_dev->msg;
unsigned int stat, fifostat; unsigned int stat, fifostat;
spin_lock(&i2c_dev->lock);
i2c_dev->err = 0; i2c_dev->err = 0;
/* Handle NACK from slave */ /* Handle NACK from slave */
...@@ -178,7 +178,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) ...@@ -178,7 +178,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
/* Clear NACK error bit by writing "1" */ /* Clear NACK error bit by writing "1" */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT, owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
OWL_I2C_FIFOSTAT_RNB, true); OWL_I2C_FIFOSTAT_RNB, true);
goto stop; return;
} }
/* Handle bus error */ /* Handle bus error */
...@@ -188,7 +188,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) ...@@ -188,7 +188,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
/* Clear BUS error bit by writing "1" */ /* Clear BUS error bit by writing "1" */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT, owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
OWL_I2C_STAT_BEB, true); OWL_I2C_STAT_BEB, true);
goto stop; return;
} }
/* Handle FIFO read */ /* Handle FIFO read */
...@@ -206,8 +206,16 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) ...@@ -206,8 +206,16 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
i2c_dev->base + OWL_I2C_REG_TXDAT); i2c_dev->base + OWL_I2C_REG_TXDAT);
} }
} }
}
static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
{
struct owl_i2c_dev *i2c_dev = _dev;
spin_lock(&i2c_dev->lock);
owl_i2c_xfer_data(i2c_dev);
stop:
/* Clear pending interrupts */ /* Clear pending interrupts */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT, owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
OWL_I2C_STAT_IRQP, true); OWL_I2C_STAT_IRQP, true);
...@@ -240,8 +248,8 @@ static int owl_i2c_check_bus_busy(struct i2c_adapter *adap) ...@@ -240,8 +248,8 @@ static int owl_i2c_check_bus_busy(struct i2c_adapter *adap)
return 0; return 0;
} }
static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, static int owl_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num) int num, bool atomic)
{ {
struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
struct i2c_msg *msg; struct i2c_msg *msg;
...@@ -285,11 +293,12 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -285,11 +293,12 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
goto err_exit; goto err_exit;
} }
if (!atomic)
reinit_completion(&i2c_dev->msg_complete); reinit_completion(&i2c_dev->msg_complete);
/* Enable I2C controller interrupt */ /* Enable/disable I2C controller interrupt */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
OWL_I2C_CTL_IRQE, true); OWL_I2C_CTL_IRQE, !atomic);
/* /*
* Select: FIFO enable, Master mode, Stop enable, Data count enable, * Select: FIFO enable, Master mode, Stop enable, Data count enable,
...@@ -357,20 +366,33 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -357,20 +366,33 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
spin_unlock_irqrestore(&i2c_dev->lock, flags); spin_unlock_irqrestore(&i2c_dev->lock, flags);
if (atomic) {
/* Wait for Command Execute Completed or NACK Error bits */
ret = readl_poll_timeout_atomic(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
val, val & (OWL_I2C_FIFOSTAT_CECB |
OWL_I2C_FIFOSTAT_RNB),
10, OWL_I2C_TIMEOUT_MS * 1000);
} else {
time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
adap->timeout); adap->timeout);
if (!time_left)
ret = -ETIMEDOUT;
}
spin_lock_irqsave(&i2c_dev->lock, flags); spin_lock_irqsave(&i2c_dev->lock, flags);
if (time_left == 0) {
if (ret) {
dev_err(&adap->dev, "Transaction timed out\n"); dev_err(&adap->dev, "Transaction timed out\n");
/* Send stop condition and release the bus */ /* Send stop condition and release the bus */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB, OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB,
true); true);
ret = -ETIMEDOUT;
goto err_exit; goto err_exit;
} }
if (atomic)
owl_i2c_xfer_data(i2c_dev);
ret = i2c_dev->err < 0 ? i2c_dev->err : num; ret = i2c_dev->err < 0 ? i2c_dev->err : num;
err_exit: err_exit:
...@@ -384,8 +406,21 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -384,8 +406,21 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
return ret; return ret;
} }
static int owl_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
return owl_i2c_xfer_common(adap, msgs, num, false);
}
static int owl_i2c_xfer_atomic(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
return owl_i2c_xfer_common(adap, msgs, num, true);
}
static const struct i2c_algorithm owl_i2c_algorithm = { static const struct i2c_algorithm owl_i2c_algorithm = {
.master_xfer = owl_i2c_master_xfer, .master_xfer = owl_i2c_xfer,
.master_xfer_atomic = owl_i2c_xfer_atomic,
.functionality = owl_i2c_func, .functionality = owl_i2c_func,
}; };
...@@ -473,6 +508,7 @@ static int owl_i2c_probe(struct platform_device *pdev) ...@@ -473,6 +508,7 @@ static int owl_i2c_probe(struct platform_device *pdev)
} }
static const struct of_device_id owl_i2c_of_match[] = { static const struct of_device_id owl_i2c_of_match[] = {
{ .compatible = "actions,s500-i2c" },
{ .compatible = "actions,s700-i2c" }, { .compatible = "actions,s700-i2c" },
{ .compatible = "actions,s900-i2c" }, { .compatible = "actions,s900-i2c" },
{ /* sentinel */ } { /* sentinel */ }
...@@ -484,6 +520,7 @@ static struct platform_driver owl_i2c_driver = { ...@@ -484,6 +520,7 @@ static struct platform_driver owl_i2c_driver = {
.driver = { .driver = {
.name = "owl-i2c", .name = "owl-i2c",
.of_match_table = of_match_ptr(owl_i2c_of_match), .of_match_table = of_match_ptr(owl_i2c_of_match),
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
}, },
}; };
module_platform_driver(owl_i2c_driver); module_platform_driver(owl_i2c_driver);
......
...@@ -33,8 +33,6 @@ struct i2c_pca_pf_data { ...@@ -33,8 +33,6 @@ struct i2c_pca_pf_data {
wait_queue_head_t wait; wait_queue_head_t wait;
struct i2c_adapter adap; struct i2c_adapter adap;
struct i2c_algo_pca_data algo_data; struct i2c_algo_pca_data algo_data;
unsigned long io_base;
unsigned long io_size;
}; };
/* Read/Write functions for different register alignments */ /* Read/Write functions for different register alignments */
...@@ -156,8 +154,6 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) ...@@ -156,8 +154,6 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)
init_waitqueue_head(&i2c->wait); init_waitqueue_head(&i2c->wait);
i2c->io_base = res->start;
i2c->io_size = resource_size(res);
i2c->irq = irq; i2c->irq = irq;
i2c->adap.nr = pdev->id; i2c->adap.nr = pdev->id;
......
...@@ -264,9 +264,6 @@ struct pxa_i2c { ...@@ -264,9 +264,6 @@ struct pxa_i2c {
u32 hs_mask; u32 hs_mask;
struct i2c_bus_recovery_info recovery; struct i2c_bus_recovery_info recovery;
struct pinctrl *pinctrl;
struct pinctrl_state *pinctrl_default;
struct pinctrl_state *pinctrl_recovery;
}; };
#define _IBMR(i2c) ((i2c)->reg_ibmr) #define _IBMR(i2c) ((i2c)->reg_ibmr)
...@@ -1305,13 +1302,12 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter *adap) ...@@ -1305,13 +1302,12 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter *adap)
*/ */
gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS); gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS); gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
} }
static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap) static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
{ {
struct pxa_i2c *i2c = adap->algo_data; struct pxa_i2c *i2c = adap->algo_data;
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
u32 isr; u32 isr;
/* /*
...@@ -1325,7 +1321,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap) ...@@ -1325,7 +1321,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
i2c_pxa_do_reset(i2c); i2c_pxa_do_reset(i2c);
} }
WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default)); WARN_ON(pinctrl_select_state(bri->pinctrl, bri->pins_default));
dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n", dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",
readl(_IBMR(i2c)), readl(_ISR(i2c))); readl(_IBMR(i2c)), readl(_ISR(i2c)));
...@@ -1347,76 +1343,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c) ...@@ -1347,76 +1343,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE)) if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
return 0; return 0;
i2c->pinctrl = devm_pinctrl_get(dev); bri->pinctrl = devm_pinctrl_get(dev);
if (PTR_ERR(i2c->pinctrl) == -ENODEV) if (PTR_ERR(bri->pinctrl) == -ENODEV) {
i2c->pinctrl = NULL; bri->pinctrl = NULL;
if (IS_ERR(i2c->pinctrl))
return PTR_ERR(i2c->pinctrl);
if (!i2c->pinctrl)
return 0;
i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
PINCTRL_STATE_DEFAULT);
i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
PTR_ERR(i2c->pinctrl_default),
PTR_ERR(i2c->pinctrl_recovery));
return 0;
}
/*
* Claiming GPIOs can influence the pinmux state, and may glitch the
* I2C bus. Do this carefully.
*/
bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
return -EPROBE_DEFER;
if (IS_ERR(bri->scl_gpiod)) {
dev_info(dev, "missing scl gpio recovery information: %pe\n",
bri->scl_gpiod);
return 0;
}
/*
* We have SCL. Pull SCL low and wait a bit so that SDA glitches
* have no effect.
*/
gpiod_direction_output(bri->scl_gpiod, 0);
udelay(10);
bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
/* Wait a bit in case of a SDA glitch, and then release SCL. */
udelay(10);
gpiod_direction_output(bri->scl_gpiod, 1);
if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
return -EPROBE_DEFER;
if (IS_ERR(bri->sda_gpiod)) {
dev_info(dev, "missing sda gpio recovery information: %pe\n",
bri->sda_gpiod);
return 0; return 0;
} }
if (IS_ERR(bri->pinctrl))
return PTR_ERR(bri->pinctrl);
bri->prepare_recovery = i2c_pxa_prepare_recovery; bri->prepare_recovery = i2c_pxa_prepare_recovery;
bri->unprepare_recovery = i2c_pxa_unprepare_recovery; bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
bri->recover_bus = i2c_generic_scl_recovery;
i2c->adap.bus_recovery_info = bri; i2c->adap.bus_recovery_info = bri;
/* return 0;
* Claiming GPIOs can change the pinmux state, which confuses the
* pinctrl since pinctrl's idea of the current setting is unaffected
* by the pinmux change caused by claiming the GPIO. Work around that
* by switching pinctrl to the GPIO state here. We do it this way to
* avoid glitching the I2C bus.
*/
pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery);
return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default);
} }
static int i2c_pxa_probe(struct platform_device *dev) static int i2c_pxa_probe(struct platform_device *dev)
......
...@@ -353,19 +353,18 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, ...@@ -353,19 +353,18 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
{ {
dma_addr_t rx_dma; dma_addr_t rx_dma;
unsigned long time_left; unsigned long time_left;
void *dma_buf = NULL; void *dma_buf;
struct geni_se *se = &gi2c->se; struct geni_se *se = &gi2c->se;
size_t len = msg->len; size_t len = msg->len;
if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
if (dma_buf) if (dma_buf)
geni_se_select_mode(se, GENI_SE_DMA); geni_se_select_mode(se, GENI_SE_DMA);
else else
geni_se_select_mode(se, GENI_SE_FIFO); geni_se_select_mode(se, GENI_SE_FIFO);
writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN); writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN);
geni_se_setup_m_cmd(se, I2C_READ, m_param);
if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) { if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) {
geni_se_select_mode(se, GENI_SE_FIFO); geni_se_select_mode(se, GENI_SE_FIFO);
...@@ -373,8 +372,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, ...@@ -373,8 +372,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
dma_buf = NULL; dma_buf = NULL;
} }
geni_se_setup_m_cmd(se, I2C_READ, m_param);
time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
if (!time_left) if (!time_left)
geni_i2c_abort_xfer(gi2c); geni_i2c_abort_xfer(gi2c);
...@@ -395,19 +392,18 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, ...@@ -395,19 +392,18 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
{ {
dma_addr_t tx_dma; dma_addr_t tx_dma;
unsigned long time_left; unsigned long time_left;
void *dma_buf = NULL; void *dma_buf;
struct geni_se *se = &gi2c->se; struct geni_se *se = &gi2c->se;
size_t len = msg->len; size_t len = msg->len;
if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
if (dma_buf) if (dma_buf)
geni_se_select_mode(se, GENI_SE_DMA); geni_se_select_mode(se, GENI_SE_DMA);
else else
geni_se_select_mode(se, GENI_SE_FIFO); geni_se_select_mode(se, GENI_SE_FIFO);
writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN); writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN);
geni_se_setup_m_cmd(se, I2C_WRITE, m_param);
if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) { if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) {
geni_se_select_mode(se, GENI_SE_FIFO); geni_se_select_mode(se, GENI_SE_FIFO);
...@@ -415,8 +411,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, ...@@ -415,8 +411,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
dma_buf = NULL; dma_buf = NULL;
} }
geni_se_setup_m_cmd(se, I2C_WRITE, m_param);
if (!dma_buf) /* Get FIFO IRQ */ if (!dma_buf) /* Get FIFO IRQ */
writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG); writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG);
......
...@@ -956,10 +956,38 @@ static int sh_mobile_i2c_remove(struct platform_device *dev) ...@@ -956,10 +956,38 @@ static int sh_mobile_i2c_remove(struct platform_device *dev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int sh_mobile_i2c_suspend(struct device *dev)
{
struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev);
i2c_mark_adapter_suspended(&pd->adap);
return 0;
}
static int sh_mobile_i2c_resume(struct device *dev)
{
struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev);
i2c_mark_adapter_resumed(&pd->adap);
return 0;
}
static const struct dev_pm_ops sh_mobile_i2c_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_mobile_i2c_suspend,
sh_mobile_i2c_resume)
};
#define DEV_PM_OPS (&sh_mobile_i2c_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
static struct platform_driver sh_mobile_i2c_driver = { static struct platform_driver sh_mobile_i2c_driver = {
.driver = { .driver = {
.name = "i2c-sh_mobile", .name = "i2c-sh_mobile",
.of_match_table = sh_mobile_i2c_dt_ids, .of_match_table = sh_mobile_i2c_dt_ids,
.pm = DEV_PM_OPS,
}, },
.probe = sh_mobile_i2c_probe, .probe = sh_mobile_i2c_probe,
.remove = sh_mobile_i2c_remove, .remove = sh_mobile_i2c_remove,
......
...@@ -549,17 +549,18 @@ static int i2c_device_probe(struct device *dev) ...@@ -549,17 +549,18 @@ static int i2c_device_probe(struct device *dev)
static int i2c_device_remove(struct device *dev) static int i2c_device_remove(struct device *dev)
{ {
struct i2c_client *client = i2c_verify_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver; struct i2c_driver *driver;
int status = 0;
if (!client || !dev->driver)
return 0;
driver = to_i2c_driver(dev->driver); driver = to_i2c_driver(dev->driver);
if (driver->remove) { if (driver->remove) {
int status;
dev_dbg(dev, "remove\n"); dev_dbg(dev, "remove\n");
status = driver->remove(client); status = driver->remove(client);
if (status)
dev_warn(dev, "remove failed (%pe), will be ignored\n", ERR_PTR(status));
} }
dev_pm_domain_detach(&client->dev, true); dev_pm_domain_detach(&client->dev, true);
...@@ -571,7 +572,8 @@ static int i2c_device_remove(struct device *dev) ...@@ -571,7 +572,8 @@ static int i2c_device_remove(struct device *dev)
if (client->flags & I2C_CLIENT_HOST_NOTIFY) if (client->flags & I2C_CLIENT_HOST_NOTIFY)
pm_runtime_put(&client->adapter->dev); pm_runtime_put(&client->adapter->dev);
return status; /* return always 0 because there is WIP to make remove-functions void */
return 0;
} }
static void i2c_device_shutdown(struct device *dev) static void i2c_device_shutdown(struct device *dev)
......
...@@ -266,35 +266,62 @@ EXPORT_SYMBOL(geni_se_init); ...@@ -266,35 +266,62 @@ EXPORT_SYMBOL(geni_se_init);
static void geni_se_select_fifo_mode(struct geni_se *se) static void geni_se_select_fifo_mode(struct geni_se *se)
{ {
u32 proto = geni_se_read_proto(se); u32 proto = geni_se_read_proto(se);
u32 val; u32 val, val_old;
geni_se_irq_clear(se); geni_se_irq_clear(se);
val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); /*
* The RX path for the UART is asynchronous and so needs more
* complex logic for enabling / disabling its interrupts.
*
* Specific notes:
* - The done and TX-related interrupts are managed manually.
* - We don't RX from the main sequencer (we use the secondary) so
* we don't need the RX-related interrupts enabled in the main
* sequencer for UART.
*/
if (proto != GENI_SE_UART) { if (proto != GENI_SE_UART) {
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN; val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN;
val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
} if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
if (proto != GENI_SE_UART)
val |= S_CMD_DONE_EN; val |= S_CMD_DONE_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
val &= ~GENI_DMA_MODE_EN; val &= ~GENI_DMA_MODE_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
} }
static void geni_se_select_dma_mode(struct geni_se *se) static void geni_se_select_dma_mode(struct geni_se *se)
{ {
u32 val; u32 proto = geni_se_read_proto(se);
u32 val, val_old;
geni_se_irq_clear(se); geni_se_irq_clear(se);
val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); if (proto != GENI_SE_UART) {
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
val &= ~S_CMD_DONE_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
val |= GENI_DMA_MODE_EN; val |= GENI_DMA_MODE_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
} }
...@@ -651,7 +678,7 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len, ...@@ -651,7 +678,7 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L); writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L);
writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H); writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H);
writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR); writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
writel_relaxed(len, se->base + SE_DMA_TX_LEN); writel(len, se->base + SE_DMA_TX_LEN);
return 0; return 0;
} }
EXPORT_SYMBOL(geni_se_tx_dma_prep); EXPORT_SYMBOL(geni_se_tx_dma_prep);
...@@ -688,7 +715,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len, ...@@ -688,7 +715,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H); writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H);
/* RX does not have EOT buffer type bit. So just reset RX_ATTR */ /* RX does not have EOT buffer type bit. So just reset RX_ATTR */
writel_relaxed(0, se->base + SE_DMA_RX_ATTR); writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
writel_relaxed(len, se->base + SE_DMA_RX_LEN); writel(len, se->base + SE_DMA_RX_LEN);
return 0; return 0;
} }
EXPORT_SYMBOL(geni_se_rx_dma_prep); EXPORT_SYMBOL(geni_se_rx_dma_prep);
......
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