All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-06  8:37 ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: srv_heupstream, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Matthias Brugger, Jean Delvare,
	David Box, Doug Anderson, Zhangfei Gao, Max Schwarz,
	Boris BREZILLON, Anders Berg, Neelesh Gupta, Lee Jones,
	Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan, Beniamino Galvani,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek

This series is for Mediatek SoCs I2C controller common bus driver.

Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
New generation SoC like MT8173 fix following limitations:

1. Only support one i2c_msg number. One exception is WRRD (write then read)
mode. WRRD can have two i2c_msg numbers.

2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
mode the Repeat Start will be issued between 2 messages.
In this driver if 2 messages is first write then read, the driver will
combine 2 messages using Write-Read mode so the RS will be issued between
the 2 messages.

3. The max transfer data length is 255 in one message. In WRRD mode, the
max data length of second msg is 31.

MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
bit first, the operation on other registers are still the same.
For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
"mediatek,have-pmic" property in the .dts file of each platform.

This driver is based on 4.1-rc1.

Change in v7:
Fix mtk_i2c_of_match in wrong patch bug.

Change in v6:
1. Update binding document not use default clock-frequency as example.
2. Add mtk_i2c_compatible struct and pass hardware capabilities
   through of_device_id
3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
   so just init one time.
4. Correct mtk_i2c_parse_dt don't set default clock bug.

Change in v5:
Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
Add MT8173 I2C driver.

Change in v4:
Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
Remove check transfer size and WRRD combine code. Instead, fill quirk
property and let i2c_check_for_quirks to do the filter.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html

Eddie Huang (1):
  I2C: mediatek: Add driver for MediaTek MT8173 I2C controller

Xudong Chen (2):
  dt-bindings: Add I2C bindings for mt65xx/mt81xx.
  I2C: mediatek: Add driver for MediaTek I2C controller

 .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
 drivers/i2c/busses/Kconfig                         |   9 +
 drivers/i2c/busses/Makefile                        |   1 +
 drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
 4 files changed, 799 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

--
1.8.1.1.dirty


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-06  8:37 ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani, Xudong Chen, Liguo Zhang

This series is for Mediatek SoCs I2C controller common bus driver.

Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
New generation SoC like MT8173 fix following limitations:

1. Only support one i2c_msg number. One exception is WRRD (write then read)
mode. WRRD can have two i2c_msg numbers.

2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
mode the Repeat Start will be issued between 2 messages.
In this driver if 2 messages is first write then read, the driver will
combine 2 messages using Write-Read mode so the RS will be issued between
the 2 messages.

3. The max transfer data length is 255 in one message. In WRRD mode, the
max data length of second msg is 31.

MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
bit first, the operation on other registers are still the same.
For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
"mediatek,have-pmic" property in the .dts file of each platform.

This driver is based on 4.1-rc1.

Change in v7:
Fix mtk_i2c_of_match in wrong patch bug.

Change in v6:
1. Update binding document not use default clock-frequency as example.
2. Add mtk_i2c_compatible struct and pass hardware capabilities
   through of_device_id
3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
   so just init one time.
4. Correct mtk_i2c_parse_dt don't set default clock bug.

Change in v5:
Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
Add MT8173 I2C driver.

Change in v4:
Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
Remove check transfer size and WRRD combine code. Instead, fill quirk
property and let i2c_check_for_quirks to do the filter.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html

Eddie Huang (1):
  I2C: mediatek: Add driver for MediaTek MT8173 I2C controller

Xudong Chen (2):
  dt-bindings: Add I2C bindings for mt65xx/mt81xx.
  I2C: mediatek: Add driver for MediaTek I2C controller

 .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
 drivers/i2c/busses/Kconfig                         |   9 +
 drivers/i2c/busses/Makefile                        |   1 +
 drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
 4 files changed, 799 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

--
1.8.1.1.dirty

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-06  8:37 ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

This series is for Mediatek SoCs I2C controller common bus driver.

Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
New generation SoC like MT8173 fix following limitations:

1. Only support one i2c_msg number. One exception is WRRD (write then read)
mode. WRRD can have two i2c_msg numbers.

2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
mode the Repeat Start will be issued between 2 messages.
In this driver if 2 messages is first write then read, the driver will
combine 2 messages using Write-Read mode so the RS will be issued between
the 2 messages.

3. The max transfer data length is 255 in one message. In WRRD mode, the
max data length of second msg is 31.

MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
bit first, the operation on other registers are still the same.
For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
"mediatek,have-pmic" property in the .dts file of each platform.

This driver is based on 4.1-rc1.

Change in v7:
Fix mtk_i2c_of_match in wrong patch bug.

Change in v6:
1. Update binding document not use default clock-frequency as example.
2. Add mtk_i2c_compatible struct and pass hardware capabilities
   through of_device_id
3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
   so just init one time.
4. Correct mtk_i2c_parse_dt don't set default clock bug.

Change in v5:
Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
Add MT8173 I2C driver.

Change in v4:
Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
Remove check transfer size and WRRD combine code. Instead, fill quirk
property and let i2c_check_for_quirks to do the filter.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html

Eddie Huang (1):
  I2C: mediatek: Add driver for MediaTek MT8173 I2C controller

Xudong Chen (2):
  dt-bindings: Add I2C bindings for mt65xx/mt81xx.
  I2C: mediatek: Add driver for MediaTek I2C controller

 .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
 drivers/i2c/busses/Kconfig                         |   9 +
 drivers/i2c/busses/Makefile                        |   1 +
 drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
 4 files changed, 799 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

--
1.8.1.1.dirty

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: srv_heupstream, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Matthias Brugger, Jean Delvare,
	David Box, Doug Anderson, Zhangfei Gao, Max Schwarz,
	Boris BREZILLON, Anders Berg, Neelesh Gupta, Lee Jones,
	Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan, Beniamino Galvani,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, Eddie Huang

From: Xudong Chen <xudong.chen@mediatek.com>

Add devicetree bindings for Mediatek Soc I2C driver.

Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
---
 .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
new file mode 100644
index 0000000..0ce6fa3
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
@@ -0,0 +1,41 @@
+* Mediatek's I2C controller
+
+The Mediatek's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
+      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
+      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
+      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
+      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
+  - reg: physical base address of the controller and dma base, length of memory
+    mapped region.
+  - interrupts: interrupt number to the cpu.
+  - clock-div: the fixed value for frequency divider of clock source in i2c
+    module. Each IC may be different.
+  - clocks: clock name from clock manager
+  - clock-names: Must include "main" and "dma", if enable have-pmic need include
+    "pmic" extra.
+
+Optional properties:
+  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
+    is 100000.
+  - mediatek,have-pmic: platform can control i2c form special pmic side.
+    Only mt6589 and mt8135 support this feature.
+  - mediatek,use-push-pull: IO config use push-pull mode.
+
+Example:
+
+	i2c0: i2c@1100d000 {
+			compatible = "mediatek,mt6577-i2c";
+			reg = <0x1100d000 0x70>,
+			      <0x11000300 0x80>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
+			clock-frequency = <400000>;
+			mediatek,have-pmic;
+			clock-div = <16>;
+			clocks = <&i2c0_ck>, <&ap_dma_ck>;
+			clock-names = "main", "dma";
+	};
+
-- 
1.8.1.1.dirty


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani, Xudong Chen, Liguo Zhang

From: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>

Add devicetree bindings for Mediatek Soc I2C driver.

Signed-off-by: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Signed-off-by: Eddie Huang <eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
new file mode 100644
index 0000000..0ce6fa3
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
@@ -0,0 +1,41 @@
+* Mediatek's I2C controller
+
+The Mediatek's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
+      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
+      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
+      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
+      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
+  - reg: physical base address of the controller and dma base, length of memory
+    mapped region.
+  - interrupts: interrupt number to the cpu.
+  - clock-div: the fixed value for frequency divider of clock source in i2c
+    module. Each IC may be different.
+  - clocks: clock name from clock manager
+  - clock-names: Must include "main" and "dma", if enable have-pmic need include
+    "pmic" extra.
+
+Optional properties:
+  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
+    is 100000.
+  - mediatek,have-pmic: platform can control i2c form special pmic side.
+    Only mt6589 and mt8135 support this feature.
+  - mediatek,use-push-pull: IO config use push-pull mode.
+
+Example:
+
+	i2c0: i2c@1100d000 {
+			compatible = "mediatek,mt6577-i2c";
+			reg = <0x1100d000 0x70>,
+			      <0x11000300 0x80>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
+			clock-frequency = <400000>;
+			mediatek,have-pmic;
+			clock-div = <16>;
+			clocks = <&i2c0_ck>, <&ap_dma_ck>;
+			clock-names = "main", "dma";
+	};
+
-- 
1.8.1.1.dirty

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xudong Chen <xudong.chen@mediatek.com>

Add devicetree bindings for Mediatek Soc I2C driver.

Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
---
 .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
new file mode 100644
index 0000000..0ce6fa3
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
@@ -0,0 +1,41 @@
+* Mediatek's I2C controller
+
+The Mediatek's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
+      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
+      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
+      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
+      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
+  - reg: physical base address of the controller and dma base, length of memory
+    mapped region.
+  - interrupts: interrupt number to the cpu.
+  - clock-div: the fixed value for frequency divider of clock source in i2c
+    module. Each IC may be different.
+  - clocks: clock name from clock manager
+  - clock-names: Must include "main" and "dma", if enable have-pmic need include
+    "pmic" extra.
+
+Optional properties:
+  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
+    is 100000.
+  - mediatek,have-pmic: platform can control i2c form special pmic side.
+    Only mt6589 and mt8135 support this feature.
+  - mediatek,use-push-pull: IO config use push-pull mode.
+
+Example:
+
+	i2c0: i2c at 1100d000 {
+			compatible = "mediatek,mt6577-i2c";
+			reg = <0x1100d000 0x70>,
+			      <0x11000300 0x80>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
+			clock-frequency = <400000>;
+			mediatek,have-pmic;
+			clock-div = <16>;
+			clocks = <&i2c0_ck>, <&ap_dma_ck>;
+			clock-names = "main", "dma";
+	};
+
-- 
1.8.1.1.dirty

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: srv_heupstream, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Matthias Brugger, Jean Delvare,
	David Box, Doug Anderson, Zhangfei Gao, Max Schwarz,
	Boris BREZILLON, Anders Berg, Neelesh Gupta, Lee Jones,
	Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan, Beniamino Galvani,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, Eddie Huang

From: Xudong Chen <xudong.chen@mediatek.com>

The mediatek SoCs have I2C controller that handle I2C transfer.
This patch include common I2C bus driver.
This driver is compatible with I2C controller on mt65xx/mt81xx.

Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
---
 drivers/i2c/busses/Kconfig      |   9 +
 drivers/i2c/busses/Makefile     |   1 +
 drivers/i2c/busses/i2c-mt65xx.c | 700 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 710 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 2255af2..14c7266 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -620,6 +620,15 @@ config I2C_MPC
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
 
+config I2C_MT65XX
+	tristate "MediaTek I2C adapter"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  This selects the MediaTek(R) Integrated Inter Circuit bus driver
+	  for MT65xx and MT81xx.
+	  If you want to use MediaTek(R) I2C interface, say Y or M here.
+	  If unsure, say N.
+
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
 	depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index cdf941d..abbf422 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_JZ4780)	+= i2c-jz4780.o
 obj-$(CONFIG_I2C_KEMPLD)	+= i2c-kempld.o
 obj-$(CONFIG_I2C_MESON)		+= i2c-meson.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
