diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch | 1148 |
1 files changed, 1148 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch new file mode 100644 index 000000000..fbf422a35 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch @@ -0,0 +1,1148 @@ +From b8d7d0f3513abdf014345b240a79d23c63409c4c Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +Date: Tue, 11 Jun 2019 15:07:08 -0700 +Subject: [PATCH] i2c: aspeed: add buffer mode transfer support + +Byte mode currently this driver uses makes lots of interrupt call +which isn't good for performance and it makes the driver very +timing sensitive. To improve performance of the driver, this commit +adds buffer mode transfer support which uses I2C SRAM buffer +instead of using a single byte buffer. + +AST2400: +It has 2 KBytes (256 Bytes x 8 pages) of I2C SRAM buffer pool from +0x1e78a800 to 0x1e78afff that can be used for all busses with +buffer pool manipulation. To simplify implementation for supporting +both AST2400 and AST2500, it assigns each 128 Bytes per bus without +using buffer pool manipulation so total 1792 Bytes of I2C SRAM +buffer will be used. + +AST2500: +It has 16 Bytes of individual I2C SRAM buffer per each bus and its +range is from 0x1e78a200 to 0x1e78a2df, so it doesn't have 'buffer +page selection' bit field in the Function control register, and +neither 'base address pointer' bit field in the Pool buffer control +register it has. To simplify implementation for supporting both +AST2400 and AST2500, it writes zeros on those register bit fields +but it's okay because it does nothing in AST2500. + +It provides buffer based master and slave data transfer. + +Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +--- + .../devicetree/bindings/i2c/i2c-aspeed.txt | 40 ++- + arch/arm/boot/dts/aspeed-g4.dtsi | 47 +-- + arch/arm/boot/dts/aspeed-g5.dtsi | 47 +-- + arch/arm/boot/dts/aspeed-g6.dtsi | 32 +- + drivers/i2c/busses/i2c-aspeed.c | 376 +++++++++++++++++++-- + 5 files changed, 451 insertions(+), 91 deletions(-) + +diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt +index 7da7e813b2b0..0ff3539cee95 100644 +--- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt ++++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt +@@ -3,7 +3,10 @@ Device tree configuration for the I2C busses on the AST24XX and AST25XX SoCs. + Required Properties: + - #address-cells : should be 1 + - #size-cells : should be 0 +-- reg : address offset and range of bus ++- reg : Address offset and range of bus registers. ++ An additional SRAM buffer address offset and range is ++ optional in case of enabling I2C dedicated SRAM for ++ buffer mode transfer support. + - compatible : should be "aspeed,ast2400-i2c-bus" + or "aspeed,ast2500-i2c-bus" + - clocks : root clock of bus, should reference the APB +@@ -28,12 +31,21 @@ i2c { + #size-cells = <1>; + ranges = <0 0x1e78a000 0x1000>; + +- i2c_ic: interrupt-controller@0 { +- #interrupt-cells = <1>; +- compatible = "aspeed,ast2400-i2c-ic"; ++ i2c_gr: i2c-global-regs@0 { ++ compatible = "aspeed,ast2500-i2c-gr", "syscon"; + reg = <0x0 0x40>; +- interrupts = <12>; +- interrupt-controller; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x0 0x40>; ++ ++ i2c_ic: interrupt-controller@0 { ++ #interrupt-cells = <1>; ++ compatible = "aspeed,ast2500-i2c-ic"; ++ reg = <0x0 0x4>; ++ interrupts = <12>; ++ interrupt-controller; ++ }; + }; + + i2c0: i2c-bus@40 { +@@ -41,11 +53,25 @@ i2c { + #size-cells = <0>; + #interrupt-cells = <1>; + reg = <0x40 0x40>; +- compatible = "aspeed,ast2400-i2c-bus"; ++ compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; + bus-frequency = <100000>; + interrupts = <0>; + interrupt-parent = <&i2c_ic>; + }; ++ ++ /* buffer mode transfer enabled */ ++ i2c1: i2c-bus@80 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #interrupt-cells = <1>; ++ reg = <0x80 0x40>, <0x210 0x10>; ++ compatible = "aspeed,ast2500-i2c-bus"; ++ clocks = <&syscon ASPEED_CLK_APB>; ++ resets = <&syscon ASPEED_RESET_I2C>; ++ bus-frequency = <100000>; ++ interrupts = <1>; ++ interrupt-parent = <&i2c_ic>; ++ }; + }; +diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi +index fc6f4e009db7..0b30c8546e64 100644 +--- a/arch/arm/boot/dts/aspeed-g4.dtsi ++++ b/arch/arm/boot/dts/aspeed-g4.dtsi +@@ -518,12 +518,21 @@ + }; + + &i2c { +- i2c_ic: interrupt-controller@0 { +- #interrupt-cells = <1>; +- compatible = "aspeed,ast2400-i2c-ic"; ++ i2c_gr: i2c-global-regs@0 { ++ compatible = "aspeed,ast2400-i2c-gr", "syscon"; + reg = <0x0 0x40>; +- interrupts = <12>; +- interrupt-controller; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x0 0x40>; ++ ++ i2c_ic: interrupt-controller@0 { ++ #interrupt-cells = <1>; ++ compatible = "aspeed,ast2400-i2c-ic"; ++ reg = <0x0 0x4>; ++ interrupts = <12>; ++ interrupt-controller; ++ }; + }; + + i2c0: i2c-bus@40 { +@@ -531,7 +540,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x40 0x40>; ++ reg = <0x40 0x40>, <0x800 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -547,7 +556,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x80 0x40>; ++ reg = <0x80 0x40>, <0x880 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -563,7 +572,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0xc0 0x40>; ++ reg = <0xc0 0x40>, <0x900 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -580,7 +589,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x100 0x40>; ++ reg = <0x100 0x40>, <0x980 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -597,7 +606,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x140 0x40>; ++ reg = <0x140 0x40>, <0xa00 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -614,7 +623,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x180 0x40>; ++ reg = <0x180 0x40>, <0xa80 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -631,7 +640,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x1c0 0x40>; ++ reg = <0x1c0 0x40>, <0xb00 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -648,7 +657,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x300 0x40>; ++ reg = <0x300 0x40>, <0xb80 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -665,7 +674,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x340 0x40>; ++ reg = <0x340 0x40>, <0xc00 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -682,7 +691,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x380 0x40>; ++ reg = <0x380 0x40>, <0xc80 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -699,7 +708,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x3c0 0x40>; ++ reg = <0x3c0 0x40>, <0xd00 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -716,7 +725,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x400 0x40>; ++ reg = <0x400 0x40>, <0xd80 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -733,7 +742,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x440 0x40>; ++ reg = <0x440 0x40>, <0xe00 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -750,7 +759,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x480 0x40>; ++ reg = <0x480 0x40>, <0xe80 0x80>; + compatible = "aspeed,ast2400-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi +index eb1f9c9d9cca..51593a0a8a23 100644 +--- a/arch/arm/boot/dts/aspeed-g5.dtsi ++++ b/arch/arm/boot/dts/aspeed-g5.dtsi +@@ -615,12 +615,21 @@ + }; + + &i2c { +- i2c_ic: interrupt-controller@0 { +- #interrupt-cells = <1>; +- compatible = "aspeed,ast2500-i2c-ic"; ++ i2c_gr: i2c-global-regs@0 { ++ compatible = "aspeed,ast2500-i2c-gr", "syscon"; + reg = <0x0 0x40>; +- interrupts = <12>; +- interrupt-controller; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x0 0x40>; ++ ++ i2c_ic: interrupt-controller@0 { ++ #interrupt-cells = <1>; ++ compatible = "aspeed,ast2500-i2c-ic"; ++ reg = <0x0 0x4>; ++ interrupts = <12>; ++ interrupt-controller; ++ }; + }; + + i2c0: i2c-bus@40 { +@@ -628,7 +637,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x40 0x40>; ++ reg = <0x40 0x40>, <0x200 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -644,7 +653,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x80 0x40>; ++ reg = <0x80 0x40>, <0x210 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -660,7 +669,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0xc0 0x40>; ++ reg = <0xc0 0x40>, <0x220 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -677,7 +686,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x100 0x40>; ++ reg = <0x100 0x40>, <0x230 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -694,7 +703,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x140 0x40>; ++ reg = <0x140 0x40>, <0x240 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -711,7 +720,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x180 0x40>; ++ reg = <0x180 0x40>, <0x250 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -728,7 +737,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x1c0 0x40>; ++ reg = <0x1c0 0x40>, <0x260 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -745,7 +754,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x300 0x40>; ++ reg = <0x300 0x40>, <0x270 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -762,7 +771,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x340 0x40>; ++ reg = <0x340 0x40>, <0x280 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -779,7 +788,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x380 0x40>; ++ reg = <0x380 0x40>, <0x290 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -796,7 +805,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x3c0 0x40>; ++ reg = <0x3c0 0x40>, <0x2a0 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -813,7 +822,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x400 0x40>; ++ reg = <0x400 0x40>, <0x2b0 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -830,7 +839,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x440 0x40>; ++ reg = <0x440 0x40>, <0x2c0 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -847,7 +856,7 @@ + #size-cells = <0>; + #interrupt-cells = <1>; + +- reg = <0x480 0x40>; ++ reg = <0x480 0x40>, <0x2d0 0x10>; + compatible = "aspeed,ast2500-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB>; + resets = <&syscon ASPEED_RESET_I2C>; +diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi +index f92a2aa999d1..3ef312543269 100644 +--- a/arch/arm/boot/dts/aspeed-g6.dtsi ++++ b/arch/arm/boot/dts/aspeed-g6.dtsi +@@ -712,7 +712,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x80 0x80>; ++ reg = <0x80 0x80>, <0xc00 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -727,7 +727,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x100 0x80>; ++ reg = <0x100 0x80>, <0xc20 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -742,7 +742,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x180 0x80>; ++ reg = <0x180 0x80>, <0xc40 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -757,7 +757,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x200 0x80>; ++ reg = <0x200 0x80>, <0xc60 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -772,7 +772,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x280 0x80>; ++ reg = <0x280 0x80>, <0xc80 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -787,7 +787,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x300 0x80>; ++ reg = <0x300 0x80>, <0xca0 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -802,7 +802,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x380 0x80>; ++ reg = <0x380 0x80>, <0xcc0 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -817,7 +817,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x400 0x80>; ++ reg = <0x400 0x80>, <0xce0 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -832,7 +832,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x480 0x80>; ++ reg = <0x480 0x80>, <0xd00 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -847,7 +847,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x500 0x80>; ++ reg = <0x500 0x80>, <0xd20 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -862,7 +862,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x580 0x80>; ++ reg = <0x580 0x80>, <0xd40 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -877,7 +877,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x600 0x80>; ++ reg = <0x600 0x80>, <0xd60 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -892,7 +892,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x680 0x80>; ++ reg = <0x680 0x80>, <0xd80 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -907,7 +907,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x700 0x80>; ++ reg = <0x700 0x80>, <0xda0 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -922,7 +922,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x780 0x80>; ++ reg = <0x780 0x80>, <0xdc0 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +@@ -937,7 +937,7 @@ + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; +- reg = <0x800 0x80>; ++ reg = <0x800 0x80>, <0xde0 0x20>; + compatible = "aspeed,ast2600-i2c-bus"; + clocks = <&syscon ASPEED_CLK_APB2>; + resets = <&syscon ASPEED_RESET_I2C>; +diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c +index 7becfcd67142..bf72e151d11f 100644 +--- a/drivers/i2c/busses/i2c-aspeed.c ++++ b/drivers/i2c/busses/i2c-aspeed.c +@@ -7,6 +7,7 @@ + * Copyright 2017 Google, Inc. + */ + ++#include <linux/bitfield.h> + #include <linux/clk.h> + #include <linux/completion.h> + #include <linux/err.h> +@@ -19,15 +20,24 @@ + #include <linux/irqchip/chained_irq.h> + #include <linux/irqdomain.h> + #include <linux/kernel.h> ++#include <linux/mfd/syscon.h> + #include <linux/module.h> + #include <linux/of_address.h> + #include <linux/of_irq.h> + #include <linux/of_platform.h> + #include <linux/platform_device.h> ++#include <linux/regmap.h> + #include <linux/reset.h> + #include <linux/slab.h> + +-/* I2C Register */ ++/* I2C Global Registers */ ++/* 0x00 : I2CG Interrupt Status Register */ ++/* 0x08 : I2CG Interrupt Target Assignment */ ++/* 0x0c : I2CG Global Control Register (AST2500) */ ++#define ASPEED_I2CG_GLOBAL_CTRL_REG 0x0c ++#define ASPEED_I2CG_SRAM_BUFFER_EN BIT(0) ++ ++/* I2C Bus Registers */ + #define ASPEED_I2C_FUN_CTRL_REG 0x00 + #define ASPEED_I2C_AC_TIMING_REG1 0x04 + #define ASPEED_I2C_AC_TIMING_REG2 0x08 +@@ -35,14 +45,12 @@ + #define ASPEED_I2C_INTR_STS_REG 0x10 + #define ASPEED_I2C_CMD_REG 0x14 + #define ASPEED_I2C_DEV_ADDR_REG 0x18 ++#define ASPEED_I2C_BUF_CTRL_REG 0x1c + #define ASPEED_I2C_BYTE_BUF_REG 0x20 + +-/* Global Register Definition */ +-/* 0x00 : I2C Interrupt Status Register */ +-/* 0x08 : I2C Interrupt Target Assignment */ +- + /* Device Register Definition */ + /* 0x00 : I2CD Function Control Register */ ++#define ASPEED_I2CD_BUFFER_PAGE_SEL_MASK GENMASK(22, 20) + #define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15) + #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8) + #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7) +@@ -102,6 +110,8 @@ + #define ASPEED_I2CD_BUS_RECOVER_CMD BIT(11) + + /* Command Bit */ ++#define ASPEED_I2CD_RX_BUFF_ENABLE BIT(7) ++#define ASPEED_I2CD_TX_BUFF_ENABLE BIT(6) + #define ASPEED_I2CD_M_STOP_CMD BIT(5) + #define ASPEED_I2CD_M_S_RX_CMD_LAST BIT(4) + #define ASPEED_I2CD_M_RX_CMD BIT(3) +@@ -118,6 +128,13 @@ + /* 0x18 : I2CD Slave Device Address Register */ + #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0) + ++/* 0x1c : I2CD Buffer Control Register */ ++/* Use 8-bits or 6-bits wide bit fileds to support both AST2400 and AST2500 */ ++#define ASPEED_I2CD_BUF_RX_COUNT_MASK GENMASK(31, 24) ++#define ASPEED_I2CD_BUF_RX_SIZE_MASK GENMASK(23, 16) ++#define ASPEED_I2CD_BUF_TX_COUNT_MASK GENMASK(15, 8) ++#define ASPEED_I2CD_BUF_OFFSET_MASK GENMASK(5, 0) ++ + enum aspeed_i2c_master_state { + ASPEED_I2C_MASTER_INACTIVE, + ASPEED_I2C_MASTER_PENDING, +@@ -163,6 +180,11 @@ struct aspeed_i2c_bus { + int master_xfer_result; + /* Multi-master */ + bool multi_master; ++ /* Buffer mode */ ++ void __iomem *buf_base; ++ u8 buf_offset; ++ u8 buf_page; ++ size_t buf_size; + #if IS_ENABLED(CONFIG_I2C_SLAVE) + struct i2c_client *slave; + enum aspeed_i2c_slave_state slave_state; +@@ -255,6 +277,77 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) + } + + #if IS_ENABLED(CONFIG_I2C_SLAVE) ++static inline void ++aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status, ++ u8 *value) ++{ ++ if (bus->buf_base && ++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && ++ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) ++ *value = readb(bus->buf_base); ++ else ++ *value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; ++} ++ ++static inline void ++aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status, ++ u8 *value) ++{ ++ int i, len; ++ ++ if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && ++ irq_status & ASPEED_I2CD_INTR_RX_DONE) { ++ if (bus->buf_base) { ++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, ++ readl(bus->base + ++ ASPEED_I2C_BUF_CTRL_REG)); ++ for (i = 0; i < len; i++) { ++ *value = readb(bus->buf_base + i); ++ i2c_slave_event(bus->slave, ++ I2C_SLAVE_WRITE_RECEIVED, ++ value); ++ } ++ } ++ } ++} ++ ++static inline void ++aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value) ++{ ++ if (bus->buf_base) { ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, ++ bus->buf_size - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, ++ bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ writel(ASPEED_I2CD_RX_BUFF_ENABLE, ++ bus->base + ASPEED_I2C_CMD_REG); ++ } ++} ++ ++static inline void ++aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value) ++{ ++ int i, len; ++ ++ if (bus->buf_base) { ++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, ++ readl(bus->base + ++ ASPEED_I2C_BUF_CTRL_REG)); ++ for (i = 1; i < len; i++) { ++ *value = readb(bus->buf_base + i); ++ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED, ++ value); ++ } ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, ++ bus->buf_size - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ writel(ASPEED_I2CD_RX_BUFF_ENABLE, ++ bus->base + ASPEED_I2C_CMD_REG); ++ } ++} ++ + static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + { + u32 command, irq_handled = 0; +@@ -281,7 +374,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + + /* Slave was sent something. */ + if (irq_status & ASPEED_I2CD_INTR_RX_DONE) { +- value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; ++ aspeed_i2c_slave_handle_rx_done(bus, irq_status, &value); + /* Handle address frame. */ + if (bus->slave_state == ASPEED_I2C_SLAVE_START) { + if (value & 0x1) +@@ -296,9 +389,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + + /* Slave was asked to stop. */ + if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) { ++ aspeed_i2c_slave_handle_normal_stop(bus, irq_status, &value); + irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP; + bus->slave_state = ASPEED_I2C_SLAVE_STOP; + } ++ + if (irq_status & ASPEED_I2CD_INTR_TX_NAK && + bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) { + irq_handled |= ASPEED_I2CD_INTR_TX_NAK; +@@ -328,9 +423,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + case ASPEED_I2C_SLAVE_WRITE_REQUESTED: + bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED; + i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); ++ aspeed_i2c_slave_handle_write_requested(bus, &value); + break; + case ASPEED_I2C_SLAVE_WRITE_RECEIVED: + i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value); ++ aspeed_i2c_slave_handle_write_received(bus, &value); + break; + case ASPEED_I2C_SLAVE_STOP: + i2c_slave_event(slave, I2C_SLAVE_STOP, &value); +@@ -350,12 +447,76 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + } + #endif /* CONFIG_I2C_SLAVE */ + ++static inline u32 ++aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) ++{ ++ u32 command = 0; ++ int len; ++ ++ if (msg->len > bus->buf_size) { ++ len = bus->buf_size; ++ } else { ++ len = msg->len; ++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; ++ } ++ ++ if (bus->buf_base) { ++ command |= ASPEED_I2CD_RX_BUFF_ENABLE; ++ ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ } ++ ++ return command; ++} ++ ++static inline u32 ++aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) ++{ ++ u8 slave_addr = i2c_8bit_addr_from_msg(msg); ++ u32 command = 0; ++ int len; ++ ++ if (msg->len + 1 > bus->buf_size) ++ len = bus->buf_size; ++ else ++ len = msg->len + 1; ++ ++ if (bus->buf_base) { ++ u8 wbuf[4]; ++ int i; ++ ++ command |= ASPEED_I2CD_TX_BUFF_ENABLE; ++ ++ /* ++ * Yeah, it looks bad but byte writing on remapped I2C SRAM ++ * causes corruption so use this way to make dword writings. ++ */ ++ wbuf[0] = slave_addr; ++ for (i = 1; i < len; i++) { ++ wbuf[i % 4] = msg->buf[i - 1]; ++ if (i % 4 == 3) ++ writel(*(u32 *)wbuf, bus->buf_base + i - 3); ++ } ++ if (--i % 4 != 3) ++ writel(*(u32 *)wbuf, bus->buf_base + i - (i % 4)); ++ ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, len - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ } ++ ++ bus->buf_index = len - 1; ++ ++ return command; ++} ++ + /* precondition: bus.lock has been acquired. */ + static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) + { + u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD; + struct i2c_msg *msg = &bus->msgs[bus->msgs_index]; +- u8 slave_addr = i2c_8bit_addr_from_msg(msg); + + #if IS_ENABLED(CONFIG_I2C_SLAVE) + /* +@@ -374,12 +535,21 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) + + if (msg->flags & I2C_M_RD) { + command |= ASPEED_I2CD_M_RX_CMD; +- /* Need to let the hardware know to NACK after RX. */ +- if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN)) +- command |= ASPEED_I2CD_M_S_RX_CMD_LAST; ++ if (!(msg->flags & I2C_M_RECV_LEN)) { ++ if (msg->len && bus->buf_base) ++ command |= aspeed_i2c_prepare_rx_buf(bus, msg); ++ ++ /* Need to let the hardware know to NACK after RX. */ ++ if (msg->len <= 1) ++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; ++ } ++ } else if (msg->len && bus->buf_base) { ++ command |= aspeed_i2c_prepare_tx_buf(bus, msg); + } + +- writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG); ++ if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE)) ++ writel(i2c_8bit_addr_from_msg(msg), ++ bus->base + ASPEED_I2C_BYTE_BUF_REG); + writel(command, bus->base + ASPEED_I2C_CMD_REG); + } + +@@ -414,6 +584,104 @@ static int aspeed_i2c_is_irq_error(u32 irq_status) + return 0; + } + ++static inline u32 ++aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus, ++ struct i2c_msg *msg) ++{ ++ u32 command = 0; ++ ++ if (bus->buf_base) { ++ u8 wbuf[4]; ++ int len; ++ int i; ++ ++ if (msg->len - bus->buf_index > bus->buf_size) ++ len = bus->buf_size; ++ else ++ len = msg->len - bus->buf_index; ++ ++ ++ command |= ASPEED_I2CD_TX_BUFF_ENABLE; ++ ++ if (msg->len - bus->buf_index > bus->buf_size) ++ len = bus->buf_size; ++ else ++ len = msg->len - bus->buf_index; ++ ++ for (i = 0; i < len; i++) { ++ wbuf[i % 4] = msg->buf[bus->buf_index + i]; ++ if (i % 4 == 3) ++ writel(*(u32 *)wbuf, ++ bus->buf_base + i - 3); ++ } ++ if (--i % 4 != 3) ++ writel(*(u32 *)wbuf, ++ bus->buf_base + i - (i % 4)); ++ ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, ++ len - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, ++ bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ ++ bus->buf_index += len; ++ } else { ++ writel(msg->buf[bus->buf_index++], ++ bus->base + ASPEED_I2C_BYTE_BUF_REG); ++ } ++ ++ return command; ++} ++ ++static inline void ++aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) ++{ ++ u8 recv_byte; ++ int len; ++ ++ if (bus->buf_base) { ++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, ++ readl(bus->base + ASPEED_I2C_BUF_CTRL_REG)); ++ memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len); ++ bus->buf_index += len; ++ } else { ++ recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; ++ msg->buf[bus->buf_index++] = recv_byte; ++ } ++} ++ ++static inline u32 ++aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus, ++ struct i2c_msg *msg) ++{ ++ u32 command = 0; ++ ++ if (bus->buf_base) { ++ int len; ++ ++ if (msg->len - bus->buf_index > bus->buf_size) { ++ len = bus->buf_size; ++ } else { ++ len = msg->len - bus->buf_index; ++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; ++ } ++ ++ command |= ASPEED_I2CD_RX_BUFF_ENABLE; ++ ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, ++ len - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, ++ bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ } else { ++ if (bus->buf_index + 1 == msg->len) ++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; ++ } ++ ++ return command; ++} ++ + static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + { + u32 irq_handled = 0, command = 0; +@@ -522,11 +790,10 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + /* fall through */ + case ASPEED_I2C_MASTER_TX_FIRST: + if (bus->buf_index < msg->len) { ++ command = ASPEED_I2CD_M_TX_CMD; ++ command |= aspeed_i2c_master_handle_tx_first(bus, msg); ++ writel(command, bus->base + ASPEED_I2C_CMD_REG); + bus->master_state = ASPEED_I2C_MASTER_TX; +- writel(msg->buf[bus->buf_index++], +- bus->base + ASPEED_I2C_BYTE_BUF_REG); +- writel(ASPEED_I2CD_M_TX_CMD, +- bus->base + ASPEED_I2C_CMD_REG); + } else { + aspeed_i2c_next_msg_or_stop(bus); + } +@@ -543,26 +810,26 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) + } + irq_handled |= ASPEED_I2CD_INTR_RX_DONE; + +- recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; +- msg->buf[bus->buf_index++] = recv_byte; +- + if (msg->flags & I2C_M_RECV_LEN) { ++ recv_byte = readl(bus->base + ++ ASPEED_I2C_BYTE_BUF_REG) >> 8; + if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) { + bus->cmd_err = -EPROTO; + aspeed_i2c_do_stop(bus); + goto out_no_complete; + } +- msg->len = recv_byte + +- ((msg->flags & I2C_CLIENT_PEC) ? 2 : 1); ++ msg->len = recv_byte + ((msg->flags & I2C_CLIENT_PEC) ? ++ 2 : 1); + msg->flags &= ~I2C_M_RECV_LEN; ++ } else if (msg->len) { ++ aspeed_i2c_master_handle_rx(bus, msg); + } + + if (bus->buf_index < msg->len) { +- bus->master_state = ASPEED_I2C_MASTER_RX; + command = ASPEED_I2CD_M_RX_CMD; +- if (bus->buf_index + 1 == msg->len) +- command |= ASPEED_I2CD_M_S_RX_CMD_LAST; ++ command |= aspeed_i2c_master_handle_rx_next(bus, msg); + writel(command, bus->base + ASPEED_I2C_CMD_REG); ++ bus->master_state = ASPEED_I2C_MASTER_RX; + } else { + aspeed_i2c_next_msg_or_stop(bus); + } +@@ -924,6 +1191,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus, + if (ret < 0) + return ret; + ++ fun_ctrl_reg |= FIELD_PREP(ASPEED_I2CD_BUFFER_PAGE_SEL_MASK, ++ bus->buf_page); ++ + if (of_property_read_bool(pdev->dev.of_node, "multi-master")) + bus->multi_master = true; + else +@@ -964,6 +1234,52 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus) + return ret; + } + ++static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus) ++{ ++ struct platform_device *pdev = to_platform_device(bus->dev); ++ bool sram_enabled = true; ++ int ret; ++ ++ /* ++ * Enable I2C SRAM in case of AST2500. ++ * SRAM is enabled by default in AST2400 and AST2600. ++ */ ++ if (of_device_is_compatible(pdev->dev.of_node, ++ "aspeed,ast2500-i2c-bus")) { ++ struct regmap *gr_regmap = syscon_regmap_lookup_by_compatible("aspeed,ast2500-i2c-gr"); ++ ++ if (IS_ERR(gr_regmap)) ++ ret = PTR_ERR(gr_regmap); ++ else ++ ret = regmap_update_bits(gr_regmap, ++ ASPEED_I2CG_GLOBAL_CTRL_REG, ++ ASPEED_I2CG_SRAM_BUFFER_EN, ++ ASPEED_I2CG_SRAM_BUFFER_EN); ++ ++ if (ret) ++ sram_enabled = false; ++ } ++ ++ if (sram_enabled) { ++ struct resource *res = platform_get_resource(pdev, ++ IORESOURCE_MEM, 1); ++ ++ if (res && resource_size(res) >= 2) ++ bus->buf_base = devm_ioremap_resource(&pdev->dev, res); ++ ++ if (!IS_ERR_OR_NULL(bus->buf_base)) { ++ bus->buf_size = resource_size(res); ++ if (of_device_is_compatible(pdev->dev.of_node, ++ "aspeed,ast2400-i2c-bus")) { ++ bus->buf_page = ((res->start >> 8) & ++ GENMASK(3, 0)) - 8; ++ bus->buf_offset = (res->start >> 2) & ++ ASPEED_I2CD_BUF_OFFSET_MASK; ++ } ++ } ++ } ++} ++ + static const struct of_device_id aspeed_i2c_bus_of_table[] = { + { + .compatible = "aspeed,ast2400-i2c-bus", +@@ -986,18 +1302,18 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) + const struct of_device_id *match; + struct aspeed_i2c_bus *bus; + struct clk *parent_clk; +- struct resource *res; + int irq, ret; + + bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL); + if (!bus) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- bus->base = devm_ioremap_resource(&pdev->dev, res); ++ bus->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(bus->base)) + return PTR_ERR(bus->base); + ++ bus->dev = &pdev->dev; ++ + parent_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(parent_clk)) + return PTR_ERR(parent_clk); +@@ -1028,6 +1344,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) + bus->get_clk_reg_val = (u32 (*)(struct device *, u32)) + match->data; + ++ aspeed_i2c_set_xfer_mode(bus); ++ + /* Initialize the I2C adapter */ + spin_lock_init(&bus->lock); + init_completion(&bus->cmd_complete); +@@ -1038,8 +1356,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) + strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name)); + i2c_set_adapdata(&bus->adap, bus); + +- bus->dev = &pdev->dev; +- + /* Clean up any left over interrupt state. */ + writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG); + writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG); +@@ -1063,8 +1379,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) + + platform_set_drvdata(pdev, bus); + +- dev_info(bus->dev, "i2c bus %d registered, irq %d\n", +- bus->adap.nr, irq); ++ dev_info(bus->dev, "i2c bus %d registered (%s mode), irq %d\n", ++ bus->adap.nr, bus->buf_base ? "buffer" : "byte", irq); + + return 0; + } +-- +2.7.4 + |