+obj-$(CONFIG_I2C_MT65XX)	+= i2c-mt65xx.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
new file mode 100644
index 0000000..faecf7e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Xudong.chen <xudong.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+
+#define I2C_HS_NACKERR			(1 << 2)
+#define I2C_ACKERR			(1 << 1)
+#define I2C_TRANSAC_COMP		(1 << 0)
+#define I2C_TRANSAC_START		(1 << 0)
+#define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
+#define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
+#define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
+#define I2C_TIMING_DATA_READ_MASK	(0x7 << 12)
+#define I2C_DCM_DISABLE			0x0000
+#define I2C_IO_CONFIG_OPEN_DRAIN	0x0003
+#define I2C_IO_CONFIG_PUSH_PULL		0x0000
+#define I2C_SOFT_RST			0x0001
+#define I2C_FIFO_ADDR_CLR		0x0001
+#define I2C_DELAY_LEN			0x0002
+#define I2C_ST_START_CON		0x8001
+#define I2C_FS_START_CON		0x1800
+#define I2C_TIME_CLR_VALUE		0x0000
+#define I2C_TIME_DEFAULT_VALUE		0x0003
+#define I2C_FS_TIME_INIT_VALUE		0x1303
+#define I2C_WRRD_TRANAC_VALUE		0x0002
+#define I2C_RD_TRANAC_VALUE		0x0001
+
+#define I2C_DMA_CON_TX			0x0000
+#define I2C_DMA_CON_RX			0x0001
+#define I2C_DMA_START_EN		0x0001
+#define I2C_DMA_INT_FLAG_NONE		0x0000
+#define I2C_DMA_CLR_FLAG		0x0000
+
+#define I2C_DEFAUT_SPEED		100000	/* hz */
+#define MAX_FS_MODE_SPEED		400000
+#define MAX_HS_MODE_SPEED		3400000
+#define MAX_MSG_NUM_MT6577		1
+#define MAX_DMA_TRANS_SIZE_MT6577	255
+#define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_SAMPLE_CNT_DIV		8
+#define MAX_STEP_CNT_DIV		64
+#define MAX_HS_STEP_CNT_DIV		8
+
+#define I2C_CONTROL_RS                  (0x1 << 1)
+#define I2C_CONTROL_DMA_EN              (0x1 << 2)
+#define I2C_CONTROL_CLK_EXT_EN          (0x1 << 3)
+#define I2C_CONTROL_DIR_CHANGE          (0x1 << 4)
+#define I2C_CONTROL_ACKERR_DET_EN       (0x1 << 5)
+#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
+#define I2C_CONTROL_WRAPPER             (0x1 << 0)
+
+#define I2C_DRV_NAME		"mt-i2c"
+
+enum DMA_REGS_OFFSET {
+	OFFSET_INT_FLAG = 0x0,
+	OFFSET_INT_EN = 0x04,
+	OFFSET_EN = 0x08,
+	OFFSET_CON = 0x18,
+	OFFSET_TX_MEM_ADDR = 0x1c,
+	OFFSET_RX_MEM_ADDR = 0x20,
+	OFFSET_TX_LEN = 0x24,
+	OFFSET_RX_LEN = 0x28,
+};
+
+enum i2c_trans_st_rs {
+	I2C_TRANS_STOP = 0,
+	I2C_TRANS_REPEATED_START,
+};
+
+enum mtk_trans_op {
+	I2C_MASTER_WR = 1,
+	I2C_MASTER_RD,
+	I2C_MASTER_WRRD,
+};
+
+enum I2C_REGS_OFFSET {
+	OFFSET_DATA_PORT = 0x0,
+	OFFSET_SLAVE_ADDR = 0x04,
+	OFFSET_INTR_MASK = 0x08,
+	OFFSET_INTR_STAT = 0x0c,
+	OFFSET_CONTROL = 0x10,
+	OFFSET_TRANSFER_LEN = 0x14,
+	OFFSET_TRANSAC_LEN = 0x18,
+	OFFSET_DELAY_LEN = 0x1c,
+	OFFSET_TIMING = 0x20,
+	OFFSET_START = 0x24,
+	OFFSET_EXT_CONF = 0x28,
+	OFFSET_FIFO_STAT = 0x30,
+	OFFSET_FIFO_THRESH = 0x34,
+	OFFSET_FIFO_ADDR_CLR = 0x38,
+	OFFSET_IO_CONFIG = 0x40,
+	OFFSET_RSV_DEBUG = 0x44,
+	OFFSET_HS = 0x48,
+	OFFSET_SOFTRESET = 0x50,
+	OFFSET_DCM_EN = 0x54,
+	OFFSET_PATH_DIR = 0x60,
+	OFFSET_DEBUGSTAT = 0x64,
+	OFFSET_DEBUGCTRL = 0x68,
+	OFFSET_TRANSFER_LEN_AUX = 0x6c,
+};
+
+struct mtk_i2c_data {
+	unsigned int clk_frequency;	/* bus speed in Hz */
+	unsigned int flags;
+	unsigned int clk_src_div;
+};
+
+struct mtk_i2c_compatible {
+	const struct i2c_adapter_quirks *quirks;
+	unsigned char pmic_i2c;
+	unsigned char dcm;
+};
+
+struct mtk_i2c {
+	struct i2c_adapter adap;	/* i2c host adapter */
+	struct device *dev;
+	struct completion msg_complete;
+
+	/* set in i2c probe */
+	void __iomem *base;		/* i2c base addr */
+	void __iomem *pdmabase;		/* dma base address*/
+	struct clk *clk_main;		/* main clock for i2c bus */
+	struct clk *clk_dma;		/* DMA clock for i2c via DMA */
+	struct clk *clk_pmic;		/* PMIC clock for i2c from PMIC */
+	bool have_pmic;			/* can use i2c pins from PMIC */
+	bool use_push_pull;		/* IO config push-pull mode */
+
+	u16 irq_stat;			/* interrupt status */
+	unsigned int speed_hz;		/* The speed in transfer */
+	enum mtk_trans_op op;
+	u16 timing_reg;
+	u16 high_speed_reg;
+	const struct mtk_i2c_compatible *dev_comp;
+};
+
+static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
+	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
+	.max_num_msgs = MAX_MSG_NUM_MT6577,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
+};
+
+static const struct mtk_i2c_compatible mt6577_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+};
+
+static const struct mtk_i2c_compatible mt6589_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 1,
+	.dcm = 0,
+};
+
+static const struct of_device_id mtk_i2c_of_match[] = {
+	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
+	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
+
+static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writew(value, i2c->base + offset);
+}
+
+static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
+{
+	return readw(i2c->base + offset);
+}
+
+static inline void mtk_i2c_writel_dma(u32 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writel(value, i2c->pdmabase + offset);
+}
+
+static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
+{
+	int ret;
+
+	ret = clk_prepare_enable(i2c->clk_dma);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(i2c->clk_main);
+	if (ret)
+		goto err_main;
+
+	if (i2c->have_pmic) {
+		ret = clk_prepare_enable(i2c->clk_pmic);
+		if (ret)
+			goto err_pmic;
+	}
+	return 0;
+
+err_pmic:
+	clk_disable_unprepare(i2c->clk_main);
+err_main:
+	clk_disable_unprepare(i2c->clk_dma);
+
+	return ret;
+}
+
+static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
+{
+	if (i2c->have_pmic)
+		clk_disable_unprepare(i2c->clk_pmic);
+
+	clk_disable_unprepare(i2c->clk_main);
+	clk_disable_unprepare(i2c->clk_dma);
+}
+
+static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
+{
+	u16 control_reg;
+
+	mtk_i2c_writew(I2C_SOFT_RST, i2c, OFFSET_SOFTRESET);
+	/* Set ioconfig */
+	if (i2c->use_push_pull)
+		mtk_i2c_writew(I2C_IO_CONFIG_PUSH_PULL, i2c, OFFSET_IO_CONFIG);
+	else
+		mtk_i2c_writew(I2C_IO_CONFIG_OPEN_DRAIN, i2c, OFFSET_IO_CONFIG);
+
+	if (i2c->dev_comp->dcm)
+		mtk_i2c_writew(I2C_DCM_DISABLE, i2c, OFFSET_DCM_EN);
+
+	mtk_i2c_writew(i2c->timing_reg, i2c, OFFSET_TIMING);
+	mtk_i2c_writew(i2c->high_speed_reg, i2c, OFFSET_HS);
+
+	/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
+	if (i2c->have_pmic)
+		mtk_i2c_writew(I2C_CONTROL_WRAPPER, i2c, OFFSET_PATH_DIR);
+
+	control_reg = I2C_CONTROL_ACKERR_DET_EN |
+		I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+	mtk_i2c_writew(I2C_DELAY_LEN, i2c, OFFSET_DELAY_LEN);
+}
+
+/* calculate i2c port speed */
+static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
+{
+	unsigned int khz;
+	unsigned int step_cnt;
+	unsigned int sample_cnt;
+	unsigned int sclk;
+	unsigned int hclk;
+	unsigned int max_step_cnt;
+	unsigned int sample_div = MAX_SAMPLE_CNT_DIV;
+	unsigned int step_div;
+	unsigned int min_div;
+	unsigned int best_mul;
+	unsigned int cnt_mul;
+
+	if (i2c->speed_hz > MAX_HS_MODE_SPEED)
+		return -EINVAL;
+	else if (i2c->speed_hz > MAX_FS_MODE_SPEED)
+		max_step_cnt = MAX_HS_STEP_CNT_DIV;
+	else
+		max_step_cnt = MAX_STEP_CNT_DIV;
+
+	step_div = max_step_cnt;
+	/* Find the best combination */
+	khz = i2c->speed_hz / 1000;
+	hclk = clk_src_in_hz / 1000;
+	min_div = ((hclk >> 1) + khz - 1) / khz;
+	best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
+
+	for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
+		step_cnt = (min_div + sample_cnt - 1) / sample_cnt;
+		cnt_mul = step_cnt * sample_cnt;
+		if (step_cnt > max_step_cnt)
+			continue;
+
+		if (cnt_mul < best_mul) {
+			best_mul = cnt_mul;
+			sample_div = sample_cnt;
+			step_div = step_cnt;
+			if (best_mul == min_div)
+				break;
+		}
+	}
+
+	sample_cnt = sample_div;
+	step_cnt = step_div;
+	sclk = hclk / (2 * sample_cnt * step_cnt);
+	if (sclk > khz) {
+		dev_dbg(i2c->dev, "%s mode: unsupported speed (%ldkhz)\n",
+			(i2c->speed_hz > MAX_HS_MODE_SPEED) ? "HS" : "ST/FT",
+			(long int)khz);
+		return -ENOTSUPP;
+	}
+
+	step_cnt--;
+	sample_cnt--;
+
+	if (i2c->speed_hz > MAX_FS_MODE_SPEED) {
+		/* Set the hign speed mode register */
+		i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
+		i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 12 |
+			(step_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8;
+	} else {
+		i2c->timing_reg =
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8 |
+			(step_cnt & I2C_TIMING_STEP_DIV_MASK) << 0;
+		/* Disable the high speed transaction */
+		i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+{
+	u16 addr_reg;
+	u16 control_reg;
+	dma_addr_t rpaddr = 0;
+	dma_addr_t wpaddr = 0;
+	int ret;
+
+	i2c->irq_stat = 0;
+
+	reinit_completion(&i2c->msg_complete);
+
+	control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
+			~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
+	if (i2c->speed_hz > 400000)
+		control_reg |= I2C_CONTROL_RS;
+	if (i2c->op == I2C_MASTER_WRRD)
+		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+
+	/* set start condition */
+	if (i2c->speed_hz <= 100000)
+		mtk_i2c_writew(I2C_ST_START_CON, i2c, OFFSET_EXT_CONF);
+	else
+		mtk_i2c_writew(I2C_FS_START_CON, i2c, OFFSET_EXT_CONF);
+
+	addr_reg = msgs->addr << 1;
+	if (i2c->op == I2C_MASTER_RD)
+		addr_reg |= 0x1;
+	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
+
+	/* Clear interrupt status */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
+
+	/* Enable interrupt */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_MASK);
+
+	/* Set transfer and transaction len */
+	if (i2c->op == I2C_MASTER_WRRD) {
+		mtk_i2c_writew(msgs->len | ((msgs + 1)->len) << 8,
+			i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	} else {
+		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	}
+
+	/* Prepare buffer data to start transfer */
+	if (i2c->op == I2C_MASTER_RD) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_RX, i2c, OFFSET_CON);
+		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_RX_LEN);
+	} else if (i2c->op == I2C_MASTER_WR) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_TX, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+	} else {
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		rpaddr = dma_map_single(i2c->adap.dev.parent, (msgs + 1)->buf,
+						(msgs + 1)->len,
+						DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr)) {
+			dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+						msgs->len, DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+		mtk_i2c_writel_dma((msgs + 1)->len, i2c, OFFSET_RX_LEN);
+	}
+
+	/* flush before sending start */
+	mb();
+	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
+	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	ret = wait_for_completion_timeout(&i2c->msg_complete,
+				i2c->adap.timeout);
+
+	/* Clear interrupt mask */
+	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
+
+	if (i2c->op == I2C_MASTER_WR) {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+					msgs->len, DMA_TO_DEVICE);
+	} else if (i2c->op == I2C_MASTER_RD) {
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr,
+					msgs->len, DMA_FROM_DEVICE);
+	} else {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr, msgs->len,
+					DMA_TO_DEVICE);
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr, (msgs + 1)->len,
+					DMA_FROM_DEVICE);
+	}
+
+	if (ret == 0) {
+		dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -ETIMEDOUT;
+	}
+
+	completion_done(&i2c->msg_complete);
+
+	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
+		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_transfer(struct i2c_adapter *adap,
+	struct i2c_msg msgs[], int num)
+{
+	int ret;
+	int left_num = num;
+	struct mtk_i2c *i2c = i2c_get_adapdata(adap);
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret)
+		return ret;
+
+	if (msgs->buf == NULL) {
+		dev_dbg(i2c->dev, "data buffer is NULL.\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	if (msgs->flags & I2C_M_RD)
+		i2c->op = I2C_MASTER_RD;
+	else
+		i2c->op = I2C_MASTER_WR;
+
+	if (num > 1) {
+		/* combined two messages into one transaction */
+		i2c->op = I2C_MASTER_WRRD;
+		left_num--;
+	}
+
+	/* always use DMA mode. */
+	ret = mtk_i2c_do_transfer(i2c, msgs);
+	if (ret < 0)
+		goto err_exit;
+
+	/* the return value is number of executed messages */
+	ret = num;
+
+err_exit:
+	mtk_i2c_clock_disable(i2c);
+	return ret;
+}
+
+static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
+{
+	struct mtk_i2c *i2c = dev_id;
+
+	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+
+	complete(&i2c->msg_complete);
+
+	return IRQ_HANDLED;
+}
+
+static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm mtk_i2c_algorithm = {
+	.master_xfer = mtk_i2c_transfer,
+	.functionality = mtk_i2c_functionality,
+};
+
+static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
+	unsigned int *clk_src_div)
+{
+	int ret;
+
+	ret = of_property_read_u32(np, "clock-frequency", &i2c->speed_hz);
+	if (ret < 0)
+		i2c->speed_hz = I2C_DEFAUT_SPEED;
+
+	ret = of_property_read_u32(np, "clock-div", clk_src_div);
+	if (ret < 0)
+		return ret;
+
+	if (*clk_src_div == 0)
+		return -EINVAL;
+
+	i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
+	i2c->use_push_pull =
+		of_property_read_bool(np, "mediatek,use-push-pull");
+
+	return 0;
+}
+
+static int mtk_i2c_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+	int ret = 0;
+	struct mtk_i2c *i2c;
+	struct clk *clk;
+	unsigned int clk_src_in_hz;
+	unsigned int clk_src_div;
+	struct resource *res;
+	int irq;
+
+	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+	if (i2c == NULL)
+		return -ENOMEM;
+
+	ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div);
+	if (ret)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i2c->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->base))
+		return PTR_ERR(i2c->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->pdmabase))
+		return PTR_ERR(i2c->pdmabase);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return irq;
+
+	init_completion(&i2c->msg_complete);
+
+	of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	i2c->dev_comp = of_id->data;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
+	i2c->dev = &i2c->adap.dev;
+	i2c->adap.dev.parent = &pdev->dev;
+	i2c->adap.owner = THIS_MODULE;
+	i2c->adap.algo = &mtk_i2c_algorithm;
+	i2c->adap.quirks = i2c->dev_comp->quirks;
+	i2c->adap.timeout = 2 * HZ;
+	i2c->adap.retries = 1;
+
+	if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
+		return -EINVAL;
+
+	i2c->clk_main = devm_clk_get(&pdev->dev, "main");
+	if (IS_ERR(i2c->clk_main)) {
+		dev_err(&pdev->dev, "cannot get main clock\n");
+		return PTR_ERR(i2c->clk_main);
+	}
+
+	i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
+	if (IS_ERR(i2c->clk_dma)) {
+		dev_err(&pdev->dev, "cannot get dma clock\n");
+		return PTR_ERR(i2c->clk_dma);
+	}
+
+	clk = i2c->clk_main;
+	if (i2c->have_pmic) {
+		i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
+		if (IS_ERR(i2c->clk_pmic)) {
+			dev_err(&pdev->dev, "cannot get pmic clock\n");
+			return PTR_ERR(i2c->clk_pmic);
+		}
+		clk = i2c->clk_pmic;
+	}
+	clk_src_in_hz = clk_get_rate(clk) / clk_src_div;
+
+	dev_dbg(&pdev->dev, "clock source %p,clock src frequency %d\n",
+		i2c->clk_main, clk_src_in_hz);
+	strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
+
+	ret = mtk_i2c_set_speed(i2c, clk_src_in_hz);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set the speed.\n");
+		return -EINVAL;
+	}
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret) {
+		dev_err(&pdev->dev, "clock enable failed!\n");
+		return ret;
+	}
+	mtk_i2c_init_hw(i2c);
+	mtk_i2c_clock_disable(i2c);
+
+	ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
+		IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Request I2C IRQ %d fail\n", irq);
+		return ret;
+	}
+
+	i2c_set_adapdata(&i2c->adap, i2c);
+	ret = i2c_add_adapter(&i2c->adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, i2c);
+
+	return 0;
+}
+
+static int mtk_i2c_remove(struct platform_device *pdev)
+{
+	struct mtk_i2c *i2c = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&i2c->adap);
+
+	return 0;
+}
+
+static struct platform_driver mtk_i2c_driver = {
+	.probe = mtk_i2c_probe,
+	.remove = mtk_i2c_remove,
+	.driver = {
+		.name = I2C_DRV_NAME,
+		.of_match_table = of_match_ptr(mtk_i2c_of_match),
+	},
+};
+
+module_platform_driver(mtk_i2c_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MediaTek I2C Bus Driver");
+MODULE_AUTHOR("Xudong Chen <xudong.chen@mediatek.com>");
-- 
1.8.1.1.dirty


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: Mark Rutland, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, David Box, Lee Jones,
	Jean Delvare, Xudong Chen, Boris BREZILLON, Arnd Bergmann,
	Liguo Zhang, Wei Yan, Neelesh Gupta, Zhangfei Gao,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Pawel Moll, Ian Campbell,
	Ray Jui, Beniamino Galvani, Rob Herring,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Matthias Brugger, Eddie Huang,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	srv_heupstream-NuS5LvNUpcLQFizaE/u3fw

From: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>

The mediatek SoCs have I2C controller that handle I2C transfer.
This patch include common I2C bus driver.
This driver is compatible with I2C controller on mt65xx/mt81xx.

Signed-off-by: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Signed-off-by: Liguo Zhang <liguo.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Signed-off-by: Eddie Huang <eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/i2c/busses/Kconfig      |   9 +
 drivers/i2c/busses/Makefile     |   1 +
 drivers/i2c/busses/i2c-mt65xx.c | 700 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 710 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 2255af2..14c7266 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -620,6 +620,15 @@ config I2C_MPC
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
 
+config I2C_MT65XX
+	tristate "MediaTek I2C adapter"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  This selects the MediaTek(R) Integrated Inter Circuit bus driver
+	  for MT65xx and MT81xx.
+	  If you want to use MediaTek(R) I2C interface, say Y or M here.
+	  If unsure, say N.
+
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
 	depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index cdf941d..abbf422 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_JZ4780)	+= i2c-jz4780.o
 obj-$(CONFIG_I2C_KEMPLD)	+= i2c-kempld.o
 obj-$(CONFIG_I2C_MESON)		+= i2c-meson.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
+obj-$(CONFIG_I2C_MT65XX)	+= i2c-mt65xx.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
new file mode 100644
index 0000000..faecf7e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Xudong.chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+
+#define I2C_HS_NACKERR			(1 << 2)
+#define I2C_ACKERR			(1 << 1)
+#define I2C_TRANSAC_COMP		(1 << 0)
+#define I2C_TRANSAC_START		(1 << 0)
+#define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
+#define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
+#define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
+#define I2C_TIMING_DATA_READ_MASK	(0x7 << 12)
+#define I2C_DCM_DISABLE			0x0000
+#define I2C_IO_CONFIG_OPEN_DRAIN	0x0003
+#define I2C_IO_CONFIG_PUSH_PULL		0x0000
+#define I2C_SOFT_RST			0x0001
+#define I2C_FIFO_ADDR_CLR		0x0001
+#define I2C_DELAY_LEN			0x0002
+#define I2C_ST_START_CON		0x8001
+#define I2C_FS_START_CON		0x1800
+#define I2C_TIME_CLR_VALUE		0x0000
+#define I2C_TIME_DEFAULT_VALUE		0x0003
+#define I2C_FS_TIME_INIT_VALUE		0x1303
+#define I2C_WRRD_TRANAC_VALUE		0x0002
+#define I2C_RD_TRANAC_VALUE		0x0001
+
+#define I2C_DMA_CON_TX			0x0000
+#define I2C_DMA_CON_RX			0x0001
+#define I2C_DMA_START_EN		0x0001
+#define I2C_DMA_INT_FLAG_NONE		0x0000
+#define I2C_DMA_CLR_FLAG		0x0000
+
+#define I2C_DEFAUT_SPEED		100000	/* hz */
+#define MAX_FS_MODE_SPEED		400000
+#define MAX_HS_MODE_SPEED		3400000
+#define MAX_MSG_NUM_MT6577		1
+#define MAX_DMA_TRANS_SIZE_MT6577	255
+#define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_SAMPLE_CNT_DIV		8
+#define MAX_STEP_CNT_DIV		64
+#define MAX_HS_STEP_CNT_DIV		8
+
+#define I2C_CONTROL_RS                  (0x1 << 1)
+#define I2C_CONTROL_DMA_EN              (0x1 << 2)
+#define I2C_CONTROL_CLK_EXT_EN          (0x1 << 3)
+#define I2C_CONTROL_DIR_CHANGE          (0x1 << 4)
+#define I2C_CONTROL_ACKERR_DET_EN       (0x1 << 5)
+#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
+#define I2C_CONTROL_WRAPPER             (0x1 << 0)
+
+#define I2C_DRV_NAME		"mt-i2c"
+
+enum DMA_REGS_OFFSET {
+	OFFSET_INT_FLAG = 0x0,
+	OFFSET_INT_EN = 0x04,
+	OFFSET_EN = 0x08,
+	OFFSET_CON = 0x18,
+	OFFSET_TX_MEM_ADDR = 0x1c,
+	OFFSET_RX_MEM_ADDR = 0x20,
+	OFFSET_TX_LEN = 0x24,
+	OFFSET_RX_LEN = 0x28,
+};
+
+enum i2c_trans_st_rs {
+	I2C_TRANS_STOP = 0,
+	I2C_TRANS_REPEATED_START,
+};
+
+enum mtk_trans_op {
+	I2C_MASTER_WR = 1,
+	I2C_MASTER_RD,
+	I2C_MASTER_WRRD,
+};
+
+enum I2C_REGS_OFFSET {
+	OFFSET_DATA_PORT = 0x0,
+	OFFSET_SLAVE_ADDR = 0x04,
+	OFFSET_INTR_MASK = 0x08,
+	OFFSET_INTR_STAT = 0x0c,
+	OFFSET_CONTROL = 0x10,
+	OFFSET_TRANSFER_LEN = 0x14,
+	OFFSET_TRANSAC_LEN = 0x18,
+	OFFSET_DELAY_LEN = 0x1c,
+	OFFSET_TIMING = 0x20,
+	OFFSET_START = 0x24,
+	OFFSET_EXT_CONF = 0x28,
+	OFFSET_FIFO_STAT = 0x30,
+	OFFSET_FIFO_THRESH = 0x34,
+	OFFSET_FIFO_ADDR_CLR = 0x38,
+	OFFSET_IO_CONFIG = 0x40,
+	OFFSET_RSV_DEBUG = 0x44,
+	OFFSET_HS = 0x48,
+	OFFSET_SOFTRESET = 0x50,
+	OFFSET_DCM_EN = 0x54,
+	OFFSET_PATH_DIR = 0x60,
+	OFFSET_DEBUGSTAT = 0x64,
+	OFFSET_DEBUGCTRL = 0x68,
+	OFFSET_TRANSFER_LEN_AUX = 0x6c,
+};
+
+struct mtk_i2c_data {
+	unsigned int clk_frequency;	/* bus speed in Hz */
+	unsigned int flags;
+	unsigned int clk_src_div;
+};
+
+struct mtk_i2c_compatible {
+	const struct i2c_adapter_quirks *quirks;
+	unsigned char pmic_i2c;
+	unsigned char dcm;
+};
+
+struct mtk_i2c {
+	struct i2c_adapter adap;	/* i2c host adapter */
+	struct device *dev;
+	struct completion msg_complete;
+
+	/* set in i2c probe */
+	void __iomem *base;		/* i2c base addr */
+	void __iomem *pdmabase;		/* dma base address*/
+	struct clk *clk_main;		/* main clock for i2c bus */
+	struct clk *clk_dma;		/* DMA clock for i2c via DMA */
+	struct clk *clk_pmic;		/* PMIC clock for i2c from PMIC */
+	bool have_pmic;			/* can use i2c pins from PMIC */
+	bool use_push_pull;		/* IO config push-pull mode */
+
+	u16 irq_stat;			/* interrupt status */
+	unsigned int speed_hz;		/* The speed in transfer */
+	enum mtk_trans_op op;
+	u16 timing_reg;
+	u16 high_speed_reg;
+	const struct mtk_i2c_compatible *dev_comp;
+};
+
+static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
+	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
+	.max_num_msgs = MAX_MSG_NUM_MT6577,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
+};
+
+static const struct mtk_i2c_compatible mt6577_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+};
+
+static const struct mtk_i2c_compatible mt6589_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 1,
+	.dcm = 0,
+};
+
+static const struct of_device_id mtk_i2c_of_match[] = {
+	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
+	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
+
+static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writew(value, i2c->base + offset);
+}
+
+static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
+{
+	return readw(i2c->base + offset);
+}
+
+static inline void mtk_i2c_writel_dma(u32 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writel(value, i2c->pdmabase + offset);
+}
+
+static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
+{
+	int ret;
+
+	ret = clk_prepare_enable(i2c->clk_dma);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(i2c->clk_main);
+	if (ret)
+		goto err_main;
+
+	if (i2c->have_pmic) {
+		ret = clk_prepare_enable(i2c->clk_pmic);
+		if (ret)
+			goto err_pmic;
+	}
+	return 0;
+
+err_pmic:
+	clk_disable_unprepare(i2c->clk_main);
+err_main:
+	clk_disable_unprepare(i2c->clk_dma);
+
+	return ret;
+}
+
+static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
+{
+	if (i2c->have_pmic)
+		clk_disable_unprepare(i2c->clk_pmic);
+
+	clk_disable_unprepare(i2c->clk_main);
+	clk_disable_unprepare(i2c->clk_dma);
+}
+
+static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
+{
+	u16 control_reg;
+
+	mtk_i2c_writew(I2C_SOFT_RST, i2c, OFFSET_SOFTRESET);
+	/* Set ioconfig */
+	if (i2c->use_push_pull)
+		mtk_i2c_writew(I2C_IO_CONFIG_PUSH_PULL, i2c, OFFSET_IO_CONFIG);
+	else
+		mtk_i2c_writew(I2C_IO_CONFIG_OPEN_DRAIN, i2c, OFFSET_IO_CONFIG);
+
+	if (i2c->dev_comp->dcm)
+		mtk_i2c_writew(I2C_DCM_DISABLE, i2c, OFFSET_DCM_EN);
+
+	mtk_i2c_writew(i2c->timing_reg, i2c, OFFSET_TIMING);
+	mtk_i2c_writew(i2c->high_speed_reg, i2c, OFFSET_HS);
+
+	/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
+	if (i2c->have_pmic)
+		mtk_i2c_writew(I2C_CONTROL_WRAPPER, i2c, OFFSET_PATH_DIR);
+
+	control_reg = I2C_CONTROL_ACKERR_DET_EN |
+		I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+	mtk_i2c_writew(I2C_DELAY_LEN, i2c, OFFSET_DELAY_LEN);
+}
+
+/* calculate i2c port speed */
+static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
+{
+	unsigned int khz;
+	unsigned int step_cnt;
+	unsigned int sample_cnt;
+	unsigned int sclk;
+	unsigned int hclk;
+	unsigned int max_step_cnt;
+	unsigned int sample_div = MAX_SAMPLE_CNT_DIV;
+	unsigned int step_div;
+	unsigned int min_div;
+	unsigned int best_mul;
+	unsigned int cnt_mul;
+
+	if (i2c->speed_hz > MAX_HS_MODE_SPEED)
+		return -EINVAL;
+	else if (i2c->speed_hz > MAX_FS_MODE_SPEED)
+		max_step_cnt = MAX_HS_STEP_CNT_DIV;
+	else
+		max_step_cnt = MAX_STEP_CNT_DIV;
+
+	step_div = max_step_cnt;
+	/* Find the best combination */
+	khz = i2c->speed_hz / 1000;
+	hclk = clk_src_in_hz / 1000;
+	min_div = ((hclk >> 1) + khz - 1) / khz;
+	best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
+
+	for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
+		step_cnt = (min_div + sample_cnt - 1) / sample_cnt;
+		cnt_mul = step_cnt * sample_cnt;
+		if (step_cnt > max_step_cnt)
+			continue;
+
+		if (cnt_mul < best_mul) {
+			best_mul = cnt_mul;
+			sample_div = sample_cnt;
+			step_div = step_cnt;
+			if (best_mul == min_div)
+				break;
+		}
+	}
+
+	sample_cnt = sample_div;
+	step_cnt = step_div;
+	sclk = hclk / (2 * sample_cnt * step_cnt);
+	if (sclk > khz) {
+		dev_dbg(i2c->dev, "%s mode: unsupported speed (%ldkhz)\n",
+			(i2c->speed_hz > MAX_HS_MODE_SPEED) ? "HS" : "ST/FT",
+			(long int)khz);
+		return -ENOTSUPP;
+	}
+
+	step_cnt--;
+	sample_cnt--;
+
+	if (i2c->speed_hz > MAX_FS_MODE_SPEED) {
+		/* Set the hign speed mode register */
+		i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
+		i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 12 |
+			(step_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8;
+	} else {
+		i2c->timing_reg =
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8 |
+			(step_cnt & I2C_TIMING_STEP_DIV_MASK) << 0;
+		/* Disable the high speed transaction */
+		i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+{
+	u16 addr_reg;
+	u16 control_reg;
+	dma_addr_t rpaddr = 0;
+	dma_addr_t wpaddr = 0;
+	int ret;
+
+	i2c->irq_stat = 0;
+
+	reinit_completion(&i2c->msg_complete);
+
+	control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
+			~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
+	if (i2c->speed_hz > 400000)
+		control_reg |= I2C_CONTROL_RS;
+	if (i2c->op == I2C_MASTER_WRRD)
+		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+
+	/* set start condition */
+	if (i2c->speed_hz <= 100000)
+		mtk_i2c_writew(I2C_ST_START_CON, i2c, OFFSET_EXT_CONF);
+	else
+		mtk_i2c_writew(I2C_FS_START_CON, i2c, OFFSET_EXT_CONF);
+
+	addr_reg = msgs->addr << 1;
+	if (i2c->op == I2C_MASTER_RD)
+		addr_reg |= 0x1;
+	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
+
+	/* Clear interrupt status */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
+
+	/* Enable interrupt */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_MASK);
+
+	/* Set transfer and transaction len */
+	if (i2c->op == I2C_MASTER_WRRD) {
+		mtk_i2c_writew(msgs->len | ((msgs + 1)->len) << 8,
+			i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	} else {
+		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	}
+
+	/* Prepare buffer data to start transfer */
+	if (i2c->op == I2C_MASTER_RD) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_RX, i2c, OFFSET_CON);
+		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_RX_LEN);
+	} else if (i2c->op == I2C_MASTER_WR) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_TX, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+	} else {
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		rpaddr = dma_map_single(i2c->adap.dev.parent, (msgs + 1)->buf,
+						(msgs + 1)->len,
+						DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr)) {
+			dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+						msgs->len, DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+		mtk_i2c_writel_dma((msgs + 1)->len, i2c, OFFSET_RX_LEN);
+	}
+
+	/* flush before sending start */
+	mb();
+	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
+	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	ret = wait_for_completion_timeout(&i2c->msg_complete,
+				i2c->adap.timeout);
+
+	/* Clear interrupt mask */
+	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
+
+	if (i2c->op == I2C_MASTER_WR) {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+					msgs->len, DMA_TO_DEVICE);
+	} else if (i2c->op == I2C_MASTER_RD) {
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr,
+					msgs->len, DMA_FROM_DEVICE);
+	} else {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr, msgs->len,
+					DMA_TO_DEVICE);
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr, (msgs + 1)->len,
+					DMA_FROM_DEVICE);
+	}
+
+	if (ret == 0) {
+		dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -ETIMEDOUT;
+	}
+
+	completion_done(&i2c->msg_complete);
+
+	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
+		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_transfer(struct i2c_adapter *adap,
+	struct i2c_msg msgs[], int num)
+{
+	int ret;
+	int left_num = num;
+	struct mtk_i2c *i2c = i2c_get_adapdata(adap);
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret)
+		return ret;
+
+	if (msgs->buf == NULL) {
+		dev_dbg(i2c->dev, "data buffer is NULL.\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	if (msgs->flags & I2C_M_RD)
+		i2c->op = I2C_MASTER_RD;
+	else
+		i2c->op = I2C_MASTER_WR;
+
+	if (num > 1) {
+		/* combined two messages into one transaction */
+		i2c->op = I2C_MASTER_WRRD;
+		left_num--;
+	}
+
+	/* always use DMA mode. */
+	ret = mtk_i2c_do_transfer(i2c, msgs);
+	if (ret < 0)
+		goto err_exit;
+
+	/* the return value is number of executed messages */
+	ret = num;
+
+err_exit:
+	mtk_i2c_clock_disable(i2c);
+	return ret;
+}
+
+static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
+{
+	struct mtk_i2c *i2c = dev_id;
+
+	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+
+	complete(&i2c->msg_complete);
+
+	return IRQ_HANDLED;
+}
+
+static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm mtk_i2c_algorithm = {
+	.master_xfer = mtk_i2c_transfer,
+	.functionality = mtk_i2c_functionality,
+};
+
+static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
+	unsigned int *clk_src_div)
+{
+	int ret;
+
+	ret = of_property_read_u32(np, "clock-frequency", &i2c->speed_hz);
+	if (ret < 0)
+		i2c->speed_hz = I2C_DEFAUT_SPEED;
+
+	ret = of_property_read_u32(np, "clock-div", clk_src_div);
+	if (ret < 0)
+		return ret;
+
+	if (*clk_src_div == 0)
+		return -EINVAL;
+
+	i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
+	i2c->use_push_pull =
+		of_property_read_bool(np, "mediatek,use-push-pull");
+
+	return 0;
+}
+
+static int mtk_i2c_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+	int ret = 0;
+	struct mtk_i2c *i2c;
+	struct clk *clk;
+	unsigned int clk_src_in_hz;
+	unsigned int clk_src_div;
+	struct resource *res;
+	int irq;
+
+	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+	if (i2c == NULL)
+		return -ENOMEM;
+
+	ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div);
+	if (ret)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i2c->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->base))
+		return PTR_ERR(i2c->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->pdmabase))
+		return PTR_ERR(i2c->pdmabase);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return irq;
+
+	init_completion(&i2c->msg_complete);
+
+	of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	i2c->dev_comp = of_id->data;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
+	i2c->dev = &i2c->adap.dev;
+	i2c->adap.dev.parent = &pdev->dev;
+	i2c->adap.owner = THIS_MODULE;
+	i2c->adap.algo = &mtk_i2c_algorithm;
+	i2c->adap.quirks = i2c->dev_comp->quirks;
+	i2c->adap.timeout = 2 * HZ;
+	i2c->adap.retries = 1;
+
+	if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
+		return -EINVAL;
+
+	i2c->clk_main = devm_clk_get(&pdev->dev, "main");
+	if (IS_ERR(i2c->clk_main)) {
+		dev_err(&pdev->dev, "cannot get main clock\n");
+		return PTR_ERR(i2c->clk_main);
+	}
+
+	i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
+	if (IS_ERR(i2c->clk_dma)) {
+		dev_err(&pdev->dev, "cannot get dma clock\n");
+		return PTR_ERR(i2c->clk_dma);
+	}
+
+	clk = i2c->clk_main;
+	if (i2c->have_pmic) {
+		i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
+		if (IS_ERR(i2c->clk_pmic)) {
+			dev_err(&pdev->dev, "cannot get pmic clock\n");
+			return PTR_ERR(i2c->clk_pmic);
+		}
+		clk = i2c->clk_pmic;
+	}
+	clk_src_in_hz = clk_get_rate(clk) / clk_src_div;
+
+	dev_dbg(&pdev->dev, "clock source %p,clock src frequency %d\n",
+		i2c->clk_main, clk_src_in_hz);
+	strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
+
+	ret = mtk_i2c_set_speed(i2c, clk_src_in_hz);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set the speed.\n");
+		return -EINVAL;
+	}
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret) {
+		dev_err(&pdev->dev, "clock enable failed!\n");
+		return ret;
+	}
+	mtk_i2c_init_hw(i2c);
+	mtk_i2c_clock_disable(i2c);
+
+	ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
+		IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Request I2C IRQ %d fail\n", irq);
+		return ret;
+	}
+
+	i2c_set_adapdata(&i2c->adap, i2c);
+	ret = i2c_add_adapter(&i2c->adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, i2c);
+
+	return 0;
+}
+
+static int mtk_i2c_remove(struct platform_device *pdev)
+{
+	struct mtk_i2c *i2c = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&i2c->adap);
+
+	return 0;
+}
+
+static struct platform_driver mtk_i2c_driver = {
+	.probe = mtk_i2c_probe,
+	.remove = mtk_i2c_remove,
+	.driver = {
+		.name = I2C_DRV_NAME,
+		.of_match_table = of_match_ptr(mtk_i2c_of_match),
+	},
+};
+
+module_platform_driver(mtk_i2c_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MediaTek I2C Bus Driver");
+MODULE_AUTHOR("Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>");
-- 
1.8.1.1.dirty

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xudong Chen <xudong.chen@mediatek.com>

The mediatek SoCs have I2C controller that handle I2C transfer.
This patch include common I2C bus driver.
This driver is compatible with I2C controller on mt65xx/mt81xx.

Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
---
 drivers/i2c/busses/Kconfig      |   9 +
 drivers/i2c/busses/Makefile     |   1 +
 drivers/i2c/busses/i2c-mt65xx.c | 700 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 710 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 2255af2..14c7266 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -620,6 +620,15 @@ config I2C_MPC
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
 
+config I2C_MT65XX
+	tristate "MediaTek I2C adapter"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	help
+	  This selects the MediaTek(R) Integrated Inter Circuit bus driver
+	  for MT65xx and MT81xx.
+	  If you want to use MediaTek(R) I2C interface, say Y or M here.
+	  If unsure, say N.
+
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
 	depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index cdf941d..abbf422 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_JZ4780)	+= i2c-jz4780.o
 obj-$(CONFIG_I2C_KEMPLD)	+= i2c-kempld.o
 obj-$(CONFIG_I2C_MESON)		+= i2c-meson.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
+obj-$(CONFIG_I2C_MT65XX)	+= i2c-mt65xx.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
new file mode 100644
index 0000000..faecf7e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Xudong.chen <xudong.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+
+#define I2C_HS_NACKERR			(1 << 2)
+#define I2C_ACKERR			(1 << 1)
+#define I2C_TRANSAC_COMP		(1 << 0)
+#define I2C_TRANSAC_START		(1 << 0)
+#define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
+#define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
+#define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
+#define I2C_TIMING_DATA_READ_MASK	(0x7 << 12)
+#define I2C_DCM_DISABLE			0x0000
+#define I2C_IO_CONFIG_OPEN_DRAIN	0x0003
+#define I2C_IO_CONFIG_PUSH_PULL		0x0000
+#define I2C_SOFT_RST			0x0001
+#define I2C_FIFO_ADDR_CLR		0x0001
+#define I2C_DELAY_LEN			0x0002
+#define I2C_ST_START_CON		0x8001
+#define I2C_FS_START_CON		0x1800
+#define I2C_TIME_CLR_VALUE		0x0000
+#define I2C_TIME_DEFAULT_VALUE		0x0003
+#define I2C_FS_TIME_INIT_VALUE		0x1303
+#define I2C_WRRD_TRANAC_VALUE		0x0002
+#define I2C_RD_TRANAC_VALUE		0x0001
+
+#define I2C_DMA_CON_TX			0x0000
+#define I2C_DMA_CON_RX			0x0001
+#define I2C_DMA_START_EN		0x0001
+#define I2C_DMA_INT_FLAG_NONE		0x0000
+#define I2C_DMA_CLR_FLAG		0x0000
+
+#define I2C_DEFAUT_SPEED		100000	/* hz */
+#define MAX_FS_MODE_SPEED		400000
+#define MAX_HS_MODE_SPEED		3400000
+#define MAX_MSG_NUM_MT6577		1
+#define MAX_DMA_TRANS_SIZE_MT6577	255
+#define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_SAMPLE_CNT_DIV		8
+#define MAX_STEP_CNT_DIV		64
+#define MAX_HS_STEP_CNT_DIV		8
+
+#define I2C_CONTROL_RS                  (0x1 << 1)
+#define I2C_CONTROL_DMA_EN              (0x1 << 2)
+#define I2C_CONTROL_CLK_EXT_EN          (0x1 << 3)
+#define I2C_CONTROL_DIR_CHANGE          (0x1 << 4)
+#define I2C_CONTROL_ACKERR_DET_EN       (0x1 << 5)
+#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
+#define I2C_CONTROL_WRAPPER             (0x1 << 0)
+
+#define I2C_DRV_NAME		"mt-i2c"
+
+enum DMA_REGS_OFFSET {
+	OFFSET_INT_FLAG = 0x0,
+	OFFSET_INT_EN = 0x04,
+	OFFSET_EN = 0x08,
+	OFFSET_CON = 0x18,
+	OFFSET_TX_MEM_ADDR = 0x1c,
+	OFFSET_RX_MEM_ADDR = 0x20,
+	OFFSET_TX_LEN = 0x24,
+	OFFSET_RX_LEN = 0x28,
+};
+
+enum i2c_trans_st_rs {
+	I2C_TRANS_STOP = 0,
+	I2C_TRANS_REPEATED_START,
+};
+
+enum mtk_trans_op {
+	I2C_MASTER_WR = 1,
+	I2C_MASTER_RD,
+	I2C_MASTER_WRRD,
+};
+
+enum I2C_REGS_OFFSET {
+	OFFSET_DATA_PORT = 0x0,
+	OFFSET_SLAVE_ADDR = 0x04,
+	OFFSET_INTR_MASK = 0x08,
+	OFFSET_INTR_STAT = 0x0c,
+	OFFSET_CONTROL = 0x10,
+	OFFSET_TRANSFER_LEN = 0x14,
+	OFFSET_TRANSAC_LEN = 0x18,
+	OFFSET_DELAY_LEN = 0x1c,
+	OFFSET_TIMING = 0x20,
+	OFFSET_START = 0x24,
+	OFFSET_EXT_CONF = 0x28,
+	OFFSET_FIFO_STAT = 0x30,
+	OFFSET_FIFO_THRESH = 0x34,
+	OFFSET_FIFO_ADDR_CLR = 0x38,
+	OFFSET_IO_CONFIG = 0x40,
+	OFFSET_RSV_DEBUG = 0x44,
+	OFFSET_HS = 0x48,
+	OFFSET_SOFTRESET = 0x50,
+	OFFSET_DCM_EN = 0x54,
+	OFFSET_PATH_DIR = 0x60,
+	OFFSET_DEBUGSTAT = 0x64,
+	OFFSET_DEBUGCTRL = 0x68,
+	OFFSET_TRANSFER_LEN_AUX = 0x6c,
+};
+
+struct mtk_i2c_data {
+	unsigned int clk_frequency;	/* bus speed in Hz */
+	unsigned int flags;
+	unsigned int clk_src_div;
+};
+
+struct mtk_i2c_compatible {
+	const struct i2c_adapter_quirks *quirks;
+	unsigned char pmic_i2c;
+	unsigned char dcm;
+};
+
+struct mtk_i2c {
+	struct i2c_adapter adap;	/* i2c host adapter */
+	struct device *dev;
+	struct completion msg_complete;
+
+	/* set in i2c probe */
+	void __iomem *base;		/* i2c base addr */
+	void __iomem *pdmabase;		/* dma base address*/
+	struct clk *clk_main;		/* main clock for i2c bus */
+	struct clk *clk_dma;		/* DMA clock for i2c via DMA */
+	struct clk *clk_pmic;		/* PMIC clock for i2c from PMIC */
+	bool have_pmic;			/* can use i2c pins from PMIC */
+	bool use_push_pull;		/* IO config push-pull mode */
+
+	u16 irq_stat;			/* interrupt status */
+	unsigned int speed_hz;		/* The speed in transfer */
+	enum mtk_trans_op op;
+	u16 timing_reg;
+	u16 high_speed_reg;
+	const struct mtk_i2c_compatible *dev_comp;
+};
+
+static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
+	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
+	.max_num_msgs = MAX_MSG_NUM_MT6577,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
+};
+
+static const struct mtk_i2c_compatible mt6577_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+};
+
+static const struct mtk_i2c_compatible mt6589_compat = {
+	.quirks = &mt6577_i2c_quirks,
+	.pmic_i2c = 1,
+	.dcm = 0,
+};
+
+static const struct of_device_id mtk_i2c_of_match[] = {
+	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
+	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
+
+static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writew(value, i2c->base + offset);
+}
+
+static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
+{
+	return readw(i2c->base + offset);
+}
+
+static inline void mtk_i2c_writel_dma(u32 value, struct mtk_i2c *i2c, u8 offset)
+{
+	writel(value, i2c->pdmabase + offset);
+}
+
+static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
+{
+	int ret;
+
+	ret = clk_prepare_enable(i2c->clk_dma);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(i2c->clk_main);
+	if (ret)
+		goto err_main;
+
+	if (i2c->have_pmic) {
+		ret = clk_prepare_enable(i2c->clk_pmic);
+		if (ret)
+			goto err_pmic;
+	}
+	return 0;
+
+err_pmic:
+	clk_disable_unprepare(i2c->clk_main);
+err_main:
+	clk_disable_unprepare(i2c->clk_dma);
+
+	return ret;
+}
+
+static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
+{
+	if (i2c->have_pmic)
+		clk_disable_unprepare(i2c->clk_pmic);
+
+	clk_disable_unprepare(i2c->clk_main);
+	clk_disable_unprepare(i2c->clk_dma);
+}
+
+static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
+{
+	u16 control_reg;
+
+	mtk_i2c_writew(I2C_SOFT_RST, i2c, OFFSET_SOFTRESET);
+	/* Set ioconfig */
+	if (i2c->use_push_pull)
+		mtk_i2c_writew(I2C_IO_CONFIG_PUSH_PULL, i2c, OFFSET_IO_CONFIG);
+	else
+		mtk_i2c_writew(I2C_IO_CONFIG_OPEN_DRAIN, i2c, OFFSET_IO_CONFIG);
+
+	if (i2c->dev_comp->dcm)
+		mtk_i2c_writew(I2C_DCM_DISABLE, i2c, OFFSET_DCM_EN);
+
+	mtk_i2c_writew(i2c->timing_reg, i2c, OFFSET_TIMING);
+	mtk_i2c_writew(i2c->high_speed_reg, i2c, OFFSET_HS);
+
+	/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
+	if (i2c->have_pmic)
+		mtk_i2c_writew(I2C_CONTROL_WRAPPER, i2c, OFFSET_PATH_DIR);
+
+	control_reg = I2C_CONTROL_ACKERR_DET_EN |
+		I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+	mtk_i2c_writew(I2C_DELAY_LEN, i2c, OFFSET_DELAY_LEN);
+}
+
+/* calculate i2c port speed */
+static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
+{
+	unsigned int khz;
+	unsigned int step_cnt;
+	unsigned int sample_cnt;
+	unsigned int sclk;
+	unsigned int hclk;
+	unsigned int max_step_cnt;
+	unsigned int sample_div = MAX_SAMPLE_CNT_DIV;
+	unsigned int step_div;
+	unsigned int min_div;
+	unsigned int best_mul;
+	unsigned int cnt_mul;
+
+	if (i2c->speed_hz > MAX_HS_MODE_SPEED)
+		return -EINVAL;
+	else if (i2c->speed_hz > MAX_FS_MODE_SPEED)
+		max_step_cnt = MAX_HS_STEP_CNT_DIV;
+	else
+		max_step_cnt = MAX_STEP_CNT_DIV;
+
+	step_div = max_step_cnt;
+	/* Find the best combination */
+	khz = i2c->speed_hz / 1000;
+	hclk = clk_src_in_hz / 1000;
+	min_div = ((hclk >> 1) + khz - 1) / khz;
+	best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
+
+	for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
+		step_cnt = (min_div + sample_cnt - 1) / sample_cnt;
+		cnt_mul = step_cnt * sample_cnt;
+		if (step_cnt > max_step_cnt)
+			continue;
+
+		if (cnt_mul < best_mul) {
+			best_mul = cnt_mul;
+			sample_div = sample_cnt;
+			step_div = step_cnt;
+			if (best_mul == min_div)
+				break;
+		}
+	}
+
+	sample_cnt = sample_div;
+	step_cnt = step_div;
+	sclk = hclk / (2 * sample_cnt * step_cnt);
+	if (sclk > khz) {
+		dev_dbg(i2c->dev, "%s mode: unsupported speed (%ldkhz)\n",
+			(i2c->speed_hz > MAX_HS_MODE_SPEED) ? "HS" : "ST/FT",
+			(long int)khz);
+		return -ENOTSUPP;
+	}
+
+	step_cnt--;
+	sample_cnt--;
+
+	if (i2c->speed_hz > MAX_FS_MODE_SPEED) {
+		/* Set the hign speed mode register */
+		i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
+		i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 12 |
+			(step_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8;
+	} else {
+		i2c->timing_reg =
+			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8 |
+			(step_cnt & I2C_TIMING_STEP_DIV_MASK) << 0;
+		/* Disable the high speed transaction */
+		i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+{
+	u16 addr_reg;
+	u16 control_reg;
+	dma_addr_t rpaddr = 0;
+	dma_addr_t wpaddr = 0;
+	int ret;
+
+	i2c->irq_stat = 0;
+
+	reinit_completion(&i2c->msg_complete);
+
+	control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
+			~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
+	if (i2c->speed_hz > 400000)
+		control_reg |= I2C_CONTROL_RS;
+	if (i2c->op == I2C_MASTER_WRRD)
+		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+
+	/* set start condition */
+	if (i2c->speed_hz <= 100000)
+		mtk_i2c_writew(I2C_ST_START_CON, i2c, OFFSET_EXT_CONF);
+	else
+		mtk_i2c_writew(I2C_FS_START_CON, i2c, OFFSET_EXT_CONF);
+
+	addr_reg = msgs->addr << 1;
+	if (i2c->op == I2C_MASTER_RD)
+		addr_reg |= 0x1;
+	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
+
+	/* Clear interrupt status */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
+
+	/* Enable interrupt */
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+		i2c, OFFSET_INTR_MASK);
+
+	/* Set transfer and transaction len */
+	if (i2c->op == I2C_MASTER_WRRD) {
+		mtk_i2c_writew(msgs->len | ((msgs + 1)->len) << 8,
+			i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	} else {
+		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
+		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+	}
+
+	/* Prepare buffer data to start transfer */
+	if (i2c->op == I2C_MASTER_RD) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_RX, i2c, OFFSET_CON);
+		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_RX_LEN);
+	} else if (i2c->op == I2C_MASTER_WR) {
+		mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CON_TX, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+	} else {
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_INT_FLAG);
+		mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_CON);
+		wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
+						msgs->len, DMA_TO_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
+			return -ENOMEM;
+		rpaddr = dma_map_single(i2c->adap.dev.parent, (msgs + 1)->buf,
+						(msgs + 1)->len,
+						DMA_FROM_DEVICE);
+		if (dma_mapping_error(i2c->adap.dev.parent, rpaddr)) {
+			dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+						msgs->len, DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+		mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
+		mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
+		mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
+		mtk_i2c_writel_dma((msgs + 1)->len, i2c, OFFSET_RX_LEN);
+	}
+
+	/* flush before sending start */
+	mb();
+	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
+	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	ret = wait_for_completion_timeout(&i2c->msg_complete,
+				i2c->adap.timeout);
+
+	/* Clear interrupt mask */
+	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
+
+	if (i2c->op == I2C_MASTER_WR) {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr,
+					msgs->len, DMA_TO_DEVICE);
+	} else if (i2c->op == I2C_MASTER_RD) {
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr,
+					msgs->len, DMA_FROM_DEVICE);
+	} else {
+		dma_unmap_single(i2c->adap.dev.parent, wpaddr, msgs->len,
+					DMA_TO_DEVICE);
+		dma_unmap_single(i2c->adap.dev.parent, rpaddr, (msgs + 1)->len,
+					DMA_FROM_DEVICE);
+	}
+
+	if (ret == 0) {
+		dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -ETIMEDOUT;
+	}
+
+	completion_done(&i2c->msg_complete);
+
+	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
+		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
+		mtk_i2c_init_hw(i2c);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int mtk_i2c_transfer(struct i2c_adapter *adap,
+	struct i2c_msg msgs[], int num)
+{
+	int ret;
+	int left_num = num;
+	struct mtk_i2c *i2c = i2c_get_adapdata(adap);
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret)
+		return ret;
+
+	if (msgs->buf == NULL) {
+		dev_dbg(i2c->dev, "data buffer is NULL.\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	if (msgs->flags & I2C_M_RD)
+		i2c->op = I2C_MASTER_RD;
+	else
+		i2c->op = I2C_MASTER_WR;
+
+	if (num > 1) {
+		/* combined two messages into one transaction */
+		i2c->op = I2C_MASTER_WRRD;
+		left_num--;
+	}
+
+	/* always use DMA mode. */
+	ret = mtk_i2c_do_transfer(i2c, msgs);
+	if (ret < 0)
+		goto err_exit;
+
+	/* the return value is number of executed messages */
+	ret = num;
+
+err_exit:
+	mtk_i2c_clock_disable(i2c);
+	return ret;
+}
+
+static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
+{
+	struct mtk_i2c *i2c = dev_id;
+
+	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+
+	complete(&i2c->msg_complete);
+
+	return IRQ_HANDLED;
+}
+
+static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm mtk_i2c_algorithm = {
+	.master_xfer = mtk_i2c_transfer,
+	.functionality = mtk_i2c_functionality,
+};
+
+static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
+	unsigned int *clk_src_div)
+{
+	int ret;
+
+	ret = of_property_read_u32(np, "clock-frequency", &i2c->speed_hz);
+	if (ret < 0)
+		i2c->speed_hz = I2C_DEFAUT_SPEED;
+
+	ret = of_property_read_u32(np, "clock-div", clk_src_div);
+	if (ret < 0)
+		return ret;
+
+	if (*clk_src_div == 0)
+		return -EINVAL;
+
+	i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
+	i2c->use_push_pull =
+		of_property_read_bool(np, "mediatek,use-push-pull");
+
+	return 0;
+}
+
+static int mtk_i2c_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+	int ret = 0;
+	struct mtk_i2c *i2c;
+	struct clk *clk;
+	unsigned int clk_src_in_hz;
+	unsigned int clk_src_div;
+	struct resource *res;
+	int irq;
+
+	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+	if (i2c == NULL)
+		return -ENOMEM;
+
+	ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div);
+	if (ret)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i2c->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->base))
+		return PTR_ERR(i2c->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c->pdmabase))
+		return PTR_ERR(i2c->pdmabase);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return irq;
+
+	init_completion(&i2c->msg_complete);
+
+	of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	i2c->dev_comp = of_id->data;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
+	i2c->dev = &i2c->adap.dev;
+	i2c->adap.dev.parent = &pdev->dev;
+	i2c->adap.owner = THIS_MODULE;
+	i2c->adap.algo = &mtk_i2c_algorithm;
+	i2c->adap.quirks = i2c->dev_comp->quirks;
+	i2c->adap.timeout = 2 * HZ;
+	i2c->adap.retries = 1;
+
+	if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
+		return -EINVAL;
+
+	i2c->clk_main = devm_clk_get(&pdev->dev, "main");
+	if (IS_ERR(i2c->clk_main)) {
+		dev_err(&pdev->dev, "cannot get main clock\n");
+		return PTR_ERR(i2c->clk_main);
+	}
+
+	i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
+	if (IS_ERR(i2c->clk_dma)) {
+		dev_err(&pdev->dev, "cannot get dma clock\n");
+		return PTR_ERR(i2c->clk_dma);
+	}
+
+	clk = i2c->clk_main;
+	if (i2c->have_pmic) {
+		i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
+		if (IS_ERR(i2c->clk_pmic)) {
+			dev_err(&pdev->dev, "cannot get pmic clock\n");
+			return PTR_ERR(i2c->clk_pmic);
+		}
+		clk = i2c->clk_pmic;
+	}
+	clk_src_in_hz = clk_get_rate(clk) / clk_src_div;
+
+	dev_dbg(&pdev->dev, "clock source %p,clock src frequency %d\n",
+		i2c->clk_main, clk_src_in_hz);
+	strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
+
+	ret = mtk_i2c_set_speed(i2c, clk_src_in_hz);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set the speed.\n");
+		return -EINVAL;
+	}
+
+	ret = mtk_i2c_clock_enable(i2c);
+	if (ret) {
+		dev_err(&pdev->dev, "clock enable failed!\n");
+		return ret;
+	}
+	mtk_i2c_init_hw(i2c);
+	mtk_i2c_clock_disable(i2c);
+
+	ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
+		IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Request I2C IRQ %d fail\n", irq);
+		return ret;
+	}
+
+	i2c_set_adapdata(&i2c->adap, i2c);
+	ret = i2c_add_adapter(&i2c->adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, i2c);
+
+	return 0;
+}
+
+static int mtk_i2c_remove(struct platform_device *pdev)
+{
+	struct mtk_i2c *i2c = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&i2c->adap);
+
+	return 0;
+}
+
+static struct platform_driver mtk_i2c_driver = {
+	.probe = mtk_i2c_probe,
+	.remove = mtk_i2c_remove,
+	.driver = {
+		.name = I2C_DRV_NAME,
+		.of_match_table = of_match_ptr(mtk_i2c_of_match),
+	},
+};
+
+module_platform_driver(mtk_i2c_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MediaTek I2C Bus Driver");
+MODULE_AUTHOR("Xudong Chen <xudong.chen@mediatek.com>");
-- 
1.8.1.1.dirty

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 3/3] I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: srv_heupstream, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Matthias Brugger, Jean Delvare,
	David Box, Doug Anderson, Zhangfei Gao, Max Schwarz,
	Boris BREZILLON, Anders Berg, Neelesh Gupta, Lee Jones,
	Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan, Beniamino Galvani,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, Eddie Huang

Add mediatek MT8173 I2C controller driver. Compare to I2C controller
of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
also increase message size to 64kb.

Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
---
 drivers/i2c/busses/i2c-mt65xx.c | 104 +++++++++++++++++++++++++++++-----------
 1 file changed, 76 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index faecf7e..c501421 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -33,10 +33,13 @@
 #include <linux/clk.h>
 #include <linux/completion.h>
 
+#define I2C_RS_TRANSFER			(1 << 4)
 #define I2C_HS_NACKERR			(1 << 2)
 #define I2C_ACKERR			(1 << 1)
 #define I2C_TRANSAC_COMP		(1 << 0)
 #define I2C_TRANSAC_START		(1 << 0)
+#define I2C_RS_MUL_CNFG			(1 << 15)
+#define I2C_RS_MUL_TRIG			(1 << 14)
 #define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
 #define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
 #define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
@@ -67,6 +70,9 @@
 #define MAX_MSG_NUM_MT6577		1
 #define MAX_DMA_TRANS_SIZE_MT6577	255
 #define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_MSG_NUM_MT8173		65535
+#define MAX_DMA_TRANS_SIZE_MT8173	65535
+#define MAX_WRRD_TRANS_SIZE_MT8173	65535
 #define MAX_SAMPLE_CNT_DIV		8
 #define MAX_STEP_CNT_DIV		64
 #define MAX_HS_STEP_CNT_DIV		8
@@ -139,6 +145,7 @@ struct mtk_i2c_compatible {
 	const struct i2c_adapter_quirks *quirks;
 	unsigned char pmic_i2c;
 	unsigned char dcm;
+	unsigned char auto_restart;
 };
 
 struct mtk_i2c {
@@ -172,21 +179,39 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
 	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
 };
 
+static const struct i2c_adapter_quirks mt8173_i2c_quirks = {
+	.max_num_msgs = MAX_MSG_NUM_MT8173,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT8173,
+};
+
 static const struct mtk_i2c_compatible mt6577_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 0,
 	.dcm = 1,
+	.auto_restart = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 1,
 	.dcm = 0,
+	.auto_restart = 0,
+};
+
+static const struct mtk_i2c_compatible mt8173_compat = {
+	.quirks = &mt8173_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+	.auto_restart = 1,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
 	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
 	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{ .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
 	{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
@@ -343,9 +368,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
 	return 0;
 }
 
-static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
+					int num, int left_num)
 {
 	u16 addr_reg;
+	u16 start_reg;
 	u16 control_reg;
 	dma_addr_t rpaddr = 0;
 	dma_addr_t wpaddr = 0;
@@ -361,6 +388,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		control_reg |= I2C_CONTROL_RS;
 	if (i2c->op == I2C_MASTER_WRRD)
 		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	if (left_num >= 1)
+		control_reg |= I2C_CONTROL_RS;
 	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
 
 	/* set start condition */
@@ -375,13 +404,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
 
 	/* Clear interrupt status */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
 
 	/* Enable interrupt */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_MASK);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_MASK);
 
 	/* Set transfer and transaction len */
 	if (i2c->op == I2C_MASTER_WRRD) {
@@ -390,7 +419,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
 	} else {
 		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
-		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+		mtk_i2c_writew(num, i2c, OFFSET_TRANSAC_LEN);
 	}
 
 	/* Prepare buffer data to start transfer */
@@ -436,13 +465,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	/* flush before sending start */
 	mb();
 	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
-	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	if (!i2c->dev_comp->auto_restart) {
+		start_reg = I2C_TRANSAC_START;
+	} else {
+		if (left_num >= 1)
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_CNFG
+					| I2C_RS_MUL_TRIG;
+		else
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
+	}
+	mtk_i2c_writew(start_reg, i2c, OFFSET_START);
 
 	ret = wait_for_completion_timeout(&i2c->msg_complete,
 				i2c->adap.timeout);
 
 	/* Clear interrupt mask */
-	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(~(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
 
 	if (i2c->op == I2C_MASTER_WR) {
@@ -472,6 +511,10 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		return -EREMOTEIO;
 	}
 
+	if (i2c->irq_stat & I2C_RS_TRANSFER)
+		dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
+				msgs->addr);
+
 	return 0;
 }
 
@@ -486,28 +529,33 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
 	if (ret)
 		return ret;
 
-	if (msgs->buf == NULL) {
-		dev_dbg(i2c->dev, "data buffer is NULL.\n");
-		ret = -EINVAL;
-		goto err_exit;
-	}
-
-	if (msgs->flags & I2C_M_RD)
-		i2c->op = I2C_MASTER_RD;
-	else
-		i2c->op = I2C_MASTER_WR;
+	while (left_num--) {
+		if (msgs->buf == NULL) {
+			dev_dbg(i2c->dev, "data buffer is NULL.\n");
+			ret = -EINVAL;
+			goto err_exit;
+		}
 
-	if (num > 1) {
-		/* combined two messages into one transaction */
-		i2c->op = I2C_MASTER_WRRD;
-		left_num--;
-	}
+		if (msgs->flags & I2C_M_RD)
+			i2c->op = I2C_MASTER_RD;
+		else
+			i2c->op = I2C_MASTER_WR;
+
+		if (!i2c->dev_comp->auto_restart) {
+			if (num > 1) {
+				/* combined two messages into one transaction */
+				i2c->op = I2C_MASTER_WRRD;
+				left_num--;
+			}
+		}
 
-	/* always use DMA mode. */
-	ret = mtk_i2c_do_transfer(i2c, msgs);
-	if (ret < 0)
-		goto err_exit;
+		/* always use DMA mode. */
+		ret = mtk_i2c_do_transfer(i2c, msgs, num, left_num);
+		if (ret < 0)
+			goto err_exit;
 
+		msgs++;
+	}
 	/* the return value is number of executed messages */
 	ret = num;
 
@@ -521,7 +569,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
 	struct mtk_i2c *i2c = dev_id;
 
 	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 
 	complete(&i2c->msg_complete);
-- 
1.8.1.1.dirty


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 3/3] I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: Wolfram Sang, Sascha Hauer
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani, Xudong Chen, Liguo Zhang

Add mediatek MT8173 I2C controller driver. Compare to I2C controller
of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
also increase message size to 64kb.

Signed-off-by: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Signed-off-by: Liguo Zhang <liguo.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Signed-off-by: Eddie Huang <eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/i2c/busses/i2c-mt65xx.c | 104 +++++++++++++++++++++++++++++-----------
 1 file changed, 76 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index faecf7e..c501421 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -33,10 +33,13 @@
 #include <linux/clk.h>
 #include <linux/completion.h>
 
+#define I2C_RS_TRANSFER			(1 << 4)
 #define I2C_HS_NACKERR			(1 << 2)
 #define I2C_ACKERR			(1 << 1)
 #define I2C_TRANSAC_COMP		(1 << 0)
 #define I2C_TRANSAC_START		(1 << 0)
+#define I2C_RS_MUL_CNFG			(1 << 15)
+#define I2C_RS_MUL_TRIG			(1 << 14)
 #define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
 #define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
 #define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
@@ -67,6 +70,9 @@
 #define MAX_MSG_NUM_MT6577		1
 #define MAX_DMA_TRANS_SIZE_MT6577	255
 #define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_MSG_NUM_MT8173		65535
+#define MAX_DMA_TRANS_SIZE_MT8173	65535
+#define MAX_WRRD_TRANS_SIZE_MT8173	65535
 #define MAX_SAMPLE_CNT_DIV		8
 #define MAX_STEP_CNT_DIV		64
 #define MAX_HS_STEP_CNT_DIV		8
@@ -139,6 +145,7 @@ struct mtk_i2c_compatible {
 	const struct i2c_adapter_quirks *quirks;
 	unsigned char pmic_i2c;
 	unsigned char dcm;
+	unsigned char auto_restart;
 };
 
 struct mtk_i2c {
@@ -172,21 +179,39 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
 	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
 };
 
+static const struct i2c_adapter_quirks mt8173_i2c_quirks = {
+	.max_num_msgs = MAX_MSG_NUM_MT8173,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT8173,
+};
+
 static const struct mtk_i2c_compatible mt6577_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 0,
 	.dcm = 1,
+	.auto_restart = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 1,
 	.dcm = 0,
+	.auto_restart = 0,
+};
+
+static const struct mtk_i2c_compatible mt8173_compat = {
+	.quirks = &mt8173_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+	.auto_restart = 1,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
 	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
 	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{ .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
 	{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
@@ -343,9 +368,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
 	return 0;
 }
 
-static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
+					int num, int left_num)
 {
 	u16 addr_reg;
+	u16 start_reg;
 	u16 control_reg;
 	dma_addr_t rpaddr = 0;
 	dma_addr_t wpaddr = 0;
@@ -361,6 +388,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		control_reg |= I2C_CONTROL_RS;
 	if (i2c->op == I2C_MASTER_WRRD)
 		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	if (left_num >= 1)
+		control_reg |= I2C_CONTROL_RS;
 	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
 
 	/* set start condition */
@@ -375,13 +404,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
 
 	/* Clear interrupt status */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
 
 	/* Enable interrupt */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_MASK);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_MASK);
 
 	/* Set transfer and transaction len */
 	if (i2c->op == I2C_MASTER_WRRD) {
@@ -390,7 +419,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
 	} else {
 		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
-		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+		mtk_i2c_writew(num, i2c, OFFSET_TRANSAC_LEN);
 	}
 
 	/* Prepare buffer data to start transfer */
@@ -436,13 +465,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	/* flush before sending start */
 	mb();
 	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
-	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	if (!i2c->dev_comp->auto_restart) {
+		start_reg = I2C_TRANSAC_START;
+	} else {
+		if (left_num >= 1)
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_CNFG
+					| I2C_RS_MUL_TRIG;
+		else
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
+	}
+	mtk_i2c_writew(start_reg, i2c, OFFSET_START);
 
 	ret = wait_for_completion_timeout(&i2c->msg_complete,
 				i2c->adap.timeout);
 
 	/* Clear interrupt mask */
-	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(~(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
 
 	if (i2c->op == I2C_MASTER_WR) {
@@ -472,6 +511,10 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		return -EREMOTEIO;
 	}
 
+	if (i2c->irq_stat & I2C_RS_TRANSFER)
+		dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
+				msgs->addr);
+
 	return 0;
 }
 
@@ -486,28 +529,33 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
 	if (ret)
 		return ret;
 
-	if (msgs->buf == NULL) {
-		dev_dbg(i2c->dev, "data buffer is NULL.\n");
-		ret = -EINVAL;
-		goto err_exit;
-	}
-
-	if (msgs->flags & I2C_M_RD)
-		i2c->op = I2C_MASTER_RD;
-	else
-		i2c->op = I2C_MASTER_WR;
+	while (left_num--) {
+		if (msgs->buf == NULL) {
+			dev_dbg(i2c->dev, "data buffer is NULL.\n");
+			ret = -EINVAL;
+			goto err_exit;
+		}
 
-	if (num > 1) {
-		/* combined two messages into one transaction */
-		i2c->op = I2C_MASTER_WRRD;
-		left_num--;
-	}
+		if (msgs->flags & I2C_M_RD)
+			i2c->op = I2C_MASTER_RD;
+		else
+			i2c->op = I2C_MASTER_WR;
+
+		if (!i2c->dev_comp->auto_restart) {
+			if (num > 1) {
+				/* combined two messages into one transaction */
+				i2c->op = I2C_MASTER_WRRD;
+				left_num--;
+			}
+		}
 
-	/* always use DMA mode. */
-	ret = mtk_i2c_do_transfer(i2c, msgs);
-	if (ret < 0)
-		goto err_exit;
+		/* always use DMA mode. */
+		ret = mtk_i2c_do_transfer(i2c, msgs, num, left_num);
+		if (ret < 0)
+			goto err_exit;
 
+		msgs++;
+	}
 	/* the return value is number of executed messages */
 	ret = num;
 
@@ -521,7 +569,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
 	struct mtk_i2c *i2c = dev_id;
 
 	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 
 	complete(&i2c->msg_complete);
-- 
1.8.1.1.dirty

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v7 3/3] I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
@ 2015-05-06  8:37   ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-06  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

Add mediatek MT8173 I2C controller driver. Compare to I2C controller
of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
also increase message size to 64kb.

Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
---
 drivers/i2c/busses/i2c-mt65xx.c | 104 +++++++++++++++++++++++++++++-----------
 1 file changed, 76 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index faecf7e..c501421 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -33,10 +33,13 @@
 #include <linux/clk.h>
 #include <linux/completion.h>
 
+#define I2C_RS_TRANSFER			(1 << 4)
 #define I2C_HS_NACKERR			(1 << 2)
 #define I2C_ACKERR			(1 << 1)
 #define I2C_TRANSAC_COMP		(1 << 0)
 #define I2C_TRANSAC_START		(1 << 0)
+#define I2C_RS_MUL_CNFG			(1 << 15)
+#define I2C_RS_MUL_TRIG			(1 << 14)
 #define I2C_TIMING_STEP_DIV_MASK	(0x3f << 0)
 #define I2C_TIMING_SAMPLE_COUNT_MASK	(0x7 << 0)
 #define I2C_TIMING_SAMPLE_DIV_MASK	(0x7 << 8)
@@ -67,6 +70,9 @@
 #define MAX_MSG_NUM_MT6577		1
 #define MAX_DMA_TRANS_SIZE_MT6577	255
 #define MAX_WRRD_TRANS_SIZE_MT6577	31
+#define MAX_MSG_NUM_MT8173		65535
+#define MAX_DMA_TRANS_SIZE_MT8173	65535
+#define MAX_WRRD_TRANS_SIZE_MT8173	65535
 #define MAX_SAMPLE_CNT_DIV		8
 #define MAX_STEP_CNT_DIV		64
 #define MAX_HS_STEP_CNT_DIV		8
@@ -139,6 +145,7 @@ struct mtk_i2c_compatible {
 	const struct i2c_adapter_quirks *quirks;
 	unsigned char pmic_i2c;
 	unsigned char dcm;
+	unsigned char auto_restart;
 };
 
 struct mtk_i2c {
@@ -172,21 +179,39 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
 	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
 };
 
+static const struct i2c_adapter_quirks mt8173_i2c_quirks = {
+	.max_num_msgs = MAX_MSG_NUM_MT8173,
+	.max_write_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_read_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT8173,
+	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT8173,
+};
+
 static const struct mtk_i2c_compatible mt6577_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 0,
 	.dcm = 1,
+	.auto_restart = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 1,
 	.dcm = 0,
+	.auto_restart = 0,
+};
+
+static const struct mtk_i2c_compatible mt8173_compat = {
+	.quirks = &mt8173_i2c_quirks,
+	.pmic_i2c = 0,
+	.dcm = 1,
+	.auto_restart = 1,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
 	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
 	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
+	{ .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
 	{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
@@ -343,9 +368,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
 	return 0;
 }
 
-static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
+					int num, int left_num)
 {
 	u16 addr_reg;
+	u16 start_reg;
 	u16 control_reg;
 	dma_addr_t rpaddr = 0;
 	dma_addr_t wpaddr = 0;
@@ -361,6 +388,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		control_reg |= I2C_CONTROL_RS;
 	if (i2c->op == I2C_MASTER_WRRD)
 		control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
+	if (left_num >= 1)
+		control_reg |= I2C_CONTROL_RS;
 	mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
 
 	/* set start condition */
@@ -375,13 +404,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
 
 	/* Clear interrupt status */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_STAT);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 	mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
 
 	/* Enable interrupt */
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
-		i2c, OFFSET_INTR_MASK);
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_MASK);
 
 	/* Set transfer and transaction len */
 	if (i2c->op == I2C_MASTER_WRRD) {
@@ -390,7 +419,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
 	} else {
 		mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
-		mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+		mtk_i2c_writew(num, i2c, OFFSET_TRANSAC_LEN);
 	}
 
 	/* Prepare buffer data to start transfer */
@@ -436,13 +465,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 	/* flush before sending start */
 	mb();
 	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
-	mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
+
+	if (!i2c->dev_comp->auto_restart) {
+		start_reg = I2C_TRANSAC_START;
+	} else {
+		if (left_num >= 1)
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_CNFG
+					| I2C_RS_MUL_TRIG;
+		else
+			start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
+	}
+	mtk_i2c_writew(start_reg, i2c, OFFSET_START);
 
 	ret = wait_for_completion_timeout(&i2c->msg_complete,
 				i2c->adap.timeout);
 
 	/* Clear interrupt mask */
-	mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(~(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
 
 	if (i2c->op == I2C_MASTER_WR) {
@@ -472,6 +511,10 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
 		return -EREMOTEIO;
 	}
 
+	if (i2c->irq_stat & I2C_RS_TRANSFER)
+		dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
+				msgs->addr);
+
 	return 0;
 }
 
@@ -486,28 +529,33 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
 	if (ret)
 		return ret;
 
-	if (msgs->buf == NULL) {
-		dev_dbg(i2c->dev, "data buffer is NULL.\n");
-		ret = -EINVAL;
-		goto err_exit;
-	}
-
-	if (msgs->flags & I2C_M_RD)
-		i2c->op = I2C_MASTER_RD;
-	else
-		i2c->op = I2C_MASTER_WR;
+	while (left_num--) {
+		if (msgs->buf == NULL) {
+			dev_dbg(i2c->dev, "data buffer is NULL.\n");
+			ret = -EINVAL;
+			goto err_exit;
+		}
 
-	if (num > 1) {
-		/* combined two messages into one transaction */
-		i2c->op = I2C_MASTER_WRRD;
-		left_num--;
-	}
+		if (msgs->flags & I2C_M_RD)
+			i2c->op = I2C_MASTER_RD;
+		else
+			i2c->op = I2C_MASTER_WR;
+
+		if (!i2c->dev_comp->auto_restart) {
+			if (num > 1) {
+				/* combined two messages into one transaction */
+				i2c->op = I2C_MASTER_WRRD;
+				left_num--;
+			}
+		}
 
-	/* always use DMA mode. */
-	ret = mtk_i2c_do_transfer(i2c, msgs);
-	if (ret < 0)
-		goto err_exit;
+		/* always use DMA mode. */
+		ret = mtk_i2c_do_transfer(i2c, msgs, num, left_num);
+		if (ret < 0)
+			goto err_exit;
 
+		msgs++;
+	}
 	/* the return value is number of executed messages */
 	ret = num;
 
@@ -521,7 +569,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
 	struct mtk_i2c *i2c = dev_id;
 
 	i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
-	mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
+	mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
 			| I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
 
 	complete(&i2c->msg_complete);
-- 
1.8.1.1.dirty

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-07  7:39   ` Lee Jones
  0 siblings, 0 replies; 48+ messages in thread
From: Lee Jones @ 2015-05-07  7:39 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Wolfram Sang, Sascha Hauer, srv_heupstream, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Jean Delvare, David Box, Doug Anderson,
	Zhangfei Gao, Max Schwarz, Boris BREZILLON, Anders Berg,
	Neelesh Gupta, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani, Xudong Chen, Liguo Zhang, linux-i2c,
	devicetree, linux-kernel, linux-arm-kernel, linux-mediatek

On Wed, 06 May 2015, Eddie Huang wrote:

> This series is for Mediatek SoCs I2C controller common bus driver.
> 
> Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> New generation SoC like MT8173 fix following limitations:
> 
> 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> mode. WRRD can have two i2c_msg numbers.
> 
> 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> mode the Repeat Start will be issued between 2 messages.
> In this driver if 2 messages is first write then read, the driver will
> combine 2 messages using Write-Read mode so the RS will be issued between
> the 2 messages.
> 
> 3. The max transfer data length is 255 in one message. In WRRD mode, the
> max data length of second msg is 31.
> 
> MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> bit first, the operation on other registers are still the same.
> For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> "mediatek,have-pmic" property in the .dts file of each platform.
> 
> This driver is based on 4.1-rc1.
> 
> Change in v7:
> Fix mtk_i2c_of_match in wrong patch bug.
> 
> Change in v6:
> 1. Update binding document not use default clock-frequency as example.
> 2. Add mtk_i2c_compatible struct and pass hardware capabilities
>    through of_device_id
> 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
>    so just init one time.
> 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> 
> Change in v5:
> Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> Add MT8173 I2C driver.
> 
> Change in v4:
> Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> Remove check transfer size and WRRD combine code. Instead, fill quirk
> property and let i2c_check_for_quirks to do the filter.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> 
> Eddie Huang (1):
>   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> 
> Xudong Chen (2):
>   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
>   I2C: mediatek: Add driver for MediaTek I2C controller
> 
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
>  drivers/i2c/busses/Kconfig                         |   9 +
>  drivers/i2c/busses/Makefile                        |   1 +
>  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
>  4 files changed, 799 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
>  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

Again, you've sent me a patch-set that has absolutely nothing to do
with me.  Can you please stop doing that, my inbox is full enough
already!

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-07  7:39   ` Lee Jones
  0 siblings, 0 replies; 48+ messages in thread
From: Lee Jones @ 2015-05-07  7:39 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Wolfram Sang, Sascha Hauer,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan, Beniamino Galvani,
	Xudong Chen, Liguo

On Wed, 06 May 2015, Eddie Huang wrote:

> This series is for Mediatek SoCs I2C controller common bus driver.
> 
> Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> New generation SoC like MT8173 fix following limitations:
> 
> 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> mode. WRRD can have two i2c_msg numbers.
> 
> 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> mode the Repeat Start will be issued between 2 messages.
> In this driver if 2 messages is first write then read, the driver will
> combine 2 messages using Write-Read mode so the RS will be issued between
> the 2 messages.
> 
> 3. The max transfer data length is 255 in one message. In WRRD mode, the
> max data length of second msg is 31.
> 
> MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> bit first, the operation on other registers are still the same.
> For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> "mediatek,have-pmic" property in the .dts file of each platform.
> 
> This driver is based on 4.1-rc1.
> 
> Change in v7:
> Fix mtk_i2c_of_match in wrong patch bug.
> 
> Change in v6:
> 1. Update binding document not use default clock-frequency as example.
> 2. Add mtk_i2c_compatible struct and pass hardware capabilities
>    through of_device_id
> 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
>    so just init one time.
> 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> 
> Change in v5:
> Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> Add MT8173 I2C driver.
> 
> Change in v4:
> Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> Remove check transfer size and WRRD combine code. Instead, fill quirk
> property and let i2c_check_for_quirks to do the filter.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> 
> Eddie Huang (1):
>   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> 
> Xudong Chen (2):
>   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
>   I2C: mediatek: Add driver for MediaTek I2C controller
> 
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
>  drivers/i2c/busses/Kconfig                         |   9 +
>  drivers/i2c/busses/Makefile                        |   1 +
>  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
>  4 files changed, 799 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
>  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

Again, you've sent me a patch-set that has absolutely nothing to do
with me.  Can you please stop doing that, my inbox is full enough
already!

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-07  7:39   ` Lee Jones
  0 siblings, 0 replies; 48+ messages in thread
From: Lee Jones @ 2015-05-07  7:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 06 May 2015, Eddie Huang wrote:

> This series is for Mediatek SoCs I2C controller common bus driver.
> 
> Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> New generation SoC like MT8173 fix following limitations:
> 
> 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> mode. WRRD can have two i2c_msg numbers.
> 
> 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> mode the Repeat Start will be issued between 2 messages.
> In this driver if 2 messages is first write then read, the driver will
> combine 2 messages using Write-Read mode so the RS will be issued between
> the 2 messages.
> 
> 3. The max transfer data length is 255 in one message. In WRRD mode, the
> max data length of second msg is 31.
> 
> MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> bit first, the operation on other registers are still the same.
> For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> "mediatek,have-pmic" property in the .dts file of each platform.
> 
> This driver is based on 4.1-rc1.
> 
> Change in v7:
> Fix mtk_i2c_of_match in wrong patch bug.
> 
> Change in v6:
> 1. Update binding document not use default clock-frequency as example.
> 2. Add mtk_i2c_compatible struct and pass hardware capabilities
>    through of_device_id
> 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
>    so just init one time.
> 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> 
> Change in v5:
> Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> Add MT8173 I2C driver.
> 
> Change in v4:
> Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> Remove check transfer size and WRRD combine code. Instead, fill quirk
> property and let i2c_check_for_quirks to do the filter.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> 
> Eddie Huang (1):
>   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> 
> Xudong Chen (2):
>   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
>   I2C: mediatek: Add driver for MediaTek I2C controller
> 
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
>  drivers/i2c/busses/Kconfig                         |   9 +
>  drivers/i2c/busses/Makefile                        |   1 +
>  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
>  4 files changed, 799 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
>  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c

Again, you've sent me a patch-set that has absolutely nothing to do
with me.  Can you please stop doing that, my inbox is full enough
already!

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
  2015-05-07  7:39   ` Lee Jones
  (?)
@ 2015-05-07  7:54     ` Eddie Huang
  -1 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-07  7:54 UTC (permalink / raw)
  To: Lee Jones
  Cc: Mark Rutland, Wolfram Sang, linux-kernel, linux-i2c, David Box,
	Jean Delvare, Xudong Chen, Boris BREZILLON, Arnd Bergmann,
	Liguo Zhang, Wei Yan, Neelesh Gupta, Zhangfei Gao, devicetree,
	Pawel Moll, Ian Campbell, Ray Jui, Beniamino Galvani,
	Rob Herring, linux-mediatek, Matthias Brugger, linux-arm-kernel,
	srv_heupstream, Anders Berg, Simon Glass, Max Schwarz,
	Doug Anderson, Sascha Hauer, Kumar Gala

Hi Lee,

On Thu, 2015-05-07 at 08:39 +0100, Lee Jones wrote:
> On Wed, 06 May 2015, Eddie Huang wrote:
> 
> > 
> > Eddie Huang (1):
> >   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> > 
> > Xudong Chen (2):
> >   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
> >   I2C: mediatek: Add driver for MediaTek I2C controller
> > 
> >  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
> >  drivers/i2c/busses/Kconfig                         |   9 +
> >  drivers/i2c/busses/Makefile                        |   1 +
> >  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
> >  4 files changed, 799 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> >  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
> 
> Again, you've sent me a patch-set that has absolutely nothing to do
> with me.  Can you please stop doing that, my inbox is full enough
> already!
> 

Sorry, I use "scripts/get_maintainer.pl" to get mail receiver, and you
are on list.
I will narrow down receiver next time.

Eddie




^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-07  7:54     ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-07  7:54 UTC (permalink / raw)
  To: Lee Jones
  Cc: Mark Rutland, Wolfram Sang, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, David Box, Jean Delvare,
	Xudong Chen, Boris BREZILLON, Arnd Bergmann, Liguo Zhang,
	Wei Yan, Neelesh Gupta, Zhangfei Gao,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Pawel Moll, Ian Campbell,
	Ray Jui, Beniamino Galvani, Rob Herring,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Matthias Brugger,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w

Hi Lee,

On Thu, 2015-05-07 at 08:39 +0100, Lee Jones wrote:
> On Wed, 06 May 2015, Eddie Huang wrote:
> 
> > 
> > Eddie Huang (1):
> >   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> > 
> > Xudong Chen (2):
> >   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
> >   I2C: mediatek: Add driver for MediaTek I2C controller
> > 
> >  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
> >  drivers/i2c/busses/Kconfig                         |   9 +
> >  drivers/i2c/busses/Makefile                        |   1 +
> >  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
> >  4 files changed, 799 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> >  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
> 
> Again, you've sent me a patch-set that has absolutely nothing to do
> with me.  Can you please stop doing that, my inbox is full enough
> already!
> 

Sorry, I use "scripts/get_maintainer.pl" to get mail receiver, and you
are on list.
I will narrow down receiver next time.

Eddie

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-07  7:54     ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-07  7:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lee,

On Thu, 2015-05-07 at 08:39 +0100, Lee Jones wrote:
> On Wed, 06 May 2015, Eddie Huang wrote:
> 
> > 
> > Eddie Huang (1):
> >   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> > 
> > Xudong Chen (2):
> >   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
> >   I2C: mediatek: Add driver for MediaTek I2C controller
> > 
> >  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
> >  drivers/i2c/busses/Kconfig                         |   9 +
> >  drivers/i2c/busses/Makefile                        |   1 +
> >  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
> >  4 files changed, 799 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> >  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
> 
> Again, you've sent me a patch-set that has absolutely nothing to do
> with me.  Can you please stop doing that, my inbox is full enough
> already!
> 

Sorry, I use "scripts/get_maintainer.pl" to get mail receiver, and you
are on list.
I will narrow down receiver next time.

Eddie

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
  2015-05-07  7:54     ` Eddie Huang
  (?)
@ 2015-05-07  8:27       ` Lee Jones
  -1 siblings, 0 replies; 48+ messages in thread
From: Lee Jones @ 2015-05-07  8:27 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Mark Rutland, Wolfram Sang, linux-kernel, linux-i2c, David Box,
	Jean Delvare, Xudong Chen, Boris BREZILLON, Arnd Bergmann,
	Liguo Zhang, Wei Yan, Neelesh Gupta, Zhangfei Gao, devicetree,
	Pawel Moll, Ian Campbell, Ray Jui, Beniamino Galvani,
	Rob Herring, linux-mediatek, Matthias Brugger, linux-arm-kernel,
	srv_heupstream, Anders Berg, Simon Glass, Max Schwarz,
	Doug Anderson, Sascha Hauer, Kumar Gala

On Thu, 07 May 2015, Eddie Huang wrote:
> On Thu, 2015-05-07 at 08:39 +0100, Lee Jones wrote:
> > On Wed, 06 May 2015, Eddie Huang wrote:
> > 
> > > 
> > > Eddie Huang (1):
> > >   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> > > 
> > > Xudong Chen (2):
> > >   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
> > >   I2C: mediatek: Add driver for MediaTek I2C controller
> > > 
> > >  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
> > >  drivers/i2c/busses/Kconfig                         |   9 +
> > >  drivers/i2c/busses/Makefile                        |   1 +
> > >  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
> > >  4 files changed, 799 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> > >  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
> > 
> > Again, you've sent me a patch-set that has absolutely nothing to do
> > with me.  Can you please stop doing that, my inbox is full enough
> > already!
> > 
> 
> Sorry, I use "scripts/get_maintainer.pl" to get mail receiver, and you
> are on list.

Yes, the "Commit Signer" entry is the bane of my life.  It's best not
to Cc everyone who has every touched a file in a given subsystem.

> I will narrow down receiver next time.

Thanks.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-07  8:27       ` Lee Jones
  0 siblings, 0 replies; 48+ messages in thread
From: Lee Jones @ 2015-05-07  8:27 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Mark Rutland, Wolfram Sang, linux-kernel, linux-i2c, David Box,
	Jean Delvare, Xudong Chen, Boris BREZILLON, Arnd Bergmann,
	Liguo Zhang, Wei Yan, Neelesh Gupta, Zhangfei Gao, devicetree,
	Pawel Moll, Ian Campbell, Ray Jui, Beniamino Galvani,
	Rob Herring, linux-mediatek, Matthias Brugger, linux-arm-kernel,
	srv_heupstream, Anders Berg

On Thu, 07 May 2015, Eddie Huang wrote:
> On Thu, 2015-05-07 at 08:39 +0100, Lee Jones wrote:
> > On Wed, 06 May 2015, Eddie Huang wrote:
> > 
> > > 
> > > Eddie Huang (1):
> > >   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> > > 
> > > Xudong Chen (2):
> > >   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
> > >   I2C: mediatek: Add driver for MediaTek I2C controller
> > > 
> > >  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
> > >  drivers/i2c/busses/Kconfig                         |   9 +
> > >  drivers/i2c/busses/Makefile                        |   1 +
> > >  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
> > >  4 files changed, 799 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> > >  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
> > 
> > Again, you've sent me a patch-set that has absolutely nothing to do
> > with me.  Can you please stop doing that, my inbox is full enough
> > already!
> > 
> 
> Sorry, I use "scripts/get_maintainer.pl" to get mail receiver, and you
> are on list.

Yes, the "Commit Signer" entry is the bane of my life.  It's best not
to Cc everyone who has every touched a file in a given subsystem.

> I will narrow down receiver next time.

Thanks.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-07  8:27       ` Lee Jones
  0 siblings, 0 replies; 48+ messages in thread
From: Lee Jones @ 2015-05-07  8:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 07 May 2015, Eddie Huang wrote:
> On Thu, 2015-05-07 at 08:39 +0100, Lee Jones wrote:
> > On Wed, 06 May 2015, Eddie Huang wrote:
> > 
> > > 
> > > Eddie Huang (1):
> > >   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> > > 
> > > Xudong Chen (2):
> > >   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
> > >   I2C: mediatek: Add driver for MediaTek I2C controller
> > > 
> > >  .../devicetree/bindings/i2c/i2c-mt6577.txt         |  41 ++
> > >  drivers/i2c/busses/Kconfig                         |   9 +
> > >  drivers/i2c/busses/Makefile                        |   1 +
> > >  drivers/i2c/busses/i2c-mt65xx.c                    | 748 +++++++++++++++++++++
> > >  4 files changed, 799 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> > >  create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
> > 
> > Again, you've sent me a patch-set that has absolutely nothing to do
> > with me.  Can you please stop doing that, my inbox is full enough
> > already!
> > 
> 
> Sorry, I use "scripts/get_maintainer.pl" to get mail receiver, and you
> are on list.

Yes, the "Commit Signer" entry is the bane of my life.  It's best not
to Cc everyone who has every touched a file in a given subsystem.

> I will narrow down receiver next time.

Thanks.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-12 12:37     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa @ 2015-05-12 12:37 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani, Xudong Chen, Liguo Zhang, linux-i2c,
	devicetree, linux-kernel, linux-arm-kernel, linux-mediatek

On Wed, May 06, 2015 at 04:37:05PM +0800, Eddie Huang wrote:
> From: Xudong Chen <xudong.chen@mediatek.com>
> 
> Add devicetree bindings for Mediatek Soc I2C driver.
> 
> Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
> Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>

Sascha, Uwe: Can you ack these patches if you are fine with them?
Would be nice since you did quite some review and were involved in the
"have-pmic" binding discussion.

Thanks,

   Wolfram

> ---
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> new file mode 100644
> index 0000000..0ce6fa3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> @@ -0,0 +1,41 @@
> +* Mediatek's I2C controller
> +
> +The Mediatek's I2C controller is used to interface with I2C devices.
> +
> +Required properties:
> +  - compatible: value should be either of the following.
> +      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
> +      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
> +      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
> +      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
> +      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
> +  - reg: physical base address of the controller and dma base, length of memory
> +    mapped region.
> +  - interrupts: interrupt number to the cpu.
> +  - clock-div: the fixed value for frequency divider of clock source in i2c
> +    module. Each IC may be different.
> +  - clocks: clock name from clock manager
> +  - clock-names: Must include "main" and "dma", if enable have-pmic need include
> +    "pmic" extra.
> +
> +Optional properties:
> +  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
> +    is 100000.
> +  - mediatek,have-pmic: platform can control i2c form special pmic side.
> +    Only mt6589 and mt8135 support this feature.
> +  - mediatek,use-push-pull: IO config use push-pull mode.
> +
> +Example:
> +
> +	i2c0: i2c@1100d000 {
> +			compatible = "mediatek,mt6577-i2c";
> +			reg = <0x1100d000 0x70>,
> +			      <0x11000300 0x80>;
> +			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
> +			clock-frequency = <400000>;
> +			mediatek,have-pmic;
> +			clock-div = <16>;
> +			clocks = <&i2c0_ck>, <&ap_dma_ck>;
> +			clock-names = "main", "dma";
> +	};
> +
> -- 
> 1.8.1.1.dirty
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-12 12:37     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa-z923LK4zBo2bacvFa/9K2g @ 2015-05-12 12:37 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Jean Delvare, David Box, Doug Anderson,
	Zhangfei Gao, Max Schwarz, Boris BREZILLON, Anders Berg,
	Neelesh Gupta, Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass,
	Wei Yan, Beniamino Galvani, Xudong Chen, Liguo

On Wed, May 06, 2015 at 04:37:05PM +0800, Eddie Huang wrote:
> From: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> 
> Add devicetree bindings for Mediatek Soc I2C driver.
> 
> Signed-off-by: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Eddie Huang <eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>

Sascha, Uwe: Can you ack these patches if you are fine with them?
Would be nice since you did quite some review and were involved in the
"have-pmic" binding discussion.

Thanks,

   Wolfram

> ---
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> new file mode 100644
> index 0000000..0ce6fa3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> @@ -0,0 +1,41 @@
> +* Mediatek's I2C controller
> +
> +The Mediatek's I2C controller is used to interface with I2C devices.
> +
> +Required properties:
> +  - compatible: value should be either of the following.
> +      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
> +      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
> +      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
> +      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
> +      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
> +  - reg: physical base address of the controller and dma base, length of memory
> +    mapped region.
> +  - interrupts: interrupt number to the cpu.
> +  - clock-div: the fixed value for frequency divider of clock source in i2c
> +    module. Each IC may be different.
> +  - clocks: clock name from clock manager
> +  - clock-names: Must include "main" and "dma", if enable have-pmic need include
> +    "pmic" extra.
> +
> +Optional properties:
> +  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
> +    is 100000.
> +  - mediatek,have-pmic: platform can control i2c form special pmic side.
> +    Only mt6589 and mt8135 support this feature.
> +  - mediatek,use-push-pull: IO config use push-pull mode.
> +
> +Example:
> +
> +	i2c0: i2c@1100d000 {
> +			compatible = "mediatek,mt6577-i2c";
> +			reg = <0x1100d000 0x70>,
> +			      <0x11000300 0x80>;
> +			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
> +			clock-frequency = <400000>;
> +			mediatek,have-pmic;
> +			clock-div = <16>;
> +			clocks = <&i2c0_ck>, <&ap_dma_ck>;
> +			clock-names = "main", "dma";
> +	};
> +
> -- 
> 1.8.1.1.dirty
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-12 12:37     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa at the-dreams.de @ 2015-05-12 12:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 06, 2015 at 04:37:05PM +0800, Eddie Huang wrote:
> From: Xudong Chen <xudong.chen@mediatek.com>
> 
> Add devicetree bindings for Mediatek Soc I2C driver.
> 
> Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
> Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>

Sascha, Uwe: Can you ack these patches if you are fine with them?
Would be nice since you did quite some review and were involved in the
"have-pmic" binding discussion.

Thanks,

   Wolfram

> ---
>  .../devicetree/bindings/i2c/i2c-mt6577.txt         | 41 ++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> new file mode 100644
> index 0000000..0ce6fa3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
> @@ -0,0 +1,41 @@
> +* Mediatek's I2C controller
> +
> +The Mediatek's I2C controller is used to interface with I2C devices.
> +
> +Required properties:
> +  - compatible: value should be either of the following.
> +      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
> +      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
> +      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
> +      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
> +      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
> +  - reg: physical base address of the controller and dma base, length of memory
> +    mapped region.
> +  - interrupts: interrupt number to the cpu.
> +  - clock-div: the fixed value for frequency divider of clock source in i2c
> +    module. Each IC may be different.
> +  - clocks: clock name from clock manager
> +  - clock-names: Must include "main" and "dma", if enable have-pmic need include
> +    "pmic" extra.
> +
> +Optional properties:
> +  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
> +    is 100000.
> +  - mediatek,have-pmic: platform can control i2c form special pmic side.
> +    Only mt6589 and mt8135 support this feature.
> +  - mediatek,use-push-pull: IO config use push-pull mode.
> +
> +Example:
> +
> +	i2c0: i2c at 1100d000 {
> +			compatible = "mediatek,mt6577-i2c";
> +			reg = <0x1100d000 0x70>,
> +			      <0x11000300 0x80>;
> +			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
> +			clock-frequency = <400000>;
> +			mediatek,have-pmic;
> +			clock-div = <16>;
> +			clocks = <&i2c0_ck>, <&ap_dma_ck>;
> +			clock-names = "main", "dma";
> +	};
> +
> -- 
> 1.8.1.1.dirty
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-12 12:45   ` Sascha Hauer
  0 siblings, 0 replies; 48+ messages in thread
From: Sascha Hauer @ 2015-05-12 12:45 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Wolfram Sang, Sascha Hauer, srv_heupstream, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Jean Delvare, David Box, Doug Anderson,
	Zhangfei Gao, Max Schwarz, Boris BREZILLON, Anders Berg,
	Neelesh Gupta, Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass,
	Wei Yan, Beniamino Galvani, Xudong Chen, Liguo Zhang, linux-i2c,
	devicetree, linux-kernel, linux-arm-kernel, linux-mediatek

On Wed, May 06, 2015 at 04:37:04PM +0800, Eddie Huang wrote:
> This series is for Mediatek SoCs I2C controller common bus driver.
> 
> Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> New generation SoC like MT8173 fix following limitations:
> 
> 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> mode. WRRD can have two i2c_msg numbers.
> 
> 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> mode the Repeat Start will be issued between 2 messages.
> In this driver if 2 messages is first write then read, the driver will
> combine 2 messages using Write-Read mode so the RS will be issued between
> the 2 messages.
> 
> 3. The max transfer data length is 255 in one message. In WRRD mode, the
> max data length of second msg is 31.
> 
> MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> bit first, the operation on other registers are still the same.
> For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> "mediatek,have-pmic" property in the .dts file of each platform.
> 
> This driver is based on 4.1-rc1.
> 
> Change in v7:
> Fix mtk_i2c_of_match in wrong patch bug.
> 
> Change in v6:
> 1. Update binding document not use default clock-frequency as example.
> 2. Add mtk_i2c_compatible struct and pass hardware capabilities
>    through of_device_id
> 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
>    so just init one time.
> 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> 
> Change in v5:
> Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> Add MT8173 I2C driver.
> 
> Change in v4:
> Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> Remove check transfer size and WRRD combine code. Instead, fill quirk
> property and let i2c_check_for_quirks to do the filter.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> 
> Eddie Huang (1):
>   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> 
> Xudong Chen (2):
>   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
>   I2C: mediatek: Add driver for MediaTek I2C controller

All:

Acked-by: Sascha Hauer <s.hauer@pengutronix.de>

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-12 12:45   ` Sascha Hauer
  0 siblings, 0 replies; 48+ messages in thread
From: Sascha Hauer @ 2015-05-12 12:45 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Wolfram Sang, Sascha Hauer,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani

On Wed, May 06, 2015 at 04:37:04PM +0800, Eddie Huang wrote:
> This series is for Mediatek SoCs I2C controller common bus driver.
> 
> Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> New generation SoC like MT8173 fix following limitations:
> 
> 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> mode. WRRD can have two i2c_msg numbers.
> 
> 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> mode the Repeat Start will be issued between 2 messages.
> In this driver if 2 messages is first write then read, the driver will
> combine 2 messages using Write-Read mode so the RS will be issued between
> the 2 messages.
> 
> 3. The max transfer data length is 255 in one message. In WRRD mode, the
> max data length of second msg is 31.
> 
> MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> bit first, the operation on other registers are still the same.
> For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> "mediatek,have-pmic" property in the .dts file of each platform.
> 
> This driver is based on 4.1-rc1.
> 
> Change in v7:
> Fix mtk_i2c_of_match in wrong patch bug.
> 
> Change in v6:
> 1. Update binding document not use default clock-frequency as example.
> 2. Add mtk_i2c_compatible struct and pass hardware capabilities
>    through of_device_id
> 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
>    so just init one time.
> 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> 
> Change in v5:
> Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> Add MT8173 I2C driver.
> 
> Change in v4:
> Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> Remove check transfer size and WRRD combine code. Instead, fill quirk
> property and let i2c_check_for_quirks to do the filter.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> 
> Eddie Huang (1):
>   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> 
> Xudong Chen (2):
>   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
>   I2C: mediatek: Add driver for MediaTek I2C controller

All:

Acked-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C
@ 2015-05-12 12:45   ` Sascha Hauer
  0 siblings, 0 replies; 48+ messages in thread
From: Sascha Hauer @ 2015-05-12 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 06, 2015 at 04:37:04PM +0800, Eddie Huang wrote:
> This series is for Mediatek SoCs I2C controller common bus driver.
> 
> Earlier MTK SoC ((for example, MT6589, MT8135)) I2C HW has some limitationes.
> New generation SoC like MT8173 fix following limitations:
> 
> 1. Only support one i2c_msg number. One exception is WRRD (write then read)
> mode. WRRD can have two i2c_msg numbers.
> 
> 2. Mediatek I2C controller support WRRD(write then read) mode, in WRRD
> mode the Repeat Start will be issued between 2 messages.
> In this driver if 2 messages is first write then read, the driver will
> combine 2 messages using Write-Read mode so the RS will be issued between
> the 2 messages.
> 
> 3. The max transfer data length is 255 in one message. In WRRD mode, the
> max data length of second msg is 31.
> 
> MT8135 and MT6589 can control I2C pins on PMIC(MT6397) by setting the i2c
> registers in MT8135 side. In this case, driver should set OFFSET_PATH_DIR
> bit first, the operation on other registers are still the same.
> For now MT6589/MT8135 support this, MT6577/MT6595/MT8127 do not support.
> For example, If want to use I2C4/5/6 pins on MT8135 just need to enable
> the pinmux, else if want to use I2C pins on PMIC(MT6397) need to add
> "mediatek,have-pmic" property in the .dts file of each platform.
> 
> This driver is based on 4.1-rc1.
> 
> Change in v7:
> Fix mtk_i2c_of_match in wrong patch bug.
> 
> Change in v6:
> 1. Update binding document not use default clock-frequency as example.
> 2. Add mtk_i2c_compatible struct and pass hardware capabilities
>    through of_device_id
> 3. Remove some hardware setting in mtk_i2c_do_transfer to mtk_i2c_init_hw
>    so just init one time.
> 4. Correct mtk_i2c_parse_dt don't set default clock bug.
> 
> Change in v5:
> Apply new i2c_adapter_quirks patch [2]. Change to use dam_map_single to map
> dma buffer. Add spinlock to fix race condition. Check of_property_read_u32
> return value. Remove I2C_FUNC_10BIT_ADDR capability due to driver not implement.
> Add MT8173 I2C driver.
> 
> Change in v4:
> Modify to support i2c_adapter_quirks base on Wolfram's patch [1].
> Remove check transfer size and WRRD combine code. Instead, fill quirk
> property and let i2c_check_for_quirks to do the filter.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314804.html
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/325744.html
> 
> Eddie Huang (1):
>   I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
> 
> Xudong Chen (2):
>   dt-bindings: Add I2C bindings for mt65xx/mt81xx.
>   I2C: mediatek: Add driver for MediaTek I2C controller

All:

Acked-by: Sascha Hauer <s.hauer@pengutronix.de>

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-12 12:45       ` Sascha Hauer
  0 siblings, 0 replies; 48+ messages in thread
From: Sascha Hauer @ 2015-05-12 12:45 UTC (permalink / raw)
  To: wsa
  Cc: Eddie Huang, Mark Rutland, linux-kernel, linux-i2c, David Box,
	Lee Jones, Jean Delvare, Xudong Chen, Boris BREZILLON,
	Arnd Bergmann, Liguo Zhang, Wei Yan, Neelesh Gupta, Zhangfei Gao,
	devicetree, Pawel Moll, Ian Campbell, Ray Jui, Beniamino Galvani,
	Rob Herring, linux-mediatek, Matthias Brugger, linux-arm-kernel,
	srv_heupstream, Anders Berg, Simon Glass, Max Schwarz,
	Doug Anderson, Sascha Hauer, Kumar Gala

Hi Wolfram,

On Tue, May 12, 2015 at 02:37:09PM +0200, wsa@the-dreams.de wrote:
> On Wed, May 06, 2015 at 04:37:05PM +0800, Eddie Huang wrote:
> > From: Xudong Chen <xudong.chen@mediatek.com>
> > 
> > Add devicetree bindings for Mediatek Soc I2C driver.
> > 
> > Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
> > Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
> 
> Sascha, Uwe: Can you ack these patches if you are fine with them?
> Would be nice since you did quite some review and were involved in the
> "have-pmic" binding discussion.

Just did that. That code went through enough reviews.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-12 12:45       ` Sascha Hauer
  0 siblings, 0 replies; 48+ messages in thread
From: Sascha Hauer @ 2015-05-12 12:45 UTC (permalink / raw)
  To: wsa-z923LK4zBo2bacvFa/9K2g
  Cc: Eddie Huang, Mark Rutland, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, David Box, Lee Jones,
	Jean Delvare, Xudong Chen, Boris BREZILLON, Arnd Bergmann,
	Liguo Zhang, Wei Yan, Neelesh Gupta, Zhangfei Gao,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Pawel Moll, Ian Campbell,
	Ray Jui, Beniamino Galvani, Rob Herring,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Matthias Brugger,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	srv_heupstream

Hi Wolfram,

On Tue, May 12, 2015 at 02:37:09PM +0200, wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org wrote:
> On Wed, May 06, 2015 at 04:37:05PM +0800, Eddie Huang wrote:
> > From: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > 
> > Add devicetree bindings for Mediatek Soc I2C driver.
> > 
> > Signed-off-by: Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > Signed-off-by: Eddie Huang <eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> 
> Sascha, Uwe: Can you ack these patches if you are fine with them?
> Would be nice since you did quite some review and were involved in the
> "have-pmic" binding discussion.

Just did that. That code went through enough reviews.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
@ 2015-05-12 12:45       ` Sascha Hauer
  0 siblings, 0 replies; 48+ messages in thread
From: Sascha Hauer @ 2015-05-12 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Wolfram,

On Tue, May 12, 2015 at 02:37:09PM +0200, wsa at the-dreams.de wrote:
> On Wed, May 06, 2015 at 04:37:05PM +0800, Eddie Huang wrote:
> > From: Xudong Chen <xudong.chen@mediatek.com>
> > 
> > Add devicetree bindings for Mediatek Soc I2C driver.
> > 
> > Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
> > Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
> 
> Sascha, Uwe: Can you ack these patches if you are fine with them?
> Would be nice since you did quite some review and were involved in the
> "have-pmic" binding discussion.

Just did that. That code went through enough reviews.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-12 12:58     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa @ 2015-05-12 12:58 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani, Xudong Chen, Liguo Zhang, linux-i2c,
	devicetree, linux-kernel, linux-arm-kernel, linux-mediatek

[-- Attachment #1: Type: text/plain, Size: 3041 bytes --]

> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/mm.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/scatterlist.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/clk.h>
> +#include <linux/completion.h>

Please sort the includes to avoid duplicates.

> +struct mtk_i2c_compatible {
> +	const struct i2c_adapter_quirks *quirks;
> +	unsigned char pmic_i2c;
> +	unsigned char dcm;
> +};

I wonder if the unsigned char options can be bits in a flags variable?

> +static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
> +	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
> +	.max_num_msgs = MAX_MSG_NUM_MT6577,
> +	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
> +};

I would think plain numbers are much more readable than defines here.
They are used only once, too.

> +static const struct of_device_id mtk_i2c_of_match[] = {
> +	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
> +	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);

No need for casts.

> +static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
> +{
> +	writew(value, i2c->base + offset);
> +}
> +
> +static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
> +{
> +	return readw(i2c->base + offset);
> +}

I am not a big fan of such extremly thin wrappers, but if you like them...

> +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> +						msgs->len, DMA_FROM_DEVICE);

I think you shouldn't use the adapter device here and later, but the dma
channel device.

> +	/* flush before sending start */
> +	mb();
> +	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);

Is mb() really needed when you use writel after that?

> +	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
> +		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
> +		mtk_i2c_init_hw(i2c);
> +		return -EREMOTEIO;

-ENXIO. Please check Documentation/i2c/fault-codes for a reference and
check all your error values.

> +	ret = of_property_read_u32(np, "clock-div", clk_src_div);
> +	if (ret < 0)
> +		return ret;

Do we need a property for that in the i2c-block? Can't the clock
provider driver deliver a properly divided clock already?


And cppcheck says:

drivers/i2c/busses/i2c-mt65xx.c:133: style: struct or union member 'mtk_i2c_data::clk_frequency' is never used.
drivers/i2c/busses/i2c-mt65xx.c:135: style: struct or union member 'mtk_i2c_data::clk_src_div' is never used.

Rest looks good, thanks!


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-12 12:58     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa-z923LK4zBo2bacvFa/9K2g @ 2015-05-12 12:58 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Jean Delvare, David Box, Doug Anderson,
	Zhangfei Gao, Max Schwarz, Boris BREZILLON, Anders Berg,
	Neelesh Gupta, Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass,
	Wei Yan, Beniamino Galvani, Xudong Chen, Liguo

[-- Attachment #1: Type: text/plain, Size: 3041 bytes --]

> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/mm.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/scatterlist.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/clk.h>
> +#include <linux/completion.h>

Please sort the includes to avoid duplicates.

> +struct mtk_i2c_compatible {
> +	const struct i2c_adapter_quirks *quirks;
> +	unsigned char pmic_i2c;
> +	unsigned char dcm;
> +};

I wonder if the unsigned char options can be bits in a flags variable?

> +static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
> +	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
> +	.max_num_msgs = MAX_MSG_NUM_MT6577,
> +	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
> +};

I would think plain numbers are much more readable than defines here.
They are used only once, too.

> +static const struct of_device_id mtk_i2c_of_match[] = {
> +	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
> +	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);

No need for casts.

> +static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
> +{
> +	writew(value, i2c->base + offset);
> +}
> +
> +static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
> +{
> +	return readw(i2c->base + offset);
> +}

I am not a big fan of such extremly thin wrappers, but if you like them...

> +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> +						msgs->len, DMA_FROM_DEVICE);

I think you shouldn't use the adapter device here and later, but the dma
channel device.

> +	/* flush before sending start */
> +	mb();
> +	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);

Is mb() really needed when you use writel after that?

> +	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
> +		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
> +		mtk_i2c_init_hw(i2c);
> +		return -EREMOTEIO;

-ENXIO. Please check Documentation/i2c/fault-codes for a reference and
check all your error values.

> +	ret = of_property_read_u32(np, "clock-div", clk_src_div);
> +	if (ret < 0)
> +		return ret;

Do we need a property for that in the i2c-block? Can't the clock
provider driver deliver a properly divided clock already?


And cppcheck says:

drivers/i2c/busses/i2c-mt65xx.c:133: style: struct or union member 'mtk_i2c_data::clk_frequency' is never used.
drivers/i2c/busses/i2c-mt65xx.c:135: style: struct or union member 'mtk_i2c_data::clk_src_div' is never used.

Rest looks good, thanks!


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-12 12:58     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa at the-dreams.de @ 2015-05-12 12:58 UTC (permalink / raw)
  To: linux-arm-kernel

> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/mm.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/scatterlist.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/clk.h>
> +#include <linux/completion.h>

Please sort the includes to avoid duplicates.

> +struct mtk_i2c_compatible {
> +	const struct i2c_adapter_quirks *quirks;
> +	unsigned char pmic_i2c;
> +	unsigned char dcm;
> +};

I wonder if the unsigned char options can be bits in a flags variable?

> +static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
> +	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
> +	.max_num_msgs = MAX_MSG_NUM_MT6577,
> +	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
> +	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
> +};

I would think plain numbers are much more readable than defines here.
They are used only once, too.

> +static const struct of_device_id mtk_i2c_of_match[] = {
> +	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
> +	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);

No need for casts.

> +static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
> +{
> +	writew(value, i2c->base + offset);
> +}
> +
> +static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
> +{
> +	return readw(i2c->base + offset);
> +}

I am not a big fan of such extremly thin wrappers, but if you like them...

> +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> +						msgs->len, DMA_FROM_DEVICE);

I think you shouldn't use the adapter device here and later, but the dma
channel device.

> +	/* flush before sending start */
> +	mb();
> +	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);

Is mb() really needed when you use writel after that?

> +	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
> +		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
> +		mtk_i2c_init_hw(i2c);
> +		return -EREMOTEIO;

-ENXIO. Please check Documentation/i2c/fault-codes for a reference and
check all your error values.

> +	ret = of_property_read_u32(np, "clock-div", clk_src_div);
> +	if (ret < 0)
> +		return ret;

Do we need a property for that in the i2c-block? Can't the clock
provider driver deliver a properly divided clock already?


And cppcheck says:

drivers/i2c/busses/i2c-mt65xx.c:133: style: struct or union member 'mtk_i2c_data::clk_frequency' is never used.
drivers/i2c/busses/i2c-mt65xx.c:135: style: struct or union member 'mtk_i2c_data::clk_src_div' is never used.

Rest looks good, thanks!

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150512/6e08758c/attachment.sig>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 3/3] I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
@ 2015-05-12 13:00     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa @ 2015-05-12 13:00 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Jean Delvare, David Box, Doug Anderson, Zhangfei Gao,
	Max Schwarz, Boris BREZILLON, Anders Berg, Neelesh Gupta,
	Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass, Wei Yan,
	Beniamino Galvani, Xudong Chen, Liguo Zhang, linux-i2c,
	devicetree, linux-kernel, linux-arm-kernel, linux-mediatek

[-- Attachment #1: Type: text/plain, Size: 244 bytes --]

> +	if (i2c->irq_stat & I2C_RS_TRANSFER)
> +		dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
> +				msgs->addr);

I'd tend to leave out this debug message. But you may leave it if you
like. Rest of the patch looks okay.

Thanks!


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 3/3] I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
@ 2015-05-12 13:00     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa-z923LK4zBo2bacvFa/9K2g @ 2015-05-12 13:00 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Jean Delvare, David Box, Doug Anderson,
	Zhangfei Gao, Max Schwarz, Boris BREZILLON, Anders Berg,
	Neelesh Gupta, Lee Jones, Arnd Bergmann, Ray Jui, Simon Glass,
	Wei Yan, Beniamino Galvani, Xudong Chen, Liguo

[-- Attachment #1: Type: text/plain, Size: 244 bytes --]

> +	if (i2c->irq_stat & I2C_RS_TRANSFER)
> +		dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
> +				msgs->addr);

I'd tend to leave out this debug message. But you may leave it if you
like. Rest of the patch looks okay.

Thanks!


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 3/3] I2C: mediatek: Add driver for MediaTek MT8173 I2C controller
@ 2015-05-12 13:00     ` wsa-z923LK4zBo2bacvFa/9K2g
  0 siblings, 0 replies; 48+ messages in thread
From: wsa at the-dreams.de @ 2015-05-12 13:00 UTC (permalink / raw)
  To: linux-arm-kernel

> +	if (i2c->irq_stat & I2C_RS_TRANSFER)
> +		dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
> +				msgs->addr);

I'd tend to leave out this debug message. But you may leave it if you
like. Rest of the patch looks okay.

Thanks!

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150512/0de3255d/attachment.sig>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  5:58       ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-18  5:58 UTC (permalink / raw)
  To: wsa
  Cc: Sascha Hauer, srv_heupstream, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek

Hi Wolfram,

Narrow down CC-list.
Please see my reply below.

On Tue, 2015-05-12 at 14:58 +0200, wsa@the-dreams.de wrote:
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/slab.h>
> > +#include <linux/i2c.h>
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/sched.h>
> > +#include <linux/delay.h>
> > +#include <linux/errno.h>
> > +#include <linux/err.h>
> > +#include <linux/device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/mm.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/scatterlist.h>
> > +#include <linux/io.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/clk.h>
> > +#include <linux/completion.h>
> 
> Please sort the includes to avoid duplicates.
OK, will fix it.

> 
> > +struct mtk_i2c_compatible {
> > +	const struct i2c_adapter_quirks *quirks;
> > +	unsigned char pmic_i2c;
> > +	unsigned char dcm;
> > +};
> 
> I wonder if the unsigned char options can be bits in a flags variable?

OK, will fix it.

> 
> > +static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
> > +	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
> > +	.max_num_msgs = MAX_MSG_NUM_MT6577,
> > +	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
> > +};
> 
> I would think plain numbers are much more readable than defines here.
> They are used only once, too.
> 
OK, will fix it.

> > +static const struct of_device_id mtk_i2c_of_match[] = {
> > +	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
> > +	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> > +	{}
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
> 
> No need for casts.
> 
OK, will fix it.

> > +static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
> > +{
> > +	writew(value, i2c->base + offset);
> > +}
> > +
> > +static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
> > +{
> > +	return readw(i2c->base + offset);
> > +}
> 
> I am not a big fan of such extremly thin wrappers, but if you like them...
> 
OK, will fix it.

> > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > +						msgs->len, DMA_FROM_DEVICE);
> 
> I think you shouldn't use the adapter device here and later, but the dma
> channel device.
> 
In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
used by other hardware.
So I tend to use DMA directly, not through DMA channel.
Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
use i2c->dev here. (Reference i2c-at91.c).

> > +	/* flush before sending start */
> > +	mb();
> > +	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
> 
> Is mb() really needed when you use writel after that?
> 
mb() should be removed here.

> > +	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
> > +		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
> > +		mtk_i2c_init_hw(i2c);
> > +		return -EREMOTEIO;
> 
> -ENXIO. Please check Documentation/i2c/fault-codes for a reference and
> check all your error values.
> 
OK, I will check return values.

> > +	ret = of_property_read_u32(np, "clock-div", clk_src_div);
> > +	if (ret < 0)
> > +		return ret;
> 
> Do we need a property for that in the i2c-block? Can't the clock
> provider driver deliver a properly divided clock already?
> 
Actually, the clock divider implement in I2C controller self.
Clock provider don't have such knowledge to know the divider. The
divider may not be the same in different chip, this is why we put
"clock-div" in device tree. 

> 
> And cppcheck says:
> 
> drivers/i2c/busses/i2c-mt65xx.c:133: style: struct or union member 'mtk_i2c_data::clk_frequency' is never used.
> drivers/i2c/busses/i2c-mt65xx.c:135: style: struct or union member 'mtk_i2c_data::clk_src_div' is never used.
> 
OK, I will remove them.

Thanks your review.
Eddie





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  5:58       ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-18  5:58 UTC (permalink / raw)
  To: wsa-z923LK4zBo2bacvFa/9K2g
  Cc: Sascha Hauer, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Xudong Chen, Liguo Zhang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Wolfram,

Narrow down CC-list.
Please see my reply below.

On Tue, 2015-05-12 at 14:58 +0200, wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org wrote:
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/slab.h>
> > +#include <linux/i2c.h>
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/sched.h>
> > +#include <linux/delay.h>
> > +#include <linux/errno.h>
> > +#include <linux/err.h>
> > +#include <linux/device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/mm.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/scatterlist.h>
> > +#include <linux/io.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/clk.h>
> > +#include <linux/completion.h>
> 
> Please sort the includes to avoid duplicates.
OK, will fix it.

> 
> > +struct mtk_i2c_compatible {
> > +	const struct i2c_adapter_quirks *quirks;
> > +	unsigned char pmic_i2c;
> > +	unsigned char dcm;
> > +};
> 
> I wonder if the unsigned char options can be bits in a flags variable?

OK, will fix it.

> 
> > +static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
> > +	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
> > +	.max_num_msgs = MAX_MSG_NUM_MT6577,
> > +	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
> > +};
> 
> I would think plain numbers are much more readable than defines here.
> They are used only once, too.
> 
OK, will fix it.

> > +static const struct of_device_id mtk_i2c_of_match[] = {
> > +	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
> > +	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> > +	{}
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
> 
> No need for casts.
> 
OK, will fix it.

> > +static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
> > +{
> > +	writew(value, i2c->base + offset);
> > +}
> > +
> > +static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
> > +{
> > +	return readw(i2c->base + offset);
> > +}
> 
> I am not a big fan of such extremly thin wrappers, but if you like them...
> 
OK, will fix it.

> > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > +						msgs->len, DMA_FROM_DEVICE);
> 
> I think you shouldn't use the adapter device here and later, but the dma
> channel device.
> 
In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
used by other hardware.
So I tend to use DMA directly, not through DMA channel.
Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
use i2c->dev here. (Reference i2c-at91.c).

> > +	/* flush before sending start */
> > +	mb();
> > +	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
> 
> Is mb() really needed when you use writel after that?
> 
mb() should be removed here.

> > +	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
> > +		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
> > +		mtk_i2c_init_hw(i2c);
> > +		return -EREMOTEIO;
> 
> -ENXIO. Please check Documentation/i2c/fault-codes for a reference and
> check all your error values.
> 
OK, I will check return values.

> > +	ret = of_property_read_u32(np, "clock-div", clk_src_div);
> > +	if (ret < 0)
> > +		return ret;
> 
> Do we need a property for that in the i2c-block? Can't the clock
> provider driver deliver a properly divided clock already?
> 
Actually, the clock divider implement in I2C controller self.
Clock provider don't have such knowledge to know the divider. The
divider may not be the same in different chip, this is why we put
"clock-div" in device tree. 

> 
> And cppcheck says:
> 
> drivers/i2c/busses/i2c-mt65xx.c:133: style: struct or union member 'mtk_i2c_data::clk_frequency' is never used.
> drivers/i2c/busses/i2c-mt65xx.c:135: style: struct or union member 'mtk_i2c_data::clk_src_div' is never used.
> 
OK, I will remove them.

Thanks your review.
Eddie

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  5:58       ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-18  5:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Wolfram,

Narrow down CC-list.
Please see my reply below.

On Tue, 2015-05-12 at 14:58 +0200, wsa at the-dreams.de wrote:
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/slab.h>
> > +#include <linux/i2c.h>
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/sched.h>
> > +#include <linux/delay.h>
> > +#include <linux/errno.h>
> > +#include <linux/err.h>
> > +#include <linux/device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/mm.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/scatterlist.h>
> > +#include <linux/io.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/clk.h>
> > +#include <linux/completion.h>
> 
> Please sort the includes to avoid duplicates.
OK, will fix it.

> 
> > +struct mtk_i2c_compatible {
> > +	const struct i2c_adapter_quirks *quirks;
> > +	unsigned char pmic_i2c;
> > +	unsigned char dcm;
> > +};
> 
> I wonder if the unsigned char options can be bits in a flags variable?

OK, will fix it.

> 
> > +static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
> > +	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
> > +	.max_num_msgs = MAX_MSG_NUM_MT6577,
> > +	.max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
> > +	.max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
> > +};
> 
> I would think plain numbers are much more readable than defines here.
> They are used only once, too.
> 
OK, will fix it.

> > +static const struct of_device_id mtk_i2c_of_match[] = {
> > +	{ .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
> > +	{ .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
> > +	{}
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
> 
> No need for casts.
> 
OK, will fix it.

> > +static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
> > +{
> > +	writew(value, i2c->base + offset);
> > +}
> > +
> > +static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
> > +{
> > +	return readw(i2c->base + offset);
> > +}
> 
> I am not a big fan of such extremly thin wrappers, but if you like them...
> 
OK, will fix it.

> > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > +						msgs->len, DMA_FROM_DEVICE);
> 
> I think you shouldn't use the adapter device here and later, but the dma
> channel device.
> 
In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
used by other hardware.
So I tend to use DMA directly, not through DMA channel.
Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
use i2c->dev here. (Reference i2c-at91.c).

> > +	/* flush before sending start */
> > +	mb();
> > +	mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
> 
> Is mb() really needed when you use writel after that?
> 
mb() should be removed here.

> > +	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
> > +		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
> > +		mtk_i2c_init_hw(i2c);
> > +		return -EREMOTEIO;
> 
> -ENXIO. Please check Documentation/i2c/fault-codes for a reference and
> check all your error values.
> 
OK, I will check return values.

> > +	ret = of_property_read_u32(np, "clock-div", clk_src_div);
> > +	if (ret < 0)
> > +		return ret;
> 
> Do we need a property for that in the i2c-block? Can't the clock
> provider driver deliver a properly divided clock already?
> 
Actually, the clock divider implement in I2C controller self.
Clock provider don't have such knowledge to know the divider. The
divider may not be the same in different chip, this is why we put
"clock-div" in device tree. 

> 
> And cppcheck says:
> 
> drivers/i2c/busses/i2c-mt65xx.c:133: style: struct or union member 'mtk_i2c_data::clk_frequency' is never used.
> drivers/i2c/busses/i2c-mt65xx.c:135: style: struct or union member 'mtk_i2c_data::clk_src_div' is never used.
> 
OK, I will remove them.

Thanks your review.
Eddie

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
  2015-05-18  5:58       ` Eddie Huang
  (?)
@ 2015-05-18  6:37         ` Wolfram Sang
  -1 siblings, 0 replies; 48+ messages in thread
From: Wolfram Sang @ 2015-05-18  6:37 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek

[-- Attachment #1: Type: text/plain, Size: 826 bytes --]

> > > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > > +						msgs->len, DMA_FROM_DEVICE);
> > 
> > I think you shouldn't use the adapter device here and later, but the dma
> > channel device.
> > 
> In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
> used by other hardware.
> So I tend to use DMA directly, not through DMA channel.
> Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
> use i2c->dev here. (Reference i2c-at91.c).

The better reference would be i2c-sh_mobile.c, especially commit
8cfcae9f0595bf0d145a67cfaa1051804a301d7c ("i2c: sh_mobile: use proper
device for mapping DMA memory") ;) The request to use the DMA channel
device came from the DMA folks, so if there is no real reason for an
exception, please use the channel device.


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  6:37         ` Wolfram Sang
  0 siblings, 0 replies; 48+ messages in thread
From: Wolfram Sang @ 2015-05-18  6:37 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Xudong Chen, Liguo Zhang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

[-- Attachment #1: Type: text/plain, Size: 826 bytes --]

> > > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > > +						msgs->len, DMA_FROM_DEVICE);
> > 
> > I think you shouldn't use the adapter device here and later, but the dma
> > channel device.
> > 
> In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
> used by other hardware.
> So I tend to use DMA directly, not through DMA channel.
> Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
> use i2c->dev here. (Reference i2c-at91.c).

The better reference would be i2c-sh_mobile.c, especially commit
8cfcae9f0595bf0d145a67cfaa1051804a301d7c ("i2c: sh_mobile: use proper
device for mapping DMA memory") ;) The request to use the DMA channel
device came from the DMA folks, so if there is no real reason for an
exception, please use the channel device.


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  6:37         ` Wolfram Sang
  0 siblings, 0 replies; 48+ messages in thread
From: Wolfram Sang @ 2015-05-18  6:37 UTC (permalink / raw)
  To: linux-arm-kernel

> > > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > > +						msgs->len, DMA_FROM_DEVICE);
> > 
> > I think you shouldn't use the adapter device here and later, but the dma
> > channel device.
> > 
> In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
> used by other hardware.
> So I tend to use DMA directly, not through DMA channel.
> Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
> use i2c->dev here. (Reference i2c-at91.c).

The better reference would be i2c-sh_mobile.c, especially commit
8cfcae9f0595bf0d145a67cfaa1051804a301d7c ("i2c: sh_mobile: use proper
device for mapping DMA memory") ;) The request to use the DMA channel
device came from the DMA folks, so if there is no real reason for an
exception, please use the channel device.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150518/2d5b42dc/attachment.sig>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
  2015-05-18  6:37         ` Wolfram Sang
  (?)
@ 2015-05-18  7:42           ` Eddie Huang
  -1 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-18  7:42 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Sascha Hauer, srv_heupstream, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek

Hi Wolfram,

On Mon, 2015-05-18 at 08:37 +0200, Wolfram Sang wrote:
> > > > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > > > +						msgs->len, DMA_FROM_DEVICE);
> > > 
> > > I think you shouldn't use the adapter device here and later, but the dma
> > > channel device.
> > > 
> > In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
> > used by other hardware.
> > So I tend to use DMA directly, not through DMA channel.
> > Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
> > use i2c->dev here. (Reference i2c-at91.c).
> 
> The better reference would be i2c-sh_mobile.c, especially commit
> 8cfcae9f0595bf0d145a67cfaa1051804a301d7c ("i2c: sh_mobile: use proper
> device for mapping DMA memory") ;) The request to use the DMA channel
> device came from the DMA folks, so if there is no real reason for an
> exception, please use the channel device.
> 

sh_mobile already implement dmaengine, so its I2C driver can use dma
channel.
But Mediatek SoC don't have "generic" DMA engine, Each DMA belong to
specific hardware, so dmaengine is not necessary, and not suitable for
our I2C controller.In other words, dma dev can be considered as part of
I2C controller dev.

Eddie



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  7:42           ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-18  7:42 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Sascha Hauer, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Xudong Chen, Liguo Zhang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Wolfram,

On Mon, 2015-05-18 at 08:37 +0200, Wolfram Sang wrote:
> > > > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > > > +						msgs->len, DMA_FROM_DEVICE);
> > > 
> > > I think you shouldn't use the adapter device here and later, but the dma
> > > channel device.
> > > 
> > In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
> > used by other hardware.
> > So I tend to use DMA directly, not through DMA channel.
> > Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
> > use i2c->dev here. (Reference i2c-at91.c).
> 
> The better reference would be i2c-sh_mobile.c, especially commit
> 8cfcae9f0595bf0d145a67cfaa1051804a301d7c ("i2c: sh_mobile: use proper
> device for mapping DMA memory") ;) The request to use the DMA channel
> device came from the DMA folks, so if there is no real reason for an
> exception, please use the channel device.
> 

sh_mobile already implement dmaengine, so its I2C driver can use dma
channel.
But Mediatek SoC don't have "generic" DMA engine, Each DMA belong to
specific hardware, so dmaengine is not necessary, and not suitable for
our I2C controller.In other words, dma dev can be considered as part of
I2C controller dev.

Eddie

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  7:42           ` Eddie Huang
  0 siblings, 0 replies; 48+ messages in thread
From: Eddie Huang @ 2015-05-18  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Wolfram,

On Mon, 2015-05-18 at 08:37 +0200, Wolfram Sang wrote:
> > > > +		rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
> > > > +						msgs->len, DMA_FROM_DEVICE);
> > > 
> > > I think you shouldn't use the adapter device here and later, but the dma
> > > channel device.
> > > 
> > In MTK SoC, each I2C controller has its own DMA, and this DMA can't be
> > used by other hardware.
> > So I tend to use DMA directly, not through DMA channel.
> > Even so, "i2c->adap.dev.parent" is not suitable here. I will change to
> > use i2c->dev here. (Reference i2c-at91.c).
> 
> The better reference would be i2c-sh_mobile.c, especially commit
> 8cfcae9f0595bf0d145a67cfaa1051804a301d7c ("i2c: sh_mobile: use proper
> device for mapping DMA memory") ;) The request to use the DMA channel
> device came from the DMA folks, so if there is no real reason for an
> exception, please use the channel device.
> 

sh_mobile already implement dmaengine, so its I2C driver can use dma
channel.
But Mediatek SoC don't have "generic" DMA engine, Each DMA belong to
specific hardware, so dmaengine is not necessary, and not suitable for
our I2C controller.In other words, dma dev can be considered as part of
I2C controller dev.

Eddie

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
  2015-05-18  7:42           ` Eddie Huang
  (?)
@ 2015-05-18  9:05             ` Wolfram Sang
  -1 siblings, 0 replies; 48+ messages in thread
From: Wolfram Sang @ 2015-05-18  9:05 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Matthias Brugger,
	Xudong Chen, Liguo Zhang, linux-i2c, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek

[-- Attachment #1: Type: text/plain, Size: 87 bytes --]

> sh_mobile already implement dmaengine, so its I2C driver can use dma
> channel.

OK.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  9:05             ` Wolfram Sang
  0 siblings, 0 replies; 48+ messages in thread
From: Wolfram Sang @ 2015-05-18  9:05 UTC (permalink / raw)
  To: Eddie Huang
  Cc: Sascha Hauer, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Matthias Brugger, Xudong Chen, Liguo Zhang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

[-- Attachment #1: Type: text/plain, Size: 87 bytes --]

> sh_mobile already implement dmaengine, so its I2C driver can use dma
> channel.

OK.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
@ 2015-05-18  9:05             ` Wolfram Sang
  0 siblings, 0 replies; 48+ messages in thread
From: Wolfram Sang @ 2015-05-18  9:05 UTC (permalink / raw)
  To: linux-arm-kernel

> sh_mobile already implement dmaengine, so its I2C driver can use dma
> channel.

OK.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150518/bd0d12ed/attachment.sig>

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2015-05-18  9:05 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-06  8:37 [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C Eddie Huang
2015-05-06  8:37 ` Eddie Huang
2015-05-06  8:37 ` Eddie Huang
2015-05-06  8:37 ` [PATCH v7 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx Eddie Huang
2015-05-06  8:37   ` Eddie Huang
2015-05-06  8:37   ` Eddie Huang
2015-05-12 12:37   ` wsa
2015-05-12 12:37     ` wsa at the-dreams.de
2015-05-12 12:37     ` wsa-z923LK4zBo2bacvFa/9K2g
2015-05-12 12:45     ` Sascha Hauer
2015-05-12 12:45       ` Sascha Hauer
2015-05-12 12:45       ` Sascha Hauer
2015-05-06  8:37 ` [PATCH v7 2/3] I2C: mediatek: Add driver for MediaTek I2C controller Eddie Huang
2015-05-06  8:37   ` Eddie Huang
2015-05-06  8:37   ` Eddie Huang
2015-05-12 12:58   ` wsa
2015-05-12 12:58     ` wsa at the-dreams.de
2015-05-12 12:58     ` wsa-z923LK4zBo2bacvFa/9K2g
2015-05-18  5:58     ` Eddie Huang
2015-05-18  5:58       ` Eddie Huang
2015-05-18  5:58       ` Eddie Huang
2015-05-18  6:37       ` Wolfram Sang
2015-05-18  6:37         ` Wolfram Sang
2015-05-18  6:37         ` Wolfram Sang
2015-05-18  7:42         ` Eddie Huang
2015-05-18  7:42           ` Eddie Huang
2015-05-18  7:42           ` Eddie Huang
2015-05-18  9:05           ` Wolfram Sang
2015-05-18  9:05             ` Wolfram Sang
2015-05-18  9:05             ` Wolfram Sang
2015-05-06  8:37 ` [PATCH v7 3/3] I2C: mediatek: Add driver for MediaTek MT8173 " Eddie Huang
2015-05-06  8:37   ` Eddie Huang
2015-05-06  8:37   ` Eddie Huang
2015-05-12 13:00   ` wsa
2015-05-12 13:00     ` wsa at the-dreams.de
2015-05-12 13:00     ` wsa-z923LK4zBo2bacvFa/9K2g
2015-05-07  7:39 ` [PATCH v7 0/3] ARM: mediatek: Add driver for Mediatek I2C Lee Jones
2015-05-07  7:39   ` Lee Jones
2015-05-07  7:39   ` Lee Jones
2015-05-07  7:54   ` Eddie Huang
2015-05-07  7:54     ` Eddie Huang
2015-05-07  7:54     ` Eddie Huang
2015-05-07  8:27     ` Lee Jones
2015-05-07  8:27       ` Lee Jones
2015-05-07  8:27       ` Lee Jones
2015-05-12 12:45 ` Sascha Hauer
2015-05-12 12:45   ` Sascha Hauer
2015-05-12 12:45   ` Sascha Hauer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.