Skip to contentSkip to conversation

Aspeed I2C driver, using Driver Model.

PATCH In review [email protected] 4 participants 44 messages Nov 22, 2016 – Nov 27, 2016

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover Aspeed I2C driver, using Driver Model.

From: Maxim Sloyko <[email protected]>

This series of patches is only meant for openbmc/u-boot tree. It adds basic support for aspeed i2c. Only single master mode is supported with synchronous transfer.

The style is inconsistent with U-Boot style guide in few places, but follows local style in those files.

Maxim Sloyko (5):
aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include
file), plus minimal device tree configuration for ast2500 eval board.
aspeed: Fixed incosistency in some SCU registers naming.
aspeed: Added function to calculate APB Clock frequency.
aspeed: Added function to configure pins for I2C devices.
aspeed: I2C driver.

 arch/arm/dts/Makefile                       |    2 +
 arch/arm/dts/aspeed-g5-evb.dts              |   28 +
 arch/arm/dts/aspeed-g5.dtsi                 | 1278 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-aspeed/ast_scu.h  |    6 +
 arch/arm/include/asm/arch-aspeed/regs-scu.h |   73 +-
 arch/arm/mach-aspeed/ast-scu.c              |   41 +-
 drivers/i2c/Kconfig                         |    7 +
 drivers/i2c/Makefile                        |    1 +
 drivers/i2c/ast_i2c.c                       |  305 +++++++
 drivers/i2c/ast_i2c.h                       |  143 +++
 10 files changed, 1851 insertions(+), 33 deletions(-)
 create mode 100644 arch/arm/dts/aspeed-g5-evb.dts
 create mode 100644 arch/arm/dts/aspeed-g5.dtsi
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h

--
2.8.0.rc3.226.g39d4020

#1 lore raw

PATCH 1/5 aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include file), plus minimal device tree configuration for ast2500 eval board.

From: Maxim Sloyko <[email protected]>

aspeed-g5.dtsi include file is copied from
https://github.com/openbmc/linux/blob/c5682cb/arch/arm/boot/dts/aspeed-g5.dtsi

---
 arch/arm/dts/Makefile          |    2 +
 arch/arm/dts/aspeed-g5-evb.dts |   28 +
 arch/arm/dts/aspeed-g5.dtsi    | 1278 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1308 insertions(+)
 create mode 100644 arch/arm/dts/aspeed-g5-evb.dts
 create mode 100644 arch/arm/dts/aspeed-g5.dtsi
arch/arm/dts/Makefile +2 -0
index ef573ec..333bf3b 100644
@@ -262,6 +262,8 @@ dtb-$(CONFIG_SOC_KEYSTONE) += k2hk-evm.dtb \
 	k2e-evm.dtb \
 	k2g-evm.dtb
 
+dtb-$(CONFIG_TARGET_AST_G5) += aspeed-g5-evb.dtb
+
 targets += $(dtb-y)
 
 # Add any required device tree compiler flags here
arch/arm/dts/aspeed-g5-evb.dts new file +28 -0
new file mode 100644
index 0000000..95dc77a
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+
+/ {
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;
+	};
+
+	aliases {
+		i2c1 = &i2c0;
+		i2c4 = &i2c3;
+		i2c8 = &i2c7;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&i2c3 {
+	status = "okay";
+};
+
+&i2c7 {
+	status = "okay";
+};
arch/arm/dts/aspeed-g5.dtsi new file +1278 -0

1,278 lines not on this page · raw message

Signature · 1 line
2.8.0.rc3.226.g39d4020
#2 lore raw

PATCH 1/5 aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include file), plus minimal device tree configuration for ast2500 eval board.

Quoted 5 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

aspeed-g5.dtsi include file is copied from
https://github.com/openbmc/linux/blob/c5682cb/arch/arm/boot/dts/aspeed-g5.dtsi

Quoted 8 lines
---
 arch/arm/dts/Makefile          |    2 +
 arch/arm/dts/aspeed-g5-evb.dts |   28 +
 arch/arm/dts/aspeed-g5.dtsi    | 1278 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1308 insertions(+)
 create mode 100644 arch/arm/dts/aspeed-g5-evb.dts
 create mode 100644 arch/arm/dts/aspeed-g5.dtsi
#3 lore raw

Re: [PATCH u-boot 1/5] aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include file), plus minimal device tree configuration for ast2500 eval board.

[resend from correct address]

Quoted 16 lines · Simon Glass
Quoted 5 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

aspeed-g5.dtsi include file is copied from
https://github.com/openbmc/linux/blob/c5682cb/arch/arm/boot/dts/aspeed-g5.dtsi

Quoted 8 lines
---
 arch/arm/dts/Makefile          |    2 +
 arch/arm/dts/aspeed-g5-evb.dts |   28 +
 arch/arm/dts/aspeed-g5.dtsi    | 1278 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1308 insertions(+)
 create mode 100644 arch/arm/dts/aspeed-g5-evb.dts
 create mode 100644 arch/arm/dts/aspeed-g5.dtsi
#4 lore raw

PATCH 2/5 aspeed: Fixed incosistency in some SCU registers naming.

In reply to [email protected]

From: Maxim Sloyko <[email protected]>

Basically fixed FUC/FUN typo that went out of hand.

---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 73 ++++++++++++++++-------------
 arch/arm/mach-aspeed/ast-scu.c              |  2 +-
 2 files changed, 42 insertions(+), 33 deletions(-)
arch/arm/include/asm/arch-aspeed/regs-scu.h +41 -32
index b714fa9..6cb4d0d 100644
@@ -830,49 +830,53 @@
 /* AST_SCU_FUN_PIN_CTRL5		0x90 - Multi-function Pin Control#5 */
 #define SCU_FUN_PIN_SPICS1		(0x1 << 31)
 #define SCU_FUN_PIN_LPC_PLUS		(0x1 << 30)
-#define SCU_FUC_PIN_USB20_HOST		(0x1 << 29)
-#define SCU_FUC_PIN_USB11_PORT4		(0x1 << 28)
-#define SCU_FUC_PIN_I2C14		(0x1 << 27)
-#define SCU_FUC_PIN_I2C13		(0x1 << 26)
-#define SCU_FUC_PIN_I2C12		(0x1 << 25)
-#define SCU_FUC_PIN_I2C11		(0x1 << 24)
-#define SCU_FUC_PIN_I2C10		(0x1 << 23)
-#define SCU_FUC_PIN_I2C9		(0x1 << 22)
-#define SCU_FUC_PIN_I2C8		(0x1 << 21)
-#define SCU_FUC_PIN_I2C7		(0x1 << 20)
-#define SCU_FUC_PIN_I2C6		(0x1 << 19)
-#define SCU_FUC_PIN_I2C5		(0x1 << 18)
-#define SCU_FUC_PIN_I2C4		(0x1 << 17)
-#define SCU_FUC_PIN_I2C3		(0x1 << 16)
-#define SCU_FUC_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
-#define SCU_FUC_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
-#define SCU_FUC_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
-#define SCU_FUC_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
-
-#define SCU_FUC_PIN_MII2_TX_DRIV(x)	(x << 10)
-#define SCU_FUC_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
-#define SCU_FUC_PIN_MII1_TX_DRIV(x)	(x << 8)
-#define SCU_FUC_PIN_MII1_TX_DRIV_MASK	(0x3 << 8)
+#define SCU_FUN_PIN_USB20_HOST		(0x1 << 29)
+#define SCU_FUN_PIN_USB11_PORT4		(0x1 << 28)
+#define SCU_FUN_PIN_I2C14		(0x1 << 27)
+#define SCU_FUN_PIN_I2C13		(0x1 << 26)
+#define SCU_FUN_PIN_I2C12		(0x1 << 25)
+#define SCU_FUN_PIN_I2C11		(0x1 << 24)
+#define SCU_FUN_PIN_I2C10		(0x1 << 23)
+#define SCU_FUN_PIN_I2C9		(0x1 << 22)
+#define SCU_FUN_PIN_I2C8		(0x1 << 21)
+#define SCU_FUN_PIN_I2C7		(0x1 << 20)
+#define SCU_FUN_PIN_I2C6		(0x1 << 19)
+#define SCU_FUN_PIN_I2C5		(0x1 << 18)
+#define SCU_FUN_PIN_I2C4		(0x1 << 17)
+#define SCU_FUN_PIN_I2C3		(0x1 << 16)
+#define SCU_FUN_PIN_I2C(n)		(0x1 << (16 + (n) - 3))
+#define SCU_FUN_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
+#define SCU_FUN_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
+#define SCU_FUN_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
+#define SCU_FUN_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
+
+#define SCU_I2C_MIN_BUS_NUM			(1)
+#define SCU_I2C_MAX_BUS_NUM			(14)
+
+#define SCU_FUN_PIN_MII2_TX_DRIV(x)	(x << 10)
+#define SCU_FUN_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
+#define SCU_FUN_PIN_MII1_TX_DRIV(x)	(x << 8)
+#define SCU_FUN_PIN_MII1_TX_DRIV_MASK	(0x3 << 8)
 
 #define MII_NORMAL_DRIV			0x0
 #define MII_HIGH_DRIV			0x2
 
-#define SCU_FUC_PIN_UART6		(0x1 << 7)
-#define SCU_FUC_PIN_ROM_16BIT		(0x1 << 6)
-#define SCU_FUC_PIN_DIGI_V_OUT(x)	(x)
-#define SCU_FUC_PIN_DIGI_V_OUT_MASK	(0x3)
+#define SCU_FUN_PIN_UART6		(0x1 << 7)
+#define SCU_FUN_PIN_ROM_16BIT		(0x1 << 6)
+#define SCU_FUN_PIN_DIGI_V_OUT(x)	(x)
+#define SCU_FUN_PIN_DIGI_V_OUT_MASK	(0x3)
 
 #define VIDEO_DISABLE			0x0
 #define VIDEO_12BITS			0x1
 #define VIDEO_24BITS			0x2
 //#define VIDEO_DISABLE			0x3
 
-#define SCU_FUC_PIN_USB11_PORT2		(0x1 << 3)
-#define SCU_FUC_PIN_SD1_8BIT		(0x1 << 3)
+#define SCU_FUN_PIN_USB11_PORT2		(0x1 << 3)
+#define SCU_FUN_PIN_SD1_8BIT		(0x1 << 3)
 
-#define SCU_FUC_PIN_MAC1_MDIO		(0x1 << 2)
-#define SCU_FUC_PIN_SD2			(0x1 << 1)
-#define SCU_FUC_PIN_SD1			(0x1 << 0)
+#define SCU_FUN_PIN_MAC1_MDIO		(0x1 << 2)
+#define SCU_FUN_PIN_SD2			(0x1 << 1)
+#define SCU_FUN_PIN_SD1			(0x1 << 0)
 
 
 /* AST_SCU_FUN_PIN_CTRL6		0x94 - Multi-function Pin Control#6*/
@@ -914,6 +918,11 @@
 #define SCU_FUN_PIN_ROMA4		(0x1 << 18)
 #define SCU_FUN_PIN_ROMA3		(0x1 << 17)
 #define SCU_FUN_PIN_ROMA2		(0x1 << 16)
+/* AST2500 only */
+#define SCU_FUN_PIN_SDA2		(0x1 << 15)
+#define SCU_FUN_PIN_SCL2		(0x1 << 14)
+#define SCU_FUN_PIN_SDA1		(0x1 << 13)
+#define SCU_FUN_PIN_SCL1		(0x1 << 12)
 
 /* AST_SCU_FUN_PIN_CTRL9		0xA8 - Multi-function Pin Control#9 */
 #define SCU_FUN_PIN_ROMA21		(0x1 << 3)
arch/arm/mach-aspeed/ast-scu.c +1 -1
index 0cc0d67..280c421 100644
@@ -394,7 +394,7 @@ void ast_scu_multi_func_eth(u8 num)
 			      AST_SCU_FUN_PIN_CTRL1);
 
 		ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
-			      SCU_FUC_PIN_MAC1_MDIO,
+			      SCU_FUN_PIN_MAC1_MDIO,
 			      AST_SCU_FUN_PIN_CTRL5);
 
 		break;
Signature · 1 line
2.8.0.rc3.226.g39d4020
#5 lore raw

PATCH 2/5 aspeed: Fixed incosistency in some SCU registers naming.

Hi Maxim,

Quoted 5 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

Basically fixed FUC/FUN typo that went out of hand.

This looks like a mix of whiltespace changes and other changes? If so, can you split it into two patches?

Quoted 5 lines
---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 73 ++++++++++++++++-------------
 arch/arm/mach-aspeed/ast-scu.c              |  2 +-
 2 files changed, 42 insertions(+), 33 deletions(-)

Regards,
Simon

#6 lore raw

Re: [PATCH u-boot 2/5] aspeed: Fixed incosistency in some SCU registers naming.

[resend from correct address]

Quoted 20 lines · Simon Glass

Hi Maxim,

Quoted 5 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

Basically fixed FUC/FUN typo that went out of hand.

This looks like a mix of whiltespace changes and other changes? If so, can you split it into two patches?

Quoted 5 lines
---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 73 ++++++++++++++++-------------
 arch/arm/mach-aspeed/ast-scu.c              |  2 +-
 2 files changed, 42 insertions(+), 33 deletions(-)

Regards,
Simon

#7 lore raw

PATCH 3/5 aspeed: Added function to calculate APB Clock frequency.

In reply to [email protected]

From: Maxim Sloyko <[email protected]>

This is needed by I2C driver.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  1 +
 arch/arm/mach-aspeed/ast-scu.c             | 11 +++++++++++
 2 files changed, 12 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +1 -0
index d248416..eb5aaa2 100644
@@ -38,6 +38,7 @@ extern void ast_scu_get_who_init_dram(void);
 extern u32 ast_get_clk_source(void);
 extern u32 ast_get_h_pll_clk(void);
 extern u32 ast_get_ahbclk(void);
+extern u32 ast_get_apbclk(void);
 
 extern u32 ast_scu_get_vga_memsize(void);
 
arch/arm/mach-aspeed/ast-scu.c +11 -0
index 280c421..e00dbe2 100644
@@ -318,6 +318,17 @@ u32 ast_get_ahbclk(void)
 
 #endif /* AST_SOC_G5 */
 
+u32 ast_get_apbclk(void)
+{
+	u32 h_pll = ast_get_h_pll_clk();
+	/* The formula for converting the bit pattern to divisor is
+	 * (4 + 4 * DIV), according to datasheet
+	 */
+	u32 apb_div = 4 + 4 * SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL));
+	return h_pll / apb_div;
+}
+
+
 void ast_scu_show_system_info(void)
 {
 
Signature · 1 line
2.8.0.rc3.226.g39d4020
#8 lore raw

PATCH 3/5 aspeed: Added function to calculate APB Clock frequency.

Hi Maxim,

Quoted 2 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

For the subject, 'Add' rather than 'Added' (we use present tense)

Quoted 13 lines

This is needed by I2C driver.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  1 +
 arch/arm/mach-aspeed/ast-scu.c             | 11 +++++++++++
 2 files changed, 12 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
index d248416..eb5aaa2 100644

arch/arm/include/asm/arch-aspeed/ast_scu.h extern void ast_scu_get_who_init_dram(void); · line 41

Quoted 4 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +1 -0
@@ -38,6 +38,7 @@ extern void ast_scu_get_who_init_dram(void);
 extern u32 ast_get_clk_source(void);
 extern u32 ast_get_h_pll_clk(void);
 extern u32 ast_get_ahbclk(void);
+extern u32 ast_get_apbclk(void);

Please add a comment as to what this does and what it returns.

Quoted 8 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
 extern u32 ast_scu_get_vga_memsize(void);
 
arch/arm/mach-aspeed/ast-scu.c +0 -0
index 280c421..e00dbe2 100644

arch/arm/mach-aspeed/ast-scu.c u32 ast_get_ahbclk(void) · line 323

Quoted 6 lines
arch/arm/mach-aspeed/ast-scu.c +3 -0
@@ -318,6 +318,17 @@ u32 ast_get_ahbclk(void)
 
 #endif /* AST_SOC_G5 */
 
+u32 ast_get_apbclk(void)
+{
+       u32 h_pll = ast_get_h_pll_clk();

Can this be ulong, or is there a reason it has to be exactly 32 bits?

blank line here (between declarations and code)

arch/arm/mach-aspeed/ast-scu.c u32 ast_get_ahbclk(void) · line 324

Quoted 1 line
arch/arm/mach-aspeed/ast-scu.c +1 -0
+       /* The formula for converting the bit pattern to divisor is

/*
* The formula...
* ...
*/

Quoted 11 lines
arch/arm/mach-aspeed/ast-scu.c +7 -1
+        * (4 + 4 * DIV), according to datasheet
+        */
+       u32 apb_div = 4 + 4 * SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL));
+       return h_pll / apb_div;
+}
+
+
 void ast_scu_show_system_info(void)
 {
 
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

#9 lore raw

Re: [PATCH u-boot 3/5] aspeed: Added function to calculate APB Clock frequency.

[resend from correct address]

Quoted 70 lines · Simon Glass

Hi Maxim,

Quoted 2 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

For the subject, 'Add' rather than 'Added' (we use present tense)

Quoted 13 lines

This is needed by I2C driver.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  1 +
 arch/arm/mach-aspeed/ast-scu.c             | 11 +++++++++++
 2 files changed, 12 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
index d248416..eb5aaa2 100644

arch/arm/include/asm/arch-aspeed/ast_scu.h extern void ast_scu_get_who_init_dram(void); · line 41

Quoted 4 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +1 -0
@@ -38,6 +38,7 @@ extern void ast_scu_get_who_init_dram(void);
 extern u32 ast_get_clk_source(void);
 extern u32 ast_get_h_pll_clk(void);
 extern u32 ast_get_ahbclk(void);
+extern u32 ast_get_apbclk(void);

Please add a comment as to what this does and what it returns.

Quoted 8 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
 extern u32 ast_scu_get_vga_memsize(void);
 
arch/arm/mach-aspeed/ast-scu.c +0 -0
index 280c421..e00dbe2 100644

arch/arm/mach-aspeed/ast-scu.c u32 ast_get_ahbclk(void) · line 323

Quoted 6 lines
arch/arm/mach-aspeed/ast-scu.c +3 -0
@@ -318,6 +318,17 @@ u32 ast_get_ahbclk(void)
 
 #endif /* AST_SOC_G5 */
 
+u32 ast_get_apbclk(void)
+{
+       u32 h_pll = ast_get_h_pll_clk();

Can this be ulong, or is there a reason it has to be exactly 32 bits?

blank line here (between declarations and code)

arch/arm/mach-aspeed/ast-scu.c u32 ast_get_ahbclk(void) · line 324

Quoted 1 line
arch/arm/mach-aspeed/ast-scu.c +1 -0
+       /* The formula for converting the bit pattern to divisor is

/*
* The formula...
* ...
*/

Quoted 11 lines
arch/arm/mach-aspeed/ast-scu.c +7 -1
+        * (4 + 4 * DIV), according to datasheet
+        */
+       u32 apb_div = 4 + 4 * SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL));
+       return h_pll / apb_div;
+}
+
+
 void ast_scu_show_system_info(void)
 {
 
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

#10 lore raw

Re: [PATCH u-boot 3/5] aspeed: Added function to calculate APB Clock frequency.

Quoted 11 lines · Simon Glass

[resend from correct address]

Quoted 7 lines · Simon Glass

Hi Maxim,

Quoted 2 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

For the subject, 'Add' rather than 'Added' (we use present tense)

Done.

Quoted 22 lines
Quoted 10 lines

Review

Quoted 10 lines

This is needed by I2C driver.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  1 +
 arch/arm/mach-aspeed/ast-scu.c             | 11 +++++++++++
 2 files changed, 12 insertions(+)
(quoted diff) +0 -0

b/arch/arm/include/asm/arch-aspeed/ast_scu.h

Quoted 10 lines

arch/arm/include/asm/arch-aspeed/ast_scu.h extern void ast_scu_get_who_init_dram(void); · line 41

Quoted 8 lines

index d248416..eb5aaa2 100644

arch/arm/include/asm/arch-aspeed/ast_scu.h +1 -0
@@ -38,6 +38,7 @@ extern void ast_scu_get_who_init_dram(void);
 extern u32 ast_get_clk_source(void);
 extern u32 ast_get_h_pll_clk(void);
 extern u32 ast_get_ahbclk(void);
+extern u32 ast_get_apbclk(void);

Please add a comment as to what this does and what it returns.

Done.

Quoted 28 lines
Quoted 5 lines

arch/arm/mach-aspeed/ast-

Quoted 5 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
 extern u32 ast_scu_get_vga_memsize(void);
 
arch/arm/mach-aspeed/ast- renamed from arch/arm/mach-aspeed/ast-scu.c +0 -0

scu.c

Quoted 21 lines

arch/arm/mach-aspeed/ast-scu.c u32 ast_get_ahbclk(void) · line 323

Quoted 10 lines

index 280c421..e00dbe2 100644

arch/arm/mach-aspeed/ast-scu.c +3 -0
@@ -318,6 +318,17 @@ u32 ast_get_ahbclk(void)
 
 #endif /* AST_SOC_G5 */
 
+u32 ast_get_apbclk(void)
+{
+       u32 h_pll = ast_get_h_pll_clk();

Can this be ulong, or is there a reason it has to be exactly 32 bits?

blank line here (between declarations and code)

arch/arm/mach-aspeed/ast-scu.c u32 ast_get_ahbclk(void) · line 324

Quoted 1 line
arch/arm/mach-aspeed/ast-scu.c +1 -0
+       /* The formula for converting the bit pattern to divisor is

/*
* The formula...
* ...
*/

Done.

Quoted 19 lines
Quoted 4 lines

arch/arm/mach-aspeed/ast-scu.c u32 ast_get_ahbclk(void)

Quoted 4 lines
arch/arm/mach-aspeed/ast-scu.c +3 -0
+        * (4 + 4 * DIV), according to datasheet
+        */
+       u32 apb_div = 4 + 4 * SCU_GET_PCLK_DIV(ast_scu_read(

AST_SCU_CLK_SEL));

Quoted 13 lines
Quoted 10 lines
arch/arm/mach-aspeed/ast-scu.c +4 -1
+       return h_pll / apb_div;
+}
+
+
 void ast_scu_show_system_info(void)
 {
 
--

2.8.0.rc3.226.g39d4020

Regards,
Simon

Signature · 1 line
*M*axim *S*loyko
#11 lore raw

PATCH 4/5 aspeed: Added function to configure pins for I2C devices.

In reply to [email protected]

From: Maxim Sloyko <[email protected]>

In the absence of pinmux driver, I2C driver will be configuring pins directly.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  5 +++++
 arch/arm/mach-aspeed/ast-scu.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +5 -0
index eb5aaa2..80ebd6f 100644
@@ -46,4 +46,9 @@ extern void ast_scu_init_eth(u8 num);
 extern void ast_scu_multi_func_eth(u8 num);
 extern void ast_scu_multi_func_romcs(u8 num);
 
+/* Enable I2C controller and pins for a particular device.
+ * Device numbering starts at 1
+ */
+extern void ast_scu_enable_i2c(u8 num);
+
 #endif
arch/arm/mach-aspeed/ast-scu.c +28 -0
index e00dbe2..b5aa8bf 100644
@@ -507,3 +507,31 @@ void ast_scu_get_who_init_dram(void)
 		break;
 	}
 }
+
+void ast_scu_enable_i2c(u8 bus_num)
+{
+	if (bus_num > SCU_I2C_MAX_BUS_NUM) {
+		debug("%s: bus_num is out of range, must be [%d - %d]\n",
+		      __func__, SCU_I2C_MIN_BUS_NUM, SCU_I2C_MAX_BUS_NUM);
+		return;
+	}
+
+	if (bus_num == 0) {
+		/* Enable I2C Controllers */
+		clrbits_le32(AST_SCU_BASE + AST_SCU_RESET, SCU_RESET_I2C);
+	} else if (bus_num >= 3) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL5,
+			     SCU_FUN_PIN_I2C(bus_num));
+	/* In earlier versions of the SoC these pins are always assigned to
+	 * respective I2C buses and require no configuration.
+	 */
+#ifdef AST_SOC_G5
+	} else if (bus_num == 1) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+			     SCU_FUN_PIN_SDA1 | SCU_FUN_PIN_SCL1);
+	} else if (bus_num == 2) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+			     SCU_FUN_PIN_SDA2 | SCU_FUN_PIN_SCL2);
+#endif
+	}
+}
Signature · 1 line
2.8.0.rc3.226.g39d4020
#12 lore raw

PATCH 4/5 aspeed: Added function to configure pins for I2C devices.

Hi Maxim,

Quoted 4 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

In the absence of pinmux driver, I2C driver will be configuring pins directly.

Commit subject s/Added/Add/

and please remove the '.' at the end.

Quoted 12 lines
---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  5 +++++
 arch/arm/mach-aspeed/ast-scu.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
index eb5aaa2..80ebd6f 100644

arch/arm/include/asm/arch-aspeed/ast_scu.h extern void ast_scu_init_eth(u8 num); · line 52

Quoted 7 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +4 -0
@@ -46,4 +46,9 @@ extern void ast_scu_init_eth(u8 num);
 extern void ast_scu_multi_func_eth(u8 num);
 extern void ast_scu_multi_func_romcs(u8 num);
 
+/* Enable I2C controller and pins for a particular device.
+ * Device numbering starts at 1
+ */
+extern void ast_scu_enable_i2c(u8 num);

I suspect this should be done as a pinctrl driver. See for drivers/pinctrl for examples.

Quoted 39 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +1 -0
+
 #endif
arch/arm/mach-aspeed/ast-scu.c +28 -1
index e00dbe2..b5aa8bf 100644
@@ -507,3 +507,31 @@ void ast_scu_get_who_init_dram(void)
                break;
        }
 }
+
+void ast_scu_enable_i2c(u8 bus_num)
+{
+       if (bus_num > SCU_I2C_MAX_BUS_NUM) {
+               debug("%s: bus_num is out of range, must be [%d - %d]\n",
+                     __func__, SCU_I2C_MIN_BUS_NUM, SCU_I2C_MAX_BUS_NUM);
+               return;
+       }
+
+       if (bus_num == 0) {
+               /* Enable I2C Controllers */
+               clrbits_le32(AST_SCU_BASE + AST_SCU_RESET, SCU_RESET_I2C);
+       } else if (bus_num >= 3) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL5,
+                            SCU_FUN_PIN_I2C(bus_num));
+       /* In earlier versions of the SoC these pins are always assigned to
+        * respective I2C buses and require no configuration.
+        */
+#ifdef AST_SOC_G5
+       } else if (bus_num == 1) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+                            SCU_FUN_PIN_SDA1 | SCU_FUN_PIN_SCL1);
+       } else if (bus_num == 2) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+                            SCU_FUN_PIN_SDA2 | SCU_FUN_PIN_SCL2);
+#endif
+       }
+}
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

#13 lore raw

Re: [PATCH u-boot 4/5] aspeed: Added function to configure pins for I2C devices.

[resend from correct address]

Quoted 79 lines · Simon Glass

Hi Maxim,

Quoted 4 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

In the absence of pinmux driver, I2C driver will be configuring pins directly.

Commit subject s/Added/Add/

and please remove the '.' at the end.

Quoted 12 lines
---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  5 +++++
 arch/arm/mach-aspeed/ast-scu.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
index eb5aaa2..80ebd6f 100644

arch/arm/include/asm/arch-aspeed/ast_scu.h extern void ast_scu_init_eth(u8 num); · line 52

Quoted 7 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +4 -0
@@ -46,4 +46,9 @@ extern void ast_scu_init_eth(u8 num);
 extern void ast_scu_multi_func_eth(u8 num);
 extern void ast_scu_multi_func_romcs(u8 num);
 
+/* Enable I2C controller and pins for a particular device.
+ * Device numbering starts at 1
+ */
+extern void ast_scu_enable_i2c(u8 num);

I suspect this should be done as a pinctrl driver. See for drivers/pinctrl for examples.

Quoted 39 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +1 -0
+
 #endif
arch/arm/mach-aspeed/ast-scu.c +28 -1
index e00dbe2..b5aa8bf 100644
@@ -507,3 +507,31 @@ void ast_scu_get_who_init_dram(void)
                break;
        }
 }
+
+void ast_scu_enable_i2c(u8 bus_num)
+{
+       if (bus_num > SCU_I2C_MAX_BUS_NUM) {
+               debug("%s: bus_num is out of range, must be [%d - %d]\n",
+                     __func__, SCU_I2C_MIN_BUS_NUM, SCU_I2C_MAX_BUS_NUM);
+               return;
+       }
+
+       if (bus_num == 0) {
+               /* Enable I2C Controllers */
+               clrbits_le32(AST_SCU_BASE + AST_SCU_RESET, SCU_RESET_I2C);
+       } else if (bus_num >= 3) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL5,
+                            SCU_FUN_PIN_I2C(bus_num));
+       /* In earlier versions of the SoC these pins are always assigned to
+        * respective I2C buses and require no configuration.
+        */
+#ifdef AST_SOC_G5
+       } else if (bus_num == 1) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+                            SCU_FUN_PIN_SDA1 | SCU_FUN_PIN_SCL1);
+       } else if (bus_num == 2) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+                            SCU_FUN_PIN_SDA2 | SCU_FUN_PIN_SCL2);
+#endif
+       }
+}
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

#14 lore raw

Re: [PATCH u-boot 4/5] aspeed: Added function to configure pins for I2C devices.

Quoted 38 lines · Simon Glass

[resend from correct address]

Quoted 34 lines · Simon Glass

Hi Maxim,

Quoted 4 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

In the absence of pinmux driver, I2C driver will be configuring pins directly.

Commit subject s/Added/Add/

and please remove the '.' at the end.

Quoted 12 lines
---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  5 +++++
 arch/arm/mach-aspeed/ast-scu.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +0 -0
index eb5aaa2..80ebd6f 100644

arch/arm/include/asm/arch-aspeed/ast_scu.h extern void ast_scu_init_eth(u8 num); · line 52

Quoted 7 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +4 -0
@@ -46,4 +46,9 @@ extern void ast_scu_init_eth(u8 num);
 extern void ast_scu_multi_func_eth(u8 num);
 extern void ast_scu_multi_func_romcs(u8 num);
 
+/* Enable I2C controller and pins for a particular device.
+ * Device numbering starts at 1
+ */
+extern void ast_scu_enable_i2c(u8 num);

I suspect this should be done as a pinctrl driver. See for drivers/pinctrl for examples.

Yes, in the future that is the plan. I think this is OK for now, given that this file already has similar functions, see ast_scu_multi_func_{eth, romcs} above.

Quoted 46 lines
Quoted 46 lines
Quoted 41 lines
arch/arm/include/asm/arch-aspeed/ast_scu.h +1 -0
+
 #endif
arch/arm/mach-aspeed/ast-scu.c +28 -1
index e00dbe2..b5aa8bf 100644
@@ -507,3 +507,31 @@ void ast_scu_get_who_init_dram(void)
                break;
        }
 }
+
+void ast_scu_enable_i2c(u8 bus_num)
+{
+       if (bus_num > SCU_I2C_MAX_BUS_NUM) {
+               debug("%s: bus_num is out of range, must be [%d - %d]\n",
+                     __func__, SCU_I2C_MIN_BUS_NUM, SCU_I2C_MAX_BUS_NUM);
+               return;
+       }
+
+       if (bus_num == 0) {
+               /* Enable I2C Controllers */
+               clrbits_le32(AST_SCU_BASE + AST_SCU_RESET, SCU_RESET_I2C);
+       } else if (bus_num >= 3) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL5,
+                            SCU_FUN_PIN_I2C(bus_num));
+       /* In earlier versions of the SoC these pins are always assigned to
+        * respective I2C buses and require no configuration.
+        */
+#ifdef AST_SOC_G5
+       } else if (bus_num == 1) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+                            SCU_FUN_PIN_SDA1 | SCU_FUN_PIN_SCL1);
+       } else if (bus_num == 2) {
+               setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+                            SCU_FUN_PIN_SDA2 | SCU_FUN_PIN_SCL2);
+#endif
+       }
+}
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

Signature · 1 line
Maxim Sloyko
#15 lore raw

PATCH 5/5 aspeed: I2C driver.

In reply to [email protected]

From: Maxim Sloyko <[email protected]>

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

---
 drivers/i2c/Kconfig   |   7 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 143 +++++++++++++++++++++++
 4 files changed, 456 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
drivers/i2c/Kconfig +7 -0
index 6e22bba..720c475 100644
@@ -90,6 +90,13 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 	  enable status register. This config option can be enabled in such
 	  cases.
 
+config SYS_I2C_AST
+	bool "Aspeed I2C Controller"
+	depends on DM_I2C
+	help
+	  Say yes here to select Aspeed I2C Host Controller. The driver
+	  supports AST2500 and AST2400 controllers.
+
 config SYS_I2C_INTEL
 	bool "Intel I2C/SMBUS driver"
 	depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +305 -0

305 lines not on this page · raw message

drivers/i2c/ast_i2c.h new file +143 -0

143 lines not on this page · raw message

Signature · 1 line
2.8.0.rc3.226.g39d4020
#16 lore raw

PATCH 5/5 aspeed: I2C driver.

Hi Maxim,

Quoted 5 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

Please add that into the Kconfig help too.

Quoted 58 lines
---
 drivers/i2c/Kconfig   |   7 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 143 +++++++++++++++++++++++
 4 files changed, 456 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
drivers/i2c/Kconfig +7 -0
index 6e22bba..720c475 100644
@@ -90,6 +90,13 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
          enable status register. This config option can be enabled in such
          cases.
 
+config SYS_I2C_AST
+       bool "Aspeed I2C Controller"
+       depends on DM_I2C
+       help
+         Say yes here to select Aspeed I2C Host Controller. The driver
+         supports AST2500 and AST2400 controllers.
+
 config SYS_I2C_INTEL
        bool "Intel I2C/SMBUS driver"
        depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +11 -0
new file mode 100644
index 0000000..f2c132e
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>

drivers/i2c/ast_i2c.c line 21

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+#include <i2c.h>
+
+#include <asm/arch/ast_scu.h>
+#include <asm/arch/regs-scu.h>
+#include <asm/io.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US (100000)
+#define I2C_SLEEP_STEP (20)

I2C_SLEEP_STEP_US

drivers/i2c/ast_i2c.c line 22

Quoted 1 line
drivers/i2c/ast_i2c.c new file +1 -0
+#define EI2C_TIMEOUT (1001)

EI2C_TIMEOUT_US

Please drop the () on those

drivers/i2c/ast_i2c.c line 26

Quoted 4 lines
drivers/i2c/ast_i2c.c new file +4 -0
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast_i2c {

Please add a struct comment with member info.

drivers/i2c/ast_i2c.c line 32

Quoted 6 lines
drivers/i2c/ast_i2c.c new file +6 -0
+       u32 id;
+       struct ast_i2c_regs *regs;
+       int speed;
+};
+
+static u32 get_clk_reg_val(u32 divider_ratio)

Function comment. Consider returning ulong.

drivers/i2c/ast_i2c.c line 44

Quoted 12 lines
drivers/i2c/ast_i2c.c new file +12 -0
+{
+       unsigned int inc = 0, div;
+       u32 scl_low, scl_high, data;
+
+       for (div = 0; divider_ratio >= 16; div++) {
+               inc |= (divider_ratio & 1);
+               divider_ratio >>= 1;
+       }
+       divider_ratio += inc;
+       scl_low = (divider_ratio >> 1) - 1;
+       scl_high = divider_ratio - scl_low - 2;
+       data = 0x77700300 | (scl_high << 16) | (scl_low << 12) | div;

blank link here. What is the magic 0x77700300 for? Should either have a comment or a #define

drivers/i2c/ast_i2c.c line 57

Quoted 13 lines
drivers/i2c/ast_i2c.c new file +13 -0
+       return data;
+}
+
+static inline void ast_i2c_clear_interrupts(struct ast_i2c_regs *i2c_base)
+{
+       writel(~0, &i2c_base->isr);
+}
+
+static void ast_i2c_init_bus(struct ast_i2c *i2c_bus)
+{
+       /* Reset device */
+       writel(0, &i2c_bus->regs->fcr);
+       /* Enable Master Mode. Assuming single-master. */

nit: Please avoid '.' at end of comments

Quoted 15 lines
drivers/i2c/ast_i2c.c new file +15 -0
+       debug("Enable Master for %p\n", i2c_bus->regs);
+       writel(AST_I2CD_MASTER_EN
+              | AST_I2CD_M_SDA_LOCK_EN
+              | AST_I2CD_MULTI_MASTER_DIS | AST_I2CD_M_SCL_DRIVE_EN,
+              &i2c_bus->regs->fcr);
+       debug("FCR: %p\n", &i2c_bus->regs->fcr);
+       /* Enable Interrupts */
+       writel(AST_I2CD_INTR_TX_ACK
+              | AST_I2CD_INTR_TX_NAK
+              | AST_I2CD_INTR_RX_DONE
+              | AST_I2CD_INTR_BUS_RECOVER_DONE
+              | AST_I2CD_INTR_NORMAL_STOP
+              | AST_I2CD_INTR_ABNORMAL, &i2c_bus->regs->icr);
+}
+

drivers/i2c/ast_i2c.c line 82

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+static int ast_i2c_probe(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       debug("Enabling I2C%u\n", dev->seq);
+       ast_scu_enable_i2c(dev->seq);
+
+       i2c_bus->id = dev->seq;
+       struct ast_i2c_regs *i2c_base =
+           (struct ast_i2c_regs *)dev_get_addr(dev);

Can you use dev_get_addr_ptr()? Need to check for NULL and return -EINVAL. Also, reading the device tree should really be in the ofdata_to_platdata() method, not probe().

drivers/i2c/ast_i2c.c line 91

Quoted 9 lines
drivers/i2c/ast_i2c.c new file +9 -0
+       i2c_bus->regs = i2c_base;
+
+       ast_i2c_init_bus(i2c_bus);
+       return 0;
+}
+
+static inline int ast_i2c_wait_isr(struct ast_i2c_regs *i2c_base, u32 flag)
+{
+       int timeout = I2C_TIMEOUT_US;

blank line here

drivers/i2c/ast_i2c.c line 99

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +8 -0
+       while (!(readl(&i2c_base->isr) & flag) && timeout > 0) {
+               udelay(I2C_SLEEP_STEP);
+               timeout -= I2C_SLEEP_STEP;
+       }
 
 
+
+       ast_i2c_clear_interrupts(i2c_base);
+       if (timeout <= 0)
+               return -EI2C_TIMEOUT;

return -ETIMEDOUT

drivers/i2c/ast_i2c.c line 105

Quoted 6 lines
drivers/i2c/ast_i2c.c new file +6 -0
+       return 0;
+}
+
+static inline int ast_i2c_send_stop(struct ast_i2c_regs *i2c_base)
+{
+       writel(AST_I2CD_M_STOP_CMD, &i2c_base->csr);

blank line (please do this before each return)

drivers/i2c/ast_i2c.c line 113

Quoted 8 lines
drivers/i2c/ast_i2c.c new file +8 -0
+       return ast_i2c_wait_isr(i2c_base, AST_I2CD_INTR_NORMAL_STOP);
+}
+
+static inline int ast_i2c_wait_tx(struct ast_i2c_regs *i2c_base)
+{
+       int timeout = I2C_TIMEOUT_US;
+       u32 flag = AST_I2CD_INTR_TX_ACK | AST_I2CD_INTR_TX_NAK;
+       u32 status = readl(&i2c_base->isr) & flag;

blank line (please do this after all decl blocks)

drivers/i2c/ast_i2c.c line 120

Quoted 7 lines
drivers/i2c/ast_i2c.c new file +7 -0
+       while (!status && timeout > 0) {
+               status = readl(&i2c_base->isr) & flag;
+               udelay(I2C_SLEEP_STEP);
+               timeout -= I2C_SLEEP_STEP;
+       }
+
+       int ret = 0;

Move this to top of function. Declarations should all be at the start of the block.

drivers/i2c/ast_i2c.c line 131

Quoted 11 lines
drivers/i2c/ast_i2c.c new file +11 -0
+       if (status == AST_I2CD_INTR_TX_NAK)
+               ret = -EREMOTEIO;
+
+       if (timeout <= 0)
+               ret = -EI2C_TIMEOUT;
+
+       ast_i2c_clear_interrupts(i2c_base);
+       return ret;
+}
+
+static inline int ast_i2c_start_txn(struct ast_i2c_regs *i2c_base, u8 devaddr)

Why inline? The compiler will do that anyway so I think you can drop it. Also please use int or uint for devaddr - particularly on ARM it isn't good to have non-register-sized parameters and return values.

Quoted 16 lines
drivers/i2c/ast_i2c.c new file +16 -0
+{
+       /* Start and Send Device Address */
+       writel(devaddr, &i2c_base->trbbr);
+       writel(AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD, &i2c_base->csr);
+       return ast_i2c_wait_tx(i2c_base);
+}
+
+static int ast_i2c_read_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8 *buffer,
+                            size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       int i2c_error =
+           ast_i2c_start_txn(i2c_base, (chip_addr << 1) | I2C_M_RD);
+       if (i2c_error < 0)
+               return i2c_error;

drivers/i2c/ast_i2c.c line 157

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+
+       u32 i2c_cmd = AST_I2CD_M_RX_CMD;
+       for (; len > 0; len--, buffer++) {
+               if (len == 1)
+                       i2c_cmd |= AST_I2CD_M_S_RX_CMD_LAST;
+               writel(i2c_cmd, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_isr(i2c_base, AST_I2CD_INTR_RX_DONE);
+               if (i2c_error < 0)
+                       return i2c_error;
+               *buffer = AST_I2CD_RX_DATA_BUF_GET(readl(&i2c_base->trbbr));

Instead of AST_I2CD_RX_DATA_BUF_GET(), please define something like AST_I2CD_RX_DATA_SHIFT and _MASK and use then here.

#define AST_I2CD_RX_DATA_SHIFT 8
#define AST_I2CD_RX_DATA_MASK (0xff << AST_I2CD_RX_DATA_SHIFT)

Quoted 30 lines
drivers/i2c/ast_i2c.c new file +30 -0
+       }
+       ast_i2c_clear_interrupts(i2c_base);
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;
+}
+
+static int ast_i2c_write_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8
+                             *buffer, size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       int i2c_error = ast_i2c_start_txn(i2c_base, (chip_addr << 1));
+       if (i2c_error < 0)
+               return i2c_error;
+
+       for (; len > 0; len--, buffer++) {
+               writel(*buffer, &i2c_base->trbbr);
+               writel(AST_I2CD_M_TX_CMD, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_tx(i2c_base);
+               if (i2c_error < 0)
+                       return i2c_error;
+       }
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;

drivers/i2c/ast_i2c.c line 197

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       u32 csr = readl(&i2c_base->csr);
+
+       int deblock_error = 0;

Just 'ret' is good enough.

Quoted 25 lines
drivers/i2c/ast_i2c.c new file +25 -0
+       bool sda_high = csr & AST_I2CD_SDA_LINE_STS;
+       bool scl_high = csr & AST_I2CD_SCL_LINE_STS;
+       if (sda_high && scl_high) {
+               /* Bus is idle, no deblocking needed. */
+               return 0;
+       } else if (sda_high) {
+               /* Send stop command */
+               debug("Unterminated TXN in (%x), sending stop\n", csr);
+               deblock_error = ast_i2c_send_stop(i2c_base);
+       } else if (scl_high) {
+               /* Possibly stuck slave */
+               debug("Bus stuck (%x), attempting recovery\n", csr);
+               writel(AST_I2CD_BUS_RECOVER_CMD, &i2c_base->csr);
+               deblock_error = ast_i2c_wait_isr(
+                       i2c_base, AST_I2CD_INTR_BUS_RECOVER_DONE);
+       } else {
+               /* Just try to reinit the device. */
+               ast_i2c_init_bus(i2c_bus);
+       }
+
+       return deblock_error;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{

drivers/i2c/ast_i2c.c line 232

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       int ret;
+
+       (void)ast_i2c_deblock(dev);
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               if (msg->flags & I2C_M_RD) {
+                       debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret =

Can you break the line in the parameters instead of at '=' ?

Quoted 13 lines
drivers/i2c/ast_i2c.c new file +13 -0
+                           ast_i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                               msg->len, (nmsgs == 1));
+               } else {
+                       debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret =
+                           ast_i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                                msg->len, (nmsgs == 1));
+               }
+               if (ret) {
+                       debug("%s: error (%d)\n", __func__, ret);
+                       return -EREMOTEIO;
+               }

drivers/i2c/ast_i2c.c line 255

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       }
+
+       return 0;
+}
+
+static int ast_i2c_set_speed(struct udevice *dev, unsigned int speed)
+{
+       debug("Setting speed ofr I2C%d to <%u>\n", dev->seq, speed);
+       if (!speed) {
+               debug("No valid speed specified.\n");

Drop '.'

Quoted 75 lines
drivers/i2c/ast_i2c.c new file +50 -0
+               return -EINVAL;
+       }
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       i2c_bus->speed = speed;
+       /* TODO: get this from device tree */
+       u32 pclk = ast_get_apbclk();
+       u32 divider = pclk / speed;
+
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       if (speed > 400000) {
+               debug("Enabling High Speed\n");
+               setbits_le32(&i2c_base->fcr, AST_I2CD_M_HIGH_SPEED_EN
+                            | AST_I2CD_M_SDA_DRIVE_1T_EN
+                            | AST_I2CD_SDA_DRIVE_1T_EN);
+               writel(0x3, &i2c_base->cactcr2);
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+       } else {
+               debug("Enabling Normal Speed\n");
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+               writel(AST_NO_TIMEOUT_CTRL, &i2c_base->cactcr2);
+       }
+
+       ast_i2c_clear_interrupts(i2c_base);
+       return 0;
+}
+
+static const struct dm_i2c_ops ast_i2c_ops = {
+       .xfer = ast_i2c_xfer,
+       .set_bus_speed = ast_i2c_set_speed,
+       .deblock = ast_i2c_deblock,
+};
+
+static const struct udevice_id ast_i2c_ids[] = {
+       {.compatible = "aspeed,ast2400-i2c-controller",},
+       {.compatible = "aspeed,ast2400-i2c-bus",},
+       {},
+};
+
+/* Tell GNU Indent to keep this as is: */
+/* *INDENT-OFF* */
+U_BOOT_DRIVER(i2c_aspeed) = {
+       .name = "i2c_aspeed",
+       .id = UCLASS_I2C,
+       .of_match = ast_i2c_ids,
+       .probe = ast_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct ast_i2c),
+       .ops = &ast_i2c_ops,
+};
+/* *INDENT-ON* */
drivers/i2c/ast_i2c.h new file +19 -0
new file mode 100644
index 0000000..8926fd2
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#ifndef __AST_I2C_H_
+#define __AST_I2C_H_
+
+struct ast_i2c_regs {
+       uint32_t fcr;
+       uint32_t cactcr1;
+       uint32_t cactcr2;
+       uint32_t icr;
+       uint32_t isr;
+       uint32_t csr;
+       uint32_t sdar;
+       uint32_t pbcr;

drivers/i2c/ast_i2c.h line 29

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+       uint32_t trbbr;
+#ifdef CONFIG_TARGET_AST_G5
+       uint32_t dma_mbar;
+       uint32_t dma_tlr;
+#endif
+};
+
+/* Device Register Definition */
+/* 0x00 : I2CD Function Control Register  */
+#define AST_I2CD_BUFF_SEL_MASK                         (0x7 << 20)

It's fine to have the AST_I2CD_ prefix if you want it. But it does make things longer, and this header will only be included in one file. So feel free to prune to AST_ if you like.

Quoted 4 lines
drivers/i2c/ast_i2c.h new file +4 -0
+#define AST_I2CD_BUFF_SEL(x)                           (x << 20)
+#define AST_I2CD_M_SDA_LOCK_EN                 (0x1 << 16)
+#define AST_I2CD_MULTI_MASTER_DIS                      (0x1 << 15)
+#define AST_I2CD_M_SCL_DRIVE_EN                (0x1 << 14)

drivers/i2c/ast_i2c.h line 43

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+#define AST_I2CD_MSB_STS                                       (0x1 << 9)
+#define AST_I2CD_SDA_DRIVE_1T_EN                       (0x1 << 8)
+#define AST_I2CD_M_SDA_DRIVE_1T_EN             (0x1 << 7)
+#define AST_I2CD_M_HIGH_SPEED_EN               (0x1 << 6)
+#define AST_I2CD_DEF_ADDR_EN                           (0x1 << 5)
+#define AST_I2CD_DEF_ALERT_EN                          (0x1 << 4)
+#define AST_I2CD_DEF_ARP_EN                                    (0x1 << 3)
+#define AST_I2CD_DEF_GCALL_EN                          (0x1 << 2)
+#define AST_I2CD_SLAVE_EN                                      (0x1 << 1)
+#define AST_I2CD_MASTER_EN                                     (0x1)

Avoid brackets around simple constants

Quoted 82 lines
drivers/i2c/ast_i2c.h new file +82 -0
+
+/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
+#define AST_I2CD_tBUF                                          (0x1 << 28)
+#define AST_I2CD_tHDSTA                                                (0x1 << 24)
+#define AST_I2CD_tACST                                         (0x1 << 20)
+#define AST_I2CD_tCKHIGH                                       (0x1 << 16)
+#define AST_I2CD_tCKLOW                                                (0x1 << 12)
+#define AST_I2CD_tHDDAT                                                (0x1 << 10)
+#define AST_I2CD_CLK_TO_BASE_DIV                       (0x1 << 8)
+#define AST_I2CD_CLK_BASE_DIV                          (0x1)
+
+/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+#define AST_I2CD_tTIMEOUT                                      (0x1)
+#define AST_NO_TIMEOUT_CTRL                                    0x0
+
+/* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+ *
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
+#define AST_I2CD_INTR_SDA_DL_TIMEOUT                   (0x1 << 14)
+#define AST_I2CD_INTR_BUS_RECOVER_DONE                 (0x1 << 13)
+#define AST_I2CD_INTR_SMBUS_ALERT                      (0x1 << 12)
+#define AST_I2CD_INTR_SMBUS_ARP_ADDR                   (0x1 << 11)
+#define AST_I2CD_INTR_SMBUS_DEV_ALERT_ADDR             (0x1 << 10)
+#define AST_I2CD_INTR_SMBUS_DEF_ADDR                   (0x1 << 9)
+#define AST_I2CD_INTR_GCALL_ADDR                       (0x1 << 8)
+#define AST_I2CD_INTR_SLAVE_MATCH                      (0x1 << 7)
+#define AST_I2CD_INTR_SCL_TIMEOUT                      (0x1 << 6)
+#define AST_I2CD_INTR_ABNORMAL                         (0x1 << 5)
+#define AST_I2CD_INTR_NORMAL_STOP                      (0x1 << 4)
+#define AST_I2CD_INTR_ARBIT_LOSS                       (0x1 << 3)
+#define AST_I2CD_INTR_RX_DONE                          (0x1 << 2)
+#define AST_I2CD_INTR_TX_NAK                           (0x1 << 1)
+#define AST_I2CD_INTR_TX_ACK                           (0x1 << 0)
+
+/* 0x14 : I2CD Command/Status Register   */
+#define AST_I2CD_SDA_OE                                        (0x1 << 28)
+#define AST_I2CD_SDA_O                                 (0x1 << 27)
+#define AST_I2CD_SCL_OE                                        (0x1 << 26)
+#define AST_I2CD_SCL_O                                 (0x1 << 25)
+#define AST_I2CD_TX_TIMING                             (0x1 << 24)
+#define AST_I2CD_TX_STATUS                             (0x1 << 23)
+
+/* Tx State Machine */
+#define AST_I2CD_IDLE                                  0x0
+#define AST_I2CD_MACTIVE                               0x8
+#define AST_I2CD_MSTART                                        0x9
+#define AST_I2CD_MSTARTR                               0xa
+#define AST_I2CD_MSTOP                                 0xb
+#define AST_I2CD_MTXD                                  0xc
+#define AST_I2CD_MRXACK                                        0xd
+#define AST_I2CD_MRXD                                  0xe
+#define AST_I2CD_MTXACK                                0xf
+#define AST_I2CD_SWAIT                                 0x1
+#define AST_I2CD_SRXD                                  0x4
+#define AST_I2CD_STXACK                                0x5
+#define AST_I2CD_STXD                                  0x6
+#define AST_I2CD_SRXACK                                0x7
+#define AST_I2CD_RECOVER                               0x3
+
+#define AST_I2CD_SCL_LINE_STS                          (0x1 << 18)
+#define AST_I2CD_SDA_LINE_STS                          (0x1 << 17)
+#define AST_I2CD_BUS_BUSY_STS                          (0x1 << 16)
+#define AST_I2CD_SDA_OE_OUT_DIR                                (0x1 << 15)
+#define AST_I2CD_SDA_O_OUT_DIR                         (0x1 << 14)
+#define AST_I2CD_SCL_OE_OUT_DIR                                (0x1 << 13)
+#define AST_I2CD_SCL_O_OUT_DIR                         (0x1 << 12)
+#define AST_I2CD_BUS_RECOVER_CMD                       (0x1 << 11)
+#define AST_I2CD_S_ALT_EN                              (0x1 << 10)
+#define AST_I2CD_RX_DMA_ENABLE                         (0x1 << 9)
+#define AST_I2CD_TX_DMA_ENABLE                         (0x1 << 8)
+
+/* Command Bit */
+#define AST_I2CD_RX_BUFF_ENABLE                                (0x1 << 7)
+#define AST_I2CD_TX_BUFF_ENABLE                                (0x1 << 6)
+#define AST_I2CD_M_STOP_CMD                                    (0x1 << 5)
+#define AST_I2CD_M_S_RX_CMD_LAST                       (0x1 << 4)
+#define AST_I2CD_M_RX_CMD                                      (0x1 << 3)
+#define AST_I2CD_S_TX_CMD                                      (0x1 << 2)
+#define AST_I2CD_M_TX_CMD                                      (0x1 << 1)

drivers/i2c/ast_i2c.h line 135

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+#define AST_I2CD_M_START_CMD                           (0x1)
+
+/* 0x18 : I2CD Slave Device Address Register   */
+
+/* 0x1C : I2CD Pool Buffer Control Register   */
+#define AST_I2CD_RX_BUF_ADDR_GET(x)                    (((x) >> 24) & 0xff)
+#define AST_I2CD_RX_BUF_END_ADDR_SET(x)                        ((x) << 16)
+#define AST_I2CD_TX_DATA_BUF_END_SET(x)                        (((x) & 0xff) << 8)
+#define AST_I2CD_RX_DATA_BUF_GET(x)                    (((x) >> 8) & 0xff)
+#define AST_I2CD_BUF_BASE_ADDR_SET(x)                  ((x) & 0x3f)

Just use simple shift and mask values, and put the logic in your C code.

Quoted 11 lines
drivers/i2c/ast_i2c.h new file +8 -1
+
+/* 0x20 : I2CD Transmit/Receive Byte Buffer Register   */
+#define AST_I2CD_GET_MODE(x)                           (((x) >> 8) & 0x1)
+
+#define AST_I2CD_RX_BYTE_BUFFER                                        (0xff << 8)
+#define AST_I2CD_TX_BYTE_BUFFER                                        (0xff)
+
+#endif                         /* __AST_I2C_H_ */
--

2.8.0.rc3.226.g39d4020

Regards,
Simon

#17 lore raw

Re: [PATCH u-boot 5/5] aspeed: I2C driver.

[resend from correct address]

Quoted 595 lines · Simon Glass

Hi Maxim,

Quoted 5 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

Please add that into the Kconfig help too.

Quoted 58 lines
---
 drivers/i2c/Kconfig   |   7 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 143 +++++++++++++++++++++++
 4 files changed, 456 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
drivers/i2c/Kconfig +7 -0
index 6e22bba..720c475 100644
@@ -90,6 +90,13 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
          enable status register. This config option can be enabled in such
          cases.
 
+config SYS_I2C_AST
+       bool "Aspeed I2C Controller"
+       depends on DM_I2C
+       help
+         Say yes here to select Aspeed I2C Host Controller. The driver
+         supports AST2500 and AST2400 controllers.
+
 config SYS_I2C_INTEL
        bool "Intel I2C/SMBUS driver"
        depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +11 -0
new file mode 100644
index 0000000..f2c132e
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>

drivers/i2c/ast_i2c.c line 21

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+#include <i2c.h>
+
+#include <asm/arch/ast_scu.h>
+#include <asm/arch/regs-scu.h>
+#include <asm/io.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US (100000)
+#define I2C_SLEEP_STEP (20)

I2C_SLEEP_STEP_US

drivers/i2c/ast_i2c.c line 22

Quoted 1 line
drivers/i2c/ast_i2c.c new file +1 -0
+#define EI2C_TIMEOUT (1001)

EI2C_TIMEOUT_US

Please drop the () on those

drivers/i2c/ast_i2c.c line 26

Quoted 4 lines
drivers/i2c/ast_i2c.c new file +4 -0
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast_i2c {

Please add a struct comment with member info.

drivers/i2c/ast_i2c.c line 32

Quoted 6 lines
drivers/i2c/ast_i2c.c new file +6 -0
+       u32 id;
+       struct ast_i2c_regs *regs;
+       int speed;
+};
+
+static u32 get_clk_reg_val(u32 divider_ratio)

Function comment. Consider returning ulong.

drivers/i2c/ast_i2c.c line 44

Quoted 12 lines
drivers/i2c/ast_i2c.c new file +12 -0
+{
+       unsigned int inc = 0, div;
+       u32 scl_low, scl_high, data;
+
+       for (div = 0; divider_ratio >= 16; div++) {
+               inc |= (divider_ratio & 1);
+               divider_ratio >>= 1;
+       }
+       divider_ratio += inc;
+       scl_low = (divider_ratio >> 1) - 1;
+       scl_high = divider_ratio - scl_low - 2;
+       data = 0x77700300 | (scl_high << 16) | (scl_low << 12) | div;

blank link here. What is the magic 0x77700300 for? Should either have a comment or a #define

drivers/i2c/ast_i2c.c line 57

Quoted 13 lines
drivers/i2c/ast_i2c.c new file +13 -0
+       return data;
+}
+
+static inline void ast_i2c_clear_interrupts(struct ast_i2c_regs *i2c_base)
+{
+       writel(~0, &i2c_base->isr);
+}
+
+static void ast_i2c_init_bus(struct ast_i2c *i2c_bus)
+{
+       /* Reset device */
+       writel(0, &i2c_bus->regs->fcr);
+       /* Enable Master Mode. Assuming single-master. */

nit: Please avoid '.' at end of comments

Quoted 15 lines
drivers/i2c/ast_i2c.c new file +15 -0
+       debug("Enable Master for %p\n", i2c_bus->regs);
+       writel(AST_I2CD_MASTER_EN
+              | AST_I2CD_M_SDA_LOCK_EN
+              | AST_I2CD_MULTI_MASTER_DIS | AST_I2CD_M_SCL_DRIVE_EN,
+              &i2c_bus->regs->fcr);
+       debug("FCR: %p\n", &i2c_bus->regs->fcr);
+       /* Enable Interrupts */
+       writel(AST_I2CD_INTR_TX_ACK
+              | AST_I2CD_INTR_TX_NAK
+              | AST_I2CD_INTR_RX_DONE
+              | AST_I2CD_INTR_BUS_RECOVER_DONE
+              | AST_I2CD_INTR_NORMAL_STOP
+              | AST_I2CD_INTR_ABNORMAL, &i2c_bus->regs->icr);
+}
+

drivers/i2c/ast_i2c.c line 82

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+static int ast_i2c_probe(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       debug("Enabling I2C%u\n", dev->seq);
+       ast_scu_enable_i2c(dev->seq);
+
+       i2c_bus->id = dev->seq;
+       struct ast_i2c_regs *i2c_base =
+           (struct ast_i2c_regs *)dev_get_addr(dev);

Can you use dev_get_addr_ptr()? Need to check for NULL and return -EINVAL. Also, reading the device tree should really be in the ofdata_to_platdata() method, not probe().

drivers/i2c/ast_i2c.c line 91

Quoted 9 lines
drivers/i2c/ast_i2c.c new file +9 -0
+       i2c_bus->regs = i2c_base;
+
+       ast_i2c_init_bus(i2c_bus);
+       return 0;
+}
+
+static inline int ast_i2c_wait_isr(struct ast_i2c_regs *i2c_base, u32 flag)
+{
+       int timeout = I2C_TIMEOUT_US;

blank line here

drivers/i2c/ast_i2c.c line 99

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +8 -0
+       while (!(readl(&i2c_base->isr) & flag) && timeout > 0) {
+               udelay(I2C_SLEEP_STEP);
+               timeout -= I2C_SLEEP_STEP;
+       }
 
 
+
+       ast_i2c_clear_interrupts(i2c_base);
+       if (timeout <= 0)
+               return -EI2C_TIMEOUT;

return -ETIMEDOUT

drivers/i2c/ast_i2c.c line 105

Quoted 6 lines
drivers/i2c/ast_i2c.c new file +6 -0
+       return 0;
+}
+
+static inline int ast_i2c_send_stop(struct ast_i2c_regs *i2c_base)
+{
+       writel(AST_I2CD_M_STOP_CMD, &i2c_base->csr);

blank line (please do this before each return)

drivers/i2c/ast_i2c.c line 113

Quoted 8 lines
drivers/i2c/ast_i2c.c new file +8 -0
+       return ast_i2c_wait_isr(i2c_base, AST_I2CD_INTR_NORMAL_STOP);
+}
+
+static inline int ast_i2c_wait_tx(struct ast_i2c_regs *i2c_base)
+{
+       int timeout = I2C_TIMEOUT_US;
+       u32 flag = AST_I2CD_INTR_TX_ACK | AST_I2CD_INTR_TX_NAK;
+       u32 status = readl(&i2c_base->isr) & flag;

blank line (please do this after all decl blocks)

drivers/i2c/ast_i2c.c line 120

Quoted 7 lines
drivers/i2c/ast_i2c.c new file +7 -0
+       while (!status && timeout > 0) {
+               status = readl(&i2c_base->isr) & flag;
+               udelay(I2C_SLEEP_STEP);
+               timeout -= I2C_SLEEP_STEP;
+       }
+
+       int ret = 0;

Move this to top of function. Declarations should all be at the start of the block.

drivers/i2c/ast_i2c.c line 131

Quoted 11 lines
drivers/i2c/ast_i2c.c new file +11 -0
+       if (status == AST_I2CD_INTR_TX_NAK)
+               ret = -EREMOTEIO;
+
+       if (timeout <= 0)
+               ret = -EI2C_TIMEOUT;
+
+       ast_i2c_clear_interrupts(i2c_base);
+       return ret;
+}
+
+static inline int ast_i2c_start_txn(struct ast_i2c_regs *i2c_base, u8 devaddr)

Why inline? The compiler will do that anyway so I think you can drop it. Also please use int or uint for devaddr - particularly on ARM it isn't good to have non-register-sized parameters and return values.

Quoted 16 lines
drivers/i2c/ast_i2c.c new file +16 -0
+{
+       /* Start and Send Device Address */
+       writel(devaddr, &i2c_base->trbbr);
+       writel(AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD, &i2c_base->csr);
+       return ast_i2c_wait_tx(i2c_base);
+}
+
+static int ast_i2c_read_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8 *buffer,
+                            size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       int i2c_error =
+           ast_i2c_start_txn(i2c_base, (chip_addr << 1) | I2C_M_RD);
+       if (i2c_error < 0)
+               return i2c_error;

drivers/i2c/ast_i2c.c line 157

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+
+       u32 i2c_cmd = AST_I2CD_M_RX_CMD;
+       for (; len > 0; len--, buffer++) {
+               if (len == 1)
+                       i2c_cmd |= AST_I2CD_M_S_RX_CMD_LAST;
+               writel(i2c_cmd, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_isr(i2c_base, AST_I2CD_INTR_RX_DONE);
+               if (i2c_error < 0)
+                       return i2c_error;
+               *buffer = AST_I2CD_RX_DATA_BUF_GET(readl(&i2c_base->trbbr));

Instead of AST_I2CD_RX_DATA_BUF_GET(), please define something like AST_I2CD_RX_DATA_SHIFT and _MASK and use then here.

#define AST_I2CD_RX_DATA_SHIFT 8
#define AST_I2CD_RX_DATA_MASK (0xff << AST_I2CD_RX_DATA_SHIFT)

Quoted 30 lines
drivers/i2c/ast_i2c.c new file +30 -0
+       }
+       ast_i2c_clear_interrupts(i2c_base);
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;
+}
+
+static int ast_i2c_write_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8
+                             *buffer, size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       int i2c_error = ast_i2c_start_txn(i2c_base, (chip_addr << 1));
+       if (i2c_error < 0)
+               return i2c_error;
+
+       for (; len > 0; len--, buffer++) {
+               writel(*buffer, &i2c_base->trbbr);
+               writel(AST_I2CD_M_TX_CMD, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_tx(i2c_base);
+               if (i2c_error < 0)
+                       return i2c_error;
+       }
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;

drivers/i2c/ast_i2c.c line 197

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       u32 csr = readl(&i2c_base->csr);
+
+       int deblock_error = 0;

Just 'ret' is good enough.

Quoted 25 lines
drivers/i2c/ast_i2c.c new file +25 -0
+       bool sda_high = csr & AST_I2CD_SDA_LINE_STS;
+       bool scl_high = csr & AST_I2CD_SCL_LINE_STS;
+       if (sda_high && scl_high) {
+               /* Bus is idle, no deblocking needed. */
+               return 0;
+       } else if (sda_high) {
+               /* Send stop command */
+               debug("Unterminated TXN in (%x), sending stop\n", csr);
+               deblock_error = ast_i2c_send_stop(i2c_base);
+       } else if (scl_high) {
+               /* Possibly stuck slave */
+               debug("Bus stuck (%x), attempting recovery\n", csr);
+               writel(AST_I2CD_BUS_RECOVER_CMD, &i2c_base->csr);
+               deblock_error = ast_i2c_wait_isr(
+                       i2c_base, AST_I2CD_INTR_BUS_RECOVER_DONE);
+       } else {
+               /* Just try to reinit the device. */
+               ast_i2c_init_bus(i2c_bus);
+       }
+
+       return deblock_error;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{

drivers/i2c/ast_i2c.c line 232

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       int ret;
+
+       (void)ast_i2c_deblock(dev);
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               if (msg->flags & I2C_M_RD) {
+                       debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret =

Can you break the line in the parameters instead of at '=' ?

Quoted 13 lines
drivers/i2c/ast_i2c.c new file +13 -0
+                           ast_i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                               msg->len, (nmsgs == 1));
+               } else {
+                       debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret =
+                           ast_i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                                msg->len, (nmsgs == 1));
+               }
+               if (ret) {
+                       debug("%s: error (%d)\n", __func__, ret);
+                       return -EREMOTEIO;
+               }

drivers/i2c/ast_i2c.c line 255

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       }
+
+       return 0;
+}
+
+static int ast_i2c_set_speed(struct udevice *dev, unsigned int speed)
+{
+       debug("Setting speed ofr I2C%d to <%u>\n", dev->seq, speed);
+       if (!speed) {
+               debug("No valid speed specified.\n");

Drop '.'

Quoted 75 lines
drivers/i2c/ast_i2c.c new file +50 -0
+               return -EINVAL;
+       }
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       i2c_bus->speed = speed;
+       /* TODO: get this from device tree */
+       u32 pclk = ast_get_apbclk();
+       u32 divider = pclk / speed;
+
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       if (speed > 400000) {
+               debug("Enabling High Speed\n");
+               setbits_le32(&i2c_base->fcr, AST_I2CD_M_HIGH_SPEED_EN
+                            | AST_I2CD_M_SDA_DRIVE_1T_EN
+                            | AST_I2CD_SDA_DRIVE_1T_EN);
+               writel(0x3, &i2c_base->cactcr2);
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+       } else {
+               debug("Enabling Normal Speed\n");
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+               writel(AST_NO_TIMEOUT_CTRL, &i2c_base->cactcr2);
+       }
+
+       ast_i2c_clear_interrupts(i2c_base);
+       return 0;
+}
+
+static const struct dm_i2c_ops ast_i2c_ops = {
+       .xfer = ast_i2c_xfer,
+       .set_bus_speed = ast_i2c_set_speed,
+       .deblock = ast_i2c_deblock,
+};
+
+static const struct udevice_id ast_i2c_ids[] = {
+       {.compatible = "aspeed,ast2400-i2c-controller",},
+       {.compatible = "aspeed,ast2400-i2c-bus",},
+       {},
+};
+
+/* Tell GNU Indent to keep this as is: */
+/* *INDENT-OFF* */
+U_BOOT_DRIVER(i2c_aspeed) = {
+       .name = "i2c_aspeed",
+       .id = UCLASS_I2C,
+       .of_match = ast_i2c_ids,
+       .probe = ast_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct ast_i2c),
+       .ops = &ast_i2c_ops,
+};
+/* *INDENT-ON* */
drivers/i2c/ast_i2c.h new file +19 -0
new file mode 100644
index 0000000..8926fd2
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#ifndef __AST_I2C_H_
+#define __AST_I2C_H_
+
+struct ast_i2c_regs {
+       uint32_t fcr;
+       uint32_t cactcr1;
+       uint32_t cactcr2;
+       uint32_t icr;
+       uint32_t isr;
+       uint32_t csr;
+       uint32_t sdar;
+       uint32_t pbcr;

drivers/i2c/ast_i2c.h line 29

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+       uint32_t trbbr;
+#ifdef CONFIG_TARGET_AST_G5
+       uint32_t dma_mbar;
+       uint32_t dma_tlr;
+#endif
+};
+
+/* Device Register Definition */
+/* 0x00 : I2CD Function Control Register  */
+#define AST_I2CD_BUFF_SEL_MASK                         (0x7 << 20)

It's fine to have the AST_I2CD_ prefix if you want it. But it does make things longer, and this header will only be included in one file. So feel free to prune to AST_ if you like.

Quoted 4 lines
drivers/i2c/ast_i2c.h new file +4 -0
+#define AST_I2CD_BUFF_SEL(x)                           (x << 20)
+#define AST_I2CD_M_SDA_LOCK_EN                 (0x1 << 16)
+#define AST_I2CD_MULTI_MASTER_DIS                      (0x1 << 15)
+#define AST_I2CD_M_SCL_DRIVE_EN                (0x1 << 14)

drivers/i2c/ast_i2c.h line 43

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+#define AST_I2CD_MSB_STS                                       (0x1 << 9)
+#define AST_I2CD_SDA_DRIVE_1T_EN                       (0x1 << 8)
+#define AST_I2CD_M_SDA_DRIVE_1T_EN             (0x1 << 7)
+#define AST_I2CD_M_HIGH_SPEED_EN               (0x1 << 6)
+#define AST_I2CD_DEF_ADDR_EN                           (0x1 << 5)
+#define AST_I2CD_DEF_ALERT_EN                          (0x1 << 4)
+#define AST_I2CD_DEF_ARP_EN                                    (0x1 << 3)
+#define AST_I2CD_DEF_GCALL_EN                          (0x1 << 2)
+#define AST_I2CD_SLAVE_EN                                      (0x1 << 1)
+#define AST_I2CD_MASTER_EN                                     (0x1)

Avoid brackets around simple constants

Quoted 82 lines
drivers/i2c/ast_i2c.h new file +82 -0
+
+/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
+#define AST_I2CD_tBUF                                          (0x1 << 28)
+#define AST_I2CD_tHDSTA                                                (0x1 << 24)
+#define AST_I2CD_tACST                                         (0x1 << 20)
+#define AST_I2CD_tCKHIGH                                       (0x1 << 16)
+#define AST_I2CD_tCKLOW                                                (0x1 << 12)
+#define AST_I2CD_tHDDAT                                                (0x1 << 10)
+#define AST_I2CD_CLK_TO_BASE_DIV                       (0x1 << 8)
+#define AST_I2CD_CLK_BASE_DIV                          (0x1)
+
+/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+#define AST_I2CD_tTIMEOUT                                      (0x1)
+#define AST_NO_TIMEOUT_CTRL                                    0x0
+
+/* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+ *
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
+#define AST_I2CD_INTR_SDA_DL_TIMEOUT                   (0x1 << 14)
+#define AST_I2CD_INTR_BUS_RECOVER_DONE                 (0x1 << 13)
+#define AST_I2CD_INTR_SMBUS_ALERT                      (0x1 << 12)
+#define AST_I2CD_INTR_SMBUS_ARP_ADDR                   (0x1 << 11)
+#define AST_I2CD_INTR_SMBUS_DEV_ALERT_ADDR             (0x1 << 10)
+#define AST_I2CD_INTR_SMBUS_DEF_ADDR                   (0x1 << 9)
+#define AST_I2CD_INTR_GCALL_ADDR                       (0x1 << 8)
+#define AST_I2CD_INTR_SLAVE_MATCH                      (0x1 << 7)
+#define AST_I2CD_INTR_SCL_TIMEOUT                      (0x1 << 6)
+#define AST_I2CD_INTR_ABNORMAL                         (0x1 << 5)
+#define AST_I2CD_INTR_NORMAL_STOP                      (0x1 << 4)
+#define AST_I2CD_INTR_ARBIT_LOSS                       (0x1 << 3)
+#define AST_I2CD_INTR_RX_DONE                          (0x1 << 2)
+#define AST_I2CD_INTR_TX_NAK                           (0x1 << 1)
+#define AST_I2CD_INTR_TX_ACK                           (0x1 << 0)
+
+/* 0x14 : I2CD Command/Status Register   */
+#define AST_I2CD_SDA_OE                                        (0x1 << 28)
+#define AST_I2CD_SDA_O                                 (0x1 << 27)
+#define AST_I2CD_SCL_OE                                        (0x1 << 26)
+#define AST_I2CD_SCL_O                                 (0x1 << 25)
+#define AST_I2CD_TX_TIMING                             (0x1 << 24)
+#define AST_I2CD_TX_STATUS                             (0x1 << 23)
+
+/* Tx State Machine */
+#define AST_I2CD_IDLE                                  0x0
+#define AST_I2CD_MACTIVE                               0x8
+#define AST_I2CD_MSTART                                        0x9
+#define AST_I2CD_MSTARTR                               0xa
+#define AST_I2CD_MSTOP                                 0xb
+#define AST_I2CD_MTXD                                  0xc
+#define AST_I2CD_MRXACK                                        0xd
+#define AST_I2CD_MRXD                                  0xe
+#define AST_I2CD_MTXACK                                0xf
+#define AST_I2CD_SWAIT                                 0x1
+#define AST_I2CD_SRXD                                  0x4
+#define AST_I2CD_STXACK                                0x5
+#define AST_I2CD_STXD                                  0x6
+#define AST_I2CD_SRXACK                                0x7
+#define AST_I2CD_RECOVER                               0x3
+
+#define AST_I2CD_SCL_LINE_STS                          (0x1 << 18)
+#define AST_I2CD_SDA_LINE_STS                          (0x1 << 17)
+#define AST_I2CD_BUS_BUSY_STS                          (0x1 << 16)
+#define AST_I2CD_SDA_OE_OUT_DIR                                (0x1 << 15)
+#define AST_I2CD_SDA_O_OUT_DIR                         (0x1 << 14)
+#define AST_I2CD_SCL_OE_OUT_DIR                                (0x1 << 13)
+#define AST_I2CD_SCL_O_OUT_DIR                         (0x1 << 12)
+#define AST_I2CD_BUS_RECOVER_CMD                       (0x1 << 11)
+#define AST_I2CD_S_ALT_EN                              (0x1 << 10)
+#define AST_I2CD_RX_DMA_ENABLE                         (0x1 << 9)
+#define AST_I2CD_TX_DMA_ENABLE                         (0x1 << 8)
+
+/* Command Bit */
+#define AST_I2CD_RX_BUFF_ENABLE                                (0x1 << 7)
+#define AST_I2CD_TX_BUFF_ENABLE                                (0x1 << 6)
+#define AST_I2CD_M_STOP_CMD                                    (0x1 << 5)
+#define AST_I2CD_M_S_RX_CMD_LAST                       (0x1 << 4)
+#define AST_I2CD_M_RX_CMD                                      (0x1 << 3)
+#define AST_I2CD_S_TX_CMD                                      (0x1 << 2)
+#define AST_I2CD_M_TX_CMD                                      (0x1 << 1)

drivers/i2c/ast_i2c.h line 135

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+#define AST_I2CD_M_START_CMD                           (0x1)
+
+/* 0x18 : I2CD Slave Device Address Register   */
+
+/* 0x1C : I2CD Pool Buffer Control Register   */
+#define AST_I2CD_RX_BUF_ADDR_GET(x)                    (((x) >> 24) & 0xff)
+#define AST_I2CD_RX_BUF_END_ADDR_SET(x)                        ((x) << 16)
+#define AST_I2CD_TX_DATA_BUF_END_SET(x)                        (((x) & 0xff) << 8)
+#define AST_I2CD_RX_DATA_BUF_GET(x)                    (((x) >> 8) & 0xff)
+#define AST_I2CD_BUF_BASE_ADDR_SET(x)                  ((x) & 0x3f)

Just use simple shift and mask values, and put the logic in your C code.

Quoted 11 lines
drivers/i2c/ast_i2c.h new file +8 -1
+
+/* 0x20 : I2CD Transmit/Receive Byte Buffer Register   */
+#define AST_I2CD_GET_MODE(x)                           (((x) >> 8) & 0x1)
+
+#define AST_I2CD_RX_BYTE_BUFFER                                        (0xff << 8)
+#define AST_I2CD_TX_BYTE_BUFFER                                        (0xff)
+
+#endif                         /* __AST_I2C_H_ */
--

2.8.0.rc3.226.g39d4020

Regards,
Simon

#18 lore raw

Re: [PATCH u-boot 5/5] aspeed: I2C driver.

All comments will be addressed for the next version.

Quoted 13 lines · Simon Glass

[resend from correct address]

Quoted 10 lines · Simon Glass

Hi Maxim,

Quoted 5 lines · On 22 November 2016 at 16:56, <[email protected]> wrote:

From: Maxim Sloyko <[email protected]>

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

Please add that into the Kconfig help too.

Done.

Quoted 85 lines
Quoted 85 lines
Quoted 59 lines
---
 drivers/i2c/Kconfig   |   7 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 143 +++++++++++++++++++++++
 4 files changed, 456 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
drivers/i2c/Kconfig +7 -0
index 6e22bba..720c475 100644
@@ -90,6 +90,13 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
          enable status register. This config option can be enabled in such
          cases.
 
+config SYS_I2C_AST
+       bool "Aspeed I2C Controller"
+       depends on DM_I2C
+       help
+         Say yes here to select Aspeed I2C Host Controller. The driver
+         supports AST2500 and AST2400 controllers.
+
 config SYS_I2C_INTEL
        bool "Intel I2C/SMBUS driver"
        depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +11 -0
new file mode 100644
index 0000000..f2c132e
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>

drivers/i2c/ast_i2c.c line 21

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+#include <i2c.h>
+
+#include <asm/arch/ast_scu.h>
+#include <asm/arch/regs-scu.h>
+#include <asm/io.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US (100000)
+#define I2C_SLEEP_STEP (20)

I2C_SLEEP_STEP_US

drivers/i2c/ast_i2c.c line 22

Quoted 1 line
drivers/i2c/ast_i2c.c new file +1 -0
+#define EI2C_TIMEOUT (1001)

EI2C_TIMEOUT_US

Please drop the () on those

drivers/i2c/ast_i2c.c line 26

Quoted 4 lines
drivers/i2c/ast_i2c.c new file +4 -0
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast_i2c {

Please add a struct comment with member info.

Quoted 8 lines
Quoted 8 lines

drivers/i2c/ast_i2c.c line 32

Quoted 6 lines
drivers/i2c/ast_i2c.c new file +6 -0
+       u32 id;
+       struct ast_i2c_regs *regs;
+       int speed;
+};
+
+static u32 get_clk_reg_val(u32 divider_ratio)

Function comment. Consider returning ulong.

It calculates register value, so I think it makes sense for it to be u32.

Quoted 492 lines
Quoted 492 lines

drivers/i2c/ast_i2c.c line 44

Quoted 13 lines
drivers/i2c/ast_i2c.c new file +12 -0
+{
+       unsigned int inc = 0, div;
+       u32 scl_low, scl_high, data;
+
+       for (div = 0; divider_ratio >= 16; div++) {
+               inc |= (divider_ratio & 1);
+               divider_ratio >>= 1;
+       }
+       divider_ratio += inc;
+       scl_low = (divider_ratio >> 1) - 1;
+       scl_high = divider_ratio - scl_low - 2;
+       data = 0x77700300 | (scl_high << 16) | (scl_low << 12) | div;

blank link here. What is the magic 0x77700300 for? Should either have a comment or a #define

drivers/i2c/ast_i2c.c line 57

Quoted 13 lines
drivers/i2c/ast_i2c.c new file +13 -0
+       return data;
+}
+
+static inline void ast_i2c_clear_interrupts(struct ast_i2c_regs *i2c_base)
+{
+       writel(~0, &i2c_base->isr);
+}
+
+static void ast_i2c_init_bus(struct ast_i2c *i2c_bus)
+{
+       /* Reset device */
+       writel(0, &i2c_bus->regs->fcr);
+       /* Enable Master Mode. Assuming single-master. */

nit: Please avoid '.' at end of comments

Quoted 15 lines
drivers/i2c/ast_i2c.c new file +15 -0
+       debug("Enable Master for %p\n", i2c_bus->regs);
+       writel(AST_I2CD_MASTER_EN
+              | AST_I2CD_M_SDA_LOCK_EN
+              | AST_I2CD_MULTI_MASTER_DIS | AST_I2CD_M_SCL_DRIVE_EN,
+              &i2c_bus->regs->fcr);
+       debug("FCR: %p\n", &i2c_bus->regs->fcr);
+       /* Enable Interrupts */
+       writel(AST_I2CD_INTR_TX_ACK
+              | AST_I2CD_INTR_TX_NAK
+              | AST_I2CD_INTR_RX_DONE
+              | AST_I2CD_INTR_BUS_RECOVER_DONE
+              | AST_I2CD_INTR_NORMAL_STOP
+              | AST_I2CD_INTR_ABNORMAL, &i2c_bus->regs->icr);
+}
+

drivers/i2c/ast_i2c.c line 82

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+static int ast_i2c_probe(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       debug("Enabling I2C%u\n", dev->seq);
+       ast_scu_enable_i2c(dev->seq);
+
+       i2c_bus->id = dev->seq;
+       struct ast_i2c_regs *i2c_base =
+           (struct ast_i2c_regs *)dev_get_addr(dev);

Can you use dev_get_addr_ptr()? Need to check for NULL and return -EINVAL. Also, reading the device tree should really be in the ofdata_to_platdata() method, not probe().

drivers/i2c/ast_i2c.c line 91

Quoted 9 lines
drivers/i2c/ast_i2c.c new file +9 -0
+       i2c_bus->regs = i2c_base;
+
+       ast_i2c_init_bus(i2c_bus);
+       return 0;
+}
+
+static inline int ast_i2c_wait_isr(struct ast_i2c_regs *i2c_base, u32 flag)
+{
+       int timeout = I2C_TIMEOUT_US;

blank line here

drivers/i2c/ast_i2c.c line 99

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +8 -0
+       while (!(readl(&i2c_base->isr) & flag) && timeout > 0) {
+               udelay(I2C_SLEEP_STEP);
+               timeout -= I2C_SLEEP_STEP;
+       }
 
 
+
+       ast_i2c_clear_interrupts(i2c_base);
+       if (timeout <= 0)
+               return -EI2C_TIMEOUT;

return -ETIMEDOUT

drivers/i2c/ast_i2c.c line 105

Quoted 6 lines
drivers/i2c/ast_i2c.c new file +6 -0
+       return 0;
+}
+
+static inline int ast_i2c_send_stop(struct ast_i2c_regs *i2c_base)
+{
+       writel(AST_I2CD_M_STOP_CMD, &i2c_base->csr);

blank line (please do this before each return)

drivers/i2c/ast_i2c.c line 113

Quoted 8 lines
drivers/i2c/ast_i2c.c new file +8 -0
+       return ast_i2c_wait_isr(i2c_base, AST_I2CD_INTR_NORMAL_STOP);
+}
+
+static inline int ast_i2c_wait_tx(struct ast_i2c_regs *i2c_base)
+{
+       int timeout = I2C_TIMEOUT_US;
+       u32 flag = AST_I2CD_INTR_TX_ACK | AST_I2CD_INTR_TX_NAK;
+       u32 status = readl(&i2c_base->isr) & flag;

blank line (please do this after all decl blocks)

drivers/i2c/ast_i2c.c line 120

Quoted 7 lines
drivers/i2c/ast_i2c.c new file +7 -0
+       while (!status && timeout > 0) {
+               status = readl(&i2c_base->isr) & flag;
+               udelay(I2C_SLEEP_STEP);
+               timeout -= I2C_SLEEP_STEP;
+       }
+
+       int ret = 0;

Move this to top of function. Declarations should all be at the start of the block.

drivers/i2c/ast_i2c.c line 131

Quoted 11 lines
drivers/i2c/ast_i2c.c new file +11 -0
+       if (status == AST_I2CD_INTR_TX_NAK)
+               ret = -EREMOTEIO;
+
+       if (timeout <= 0)
+               ret = -EI2C_TIMEOUT;
+
+       ast_i2c_clear_interrupts(i2c_base);
+       return ret;
+}
+
+static inline int ast_i2c_start_txn(struct ast_i2c_regs *i2c_base, u8 devaddr)

Why inline? The compiler will do that anyway so I think you can drop it. Also please use int or uint for devaddr - particularly on ARM it isn't good to have non-register-sized parameters and return values.

Quoted 16 lines
drivers/i2c/ast_i2c.c new file +16 -0
+{
+       /* Start and Send Device Address */
+       writel(devaddr, &i2c_base->trbbr);
+       writel(AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD, &i2c_base->csr);
+       return ast_i2c_wait_tx(i2c_base);
+}
+
+static int ast_i2c_read_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8 *buffer,
+                            size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       int i2c_error =
+           ast_i2c_start_txn(i2c_base, (chip_addr << 1) | I2C_M_RD);
+       if (i2c_error < 0)
+               return i2c_error;

drivers/i2c/ast_i2c.c line 157

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+
+       u32 i2c_cmd = AST_I2CD_M_RX_CMD;
+       for (; len > 0; len--, buffer++) {
+               if (len == 1)
+                       i2c_cmd |= AST_I2CD_M_S_RX_CMD_LAST;
+               writel(i2c_cmd, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_isr(i2c_base, AST_I2CD_INTR_RX_DONE);
+               if (i2c_error < 0)
+                       return i2c_error;
+               *buffer = AST_I2CD_RX_DATA_BUF_GET(readl(&i2c_base->trbbr));

Instead of AST_I2CD_RX_DATA_BUF_GET(), please define something like AST_I2CD_RX_DATA_SHIFT and _MASK and use then here.

#define AST_I2CD_RX_DATA_SHIFT 8
#define AST_I2CD_RX_DATA_MASK (0xff << AST_I2CD_RX_DATA_SHIFT)

Quoted 30 lines
drivers/i2c/ast_i2c.c new file +30 -0
+       }
+       ast_i2c_clear_interrupts(i2c_base);
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;
+}
+
+static int ast_i2c_write_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8
+                             *buffer, size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       int i2c_error = ast_i2c_start_txn(i2c_base, (chip_addr << 1));
+       if (i2c_error < 0)
+               return i2c_error;
+
+       for (; len > 0; len--, buffer++) {
+               writel(*buffer, &i2c_base->trbbr);
+               writel(AST_I2CD_M_TX_CMD, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_tx(i2c_base);
+               if (i2c_error < 0)
+                       return i2c_error;
+       }
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;

drivers/i2c/ast_i2c.c line 197

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+
+       u32 csr = readl(&i2c_base->csr);
+
+       int deblock_error = 0;

Just 'ret' is good enough.

Quoted 25 lines
drivers/i2c/ast_i2c.c new file +25 -0
+       bool sda_high = csr & AST_I2CD_SDA_LINE_STS;
+       bool scl_high = csr & AST_I2CD_SCL_LINE_STS;
+       if (sda_high && scl_high) {
+               /* Bus is idle, no deblocking needed. */
+               return 0;
+       } else if (sda_high) {
+               /* Send stop command */
+               debug("Unterminated TXN in (%x), sending stop\n", csr);
+               deblock_error = ast_i2c_send_stop(i2c_base);
+       } else if (scl_high) {
+               /* Possibly stuck slave */
+               debug("Bus stuck (%x), attempting recovery\n", csr);
+               writel(AST_I2CD_BUS_RECOVER_CMD, &i2c_base->csr);
+               deblock_error = ast_i2c_wait_isr(
+                       i2c_base, AST_I2CD_INTR_BUS_RECOVER_DONE);
+       } else {
+               /* Just try to reinit the device. */
+               ast_i2c_init_bus(i2c_bus);
+       }
+
+       return deblock_error;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{

drivers/i2c/ast_i2c.c line 232

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       int ret;
+
+       (void)ast_i2c_deblock(dev);
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               if (msg->flags & I2C_M_RD) {
+                       debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret =

Can you break the line in the parameters instead of at '=' ?

Quoted 13 lines
drivers/i2c/ast_i2c.c new file +13 -0
+                           ast_i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                               msg->len, (nmsgs == 1));
+               } else {
+                       debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret =
+                           ast_i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                                msg->len, (nmsgs == 1));
+               }
+               if (ret) {
+                       debug("%s: error (%d)\n", __func__, ret);
+                       return -EREMOTEIO;
+               }

drivers/i2c/ast_i2c.c line 255

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       }
+
+       return 0;
+}
+
+static int ast_i2c_set_speed(struct udevice *dev, unsigned int speed)
+{
+       debug("Setting speed ofr I2C%d to <%u>\n", dev->seq, speed);
+       if (!speed) {
+               debug("No valid speed specified.\n");

Drop '.'

Quoted 75 lines
drivers/i2c/ast_i2c.c new file +50 -0
+               return -EINVAL;
+       }
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       i2c_bus->speed = speed;
+       /* TODO: get this from device tree */
+       u32 pclk = ast_get_apbclk();
+       u32 divider = pclk / speed;
+
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       if (speed > 400000) {
+               debug("Enabling High Speed\n");
+               setbits_le32(&i2c_base->fcr, AST_I2CD_M_HIGH_SPEED_EN
+                            | AST_I2CD_M_SDA_DRIVE_1T_EN
+                            | AST_I2CD_SDA_DRIVE_1T_EN);
+               writel(0x3, &i2c_base->cactcr2);
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+       } else {
+               debug("Enabling Normal Speed\n");
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+               writel(AST_NO_TIMEOUT_CTRL, &i2c_base->cactcr2);
+       }
+
+       ast_i2c_clear_interrupts(i2c_base);
+       return 0;
+}
+
+static const struct dm_i2c_ops ast_i2c_ops = {
+       .xfer = ast_i2c_xfer,
+       .set_bus_speed = ast_i2c_set_speed,
+       .deblock = ast_i2c_deblock,
+};
+
+static const struct udevice_id ast_i2c_ids[] = {
+       {.compatible = "aspeed,ast2400-i2c-controller",},
+       {.compatible = "aspeed,ast2400-i2c-bus",},
+       {},
+};
+
+/* Tell GNU Indent to keep this as is: */
+/* *INDENT-OFF* */
+U_BOOT_DRIVER(i2c_aspeed) = {
+       .name = "i2c_aspeed",
+       .id = UCLASS_I2C,
+       .of_match = ast_i2c_ids,
+       .probe = ast_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct ast_i2c),
+       .ops = &ast_i2c_ops,
+};
+/* *INDENT-ON* */
drivers/i2c/ast_i2c.h new file +19 -0
new file mode 100644
index 0000000..8926fd2
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#ifndef __AST_I2C_H_
+#define __AST_I2C_H_
+
+struct ast_i2c_regs {
+       uint32_t fcr;
+       uint32_t cactcr1;
+       uint32_t cactcr2;
+       uint32_t icr;
+       uint32_t isr;
+       uint32_t csr;
+       uint32_t sdar;
+       uint32_t pbcr;

drivers/i2c/ast_i2c.h line 29

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+       uint32_t trbbr;
+#ifdef CONFIG_TARGET_AST_G5
+       uint32_t dma_mbar;
+       uint32_t dma_tlr;
+#endif
+};
+
+/* Device Register Definition */
+/* 0x00 : I2CD Function Control Register  */
+#define AST_I2CD_BUFF_SEL_MASK                         (0x7 << 20)

It's fine to have the AST_I2CD_ prefix if you want it. But it does make things longer, and this header will only be included in one file. So feel free to prune to AST_ if you like.

Quoted 4 lines
drivers/i2c/ast_i2c.h new file +4 -0
+#define AST_I2CD_BUFF_SEL(x)                           (x << 20)
+#define AST_I2CD_M_SDA_LOCK_EN                 (0x1 << 16)
+#define AST_I2CD_MULTI_MASTER_DIS                      (0x1 << 15)
+#define AST_I2CD_M_SCL_DRIVE_EN                (0x1 << 14)

drivers/i2c/ast_i2c.h line 43

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+#define AST_I2CD_MSB_STS                                       (0x1 << 9)
+#define AST_I2CD_SDA_DRIVE_1T_EN                       (0x1 << 8)
+#define AST_I2CD_M_SDA_DRIVE_1T_EN             (0x1 << 7)
+#define AST_I2CD_M_HIGH_SPEED_EN               (0x1 << 6)
+#define AST_I2CD_DEF_ADDR_EN                           (0x1 << 5)
+#define AST_I2CD_DEF_ALERT_EN                          (0x1 << 4)
+#define AST_I2CD_DEF_ARP_EN                                    (0x1 << 3)
+#define AST_I2CD_DEF_GCALL_EN                          (0x1 << 2)
+#define AST_I2CD_SLAVE_EN                                      (0x1 << 1)
+#define AST_I2CD_MASTER_EN                                     (0x1)

Avoid brackets around simple constants

Quoted 82 lines
drivers/i2c/ast_i2c.h new file +82 -0
+
+/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
+#define AST_I2CD_tBUF                                          (0x1 << 28)
+#define AST_I2CD_tHDSTA                                                (0x1 << 24)
+#define AST_I2CD_tACST                                         (0x1 << 20)
+#define AST_I2CD_tCKHIGH                                       (0x1 << 16)
+#define AST_I2CD_tCKLOW                                                (0x1 << 12)
+#define AST_I2CD_tHDDAT                                                (0x1 << 10)
+#define AST_I2CD_CLK_TO_BASE_DIV                       (0x1 << 8)
+#define AST_I2CD_CLK_BASE_DIV                          (0x1)
+
+/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+#define AST_I2CD_tTIMEOUT                                      (0x1)
+#define AST_NO_TIMEOUT_CTRL                                    0x0
+
+/* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+ *
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
+#define AST_I2CD_INTR_SDA_DL_TIMEOUT                   (0x1 << 14)
+#define AST_I2CD_INTR_BUS_RECOVER_DONE                 (0x1 << 13)
+#define AST_I2CD_INTR_SMBUS_ALERT                      (0x1 << 12)
+#define AST_I2CD_INTR_SMBUS_ARP_ADDR                   (0x1 << 11)
+#define AST_I2CD_INTR_SMBUS_DEV_ALERT_ADDR             (0x1 << 10)
+#define AST_I2CD_INTR_SMBUS_DEF_ADDR                   (0x1 << 9)
+#define AST_I2CD_INTR_GCALL_ADDR                       (0x1 << 8)
+#define AST_I2CD_INTR_SLAVE_MATCH                      (0x1 << 7)
+#define AST_I2CD_INTR_SCL_TIMEOUT                      (0x1 << 6)
+#define AST_I2CD_INTR_ABNORMAL                         (0x1 << 5)
+#define AST_I2CD_INTR_NORMAL_STOP                      (0x1 << 4)
+#define AST_I2CD_INTR_ARBIT_LOSS                       (0x1 << 3)
+#define AST_I2CD_INTR_RX_DONE                          (0x1 << 2)
+#define AST_I2CD_INTR_TX_NAK                           (0x1 << 1)
+#define AST_I2CD_INTR_TX_ACK                           (0x1 << 0)
+
+/* 0x14 : I2CD Command/Status Register   */
+#define AST_I2CD_SDA_OE                                        (0x1 << 28)
+#define AST_I2CD_SDA_O                                 (0x1 << 27)
+#define AST_I2CD_SCL_OE                                        (0x1 << 26)
+#define AST_I2CD_SCL_O                                 (0x1 << 25)
+#define AST_I2CD_TX_TIMING                             (0x1 << 24)
+#define AST_I2CD_TX_STATUS                             (0x1 << 23)
+
+/* Tx State Machine */
+#define AST_I2CD_IDLE                                  0x0
+#define AST_I2CD_MACTIVE                               0x8
+#define AST_I2CD_MSTART                                        0x9
+#define AST_I2CD_MSTARTR                               0xa
+#define AST_I2CD_MSTOP                                 0xb
+#define AST_I2CD_MTXD                                  0xc
+#define AST_I2CD_MRXACK                                        0xd
+#define AST_I2CD_MRXD                                  0xe
+#define AST_I2CD_MTXACK                                0xf
+#define AST_I2CD_SWAIT                                 0x1
+#define AST_I2CD_SRXD                                  0x4
+#define AST_I2CD_STXACK                                0x5
+#define AST_I2CD_STXD                                  0x6
+#define AST_I2CD_SRXACK                                0x7
+#define AST_I2CD_RECOVER                               0x3
+
+#define AST_I2CD_SCL_LINE_STS                          (0x1 << 18)
+#define AST_I2CD_SDA_LINE_STS                          (0x1 << 17)
+#define AST_I2CD_BUS_BUSY_STS                          (0x1 << 16)
+#define AST_I2CD_SDA_OE_OUT_DIR                                (0x1 << 15)
+#define AST_I2CD_SDA_O_OUT_DIR                         (0x1 << 14)
+#define AST_I2CD_SCL_OE_OUT_DIR                                (0x1 << 13)
+#define AST_I2CD_SCL_O_OUT_DIR                         (0x1 << 12)
+#define AST_I2CD_BUS_RECOVER_CMD                       (0x1 << 11)
+#define AST_I2CD_S_ALT_EN                              (0x1 << 10)
+#define AST_I2CD_RX_DMA_ENABLE                         (0x1 << 9)
+#define AST_I2CD_TX_DMA_ENABLE                         (0x1 << 8)
+
+/* Command Bit */
+#define AST_I2CD_RX_BUFF_ENABLE                                (0x1 << 7)
+#define AST_I2CD_TX_BUFF_ENABLE                                (0x1 << 6)
+#define AST_I2CD_M_STOP_CMD                                    (0x1 << 5)
+#define AST_I2CD_M_S_RX_CMD_LAST                       (0x1 << 4)
+#define AST_I2CD_M_RX_CMD                                      (0x1 << 3)
+#define AST_I2CD_S_TX_CMD                                      (0x1 << 2)
+#define AST_I2CD_M_TX_CMD                                      (0x1 << 1)

drivers/i2c/ast_i2c.h line 135

Quoted 10 lines
drivers/i2c/ast_i2c.h new file +10 -0
+#define AST_I2CD_M_START_CMD                           (0x1)
+
+/* 0x18 : I2CD Slave Device Address Register   */
+
+/* 0x1C : I2CD Pool Buffer Control Register   */
+#define AST_I2CD_RX_BUF_ADDR_GET(x)                    (((x) >> 24) & 0xff)
+#define AST_I2CD_RX_BUF_END_ADDR_SET(x)                        ((x) << 16)
+#define AST_I2CD_TX_DATA_BUF_END_SET(x)                        (((x) & 0xff) << 8)
+#define AST_I2CD_RX_DATA_BUF_GET(x)                    (((x) >> 8) & 0xff)
+#define AST_I2CD_BUF_BASE_ADDR_SET(x)                  ((x) & 0x3f)

Just use simple shift and mask values, and put the logic in your C code.

Quoted 11 lines
drivers/i2c/ast_i2c.h new file +8 -1
+
+/* 0x20 : I2CD Transmit/Receive Byte Buffer Register   */
+#define AST_I2CD_GET_MODE(x)                           (((x) >> 8) & 0x1)
+
+#define AST_I2CD_RX_BYTE_BUFFER                                        (0xff << 8)
+#define AST_I2CD_TX_BYTE_BUFFER                                        (0xff)
+
+#endif                         /* __AST_I2C_H_ */
--

2.8.0.rc3.226.g39d4020

Regards,
Simon

Signature · 1 line
Maxim Sloyko
#19 lore raw
In reply to [email protected]

Hello Maxim,

Am 23.11.2016 um 00:56 schrieb maxims at google.com:

Quoted 3 lines

From: Maxim Sloyko <[email protected]>

This series of patches is only meant for openbmc/u-boot tree.

If this series is not for U-Boot mainline, why do you post this patches on the U-Boot Mailinglist?

bye,
Heiko

Quoted 39 lines

It adds basic support for aspeed i2c. Only single master mode is supported with synchronous transfer.

The style is inconsistent with U-Boot style guide in few places, but follows local style in those files.

Maxim Sloyko (5):
aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include
file), plus minimal device tree configuration for ast2500 eval board.
aspeed: Fixed incosistency in some SCU registers naming.
aspeed: Added function to calculate APB Clock frequency.
aspeed: Added function to configure pins for I2C devices.
aspeed: I2C driver.

  arch/arm/dts/Makefile                       |    2 +
  arch/arm/dts/aspeed-g5-evb.dts              |   28 +
  arch/arm/dts/aspeed-g5.dtsi                 | 1278 +++++++++++++++++++++++++++
  arch/arm/include/asm/arch-aspeed/ast_scu.h  |    6 +
  arch/arm/include/asm/arch-aspeed/regs-scu.h |   73 +-
  arch/arm/mach-aspeed/ast-scu.c              |   41 +-
  drivers/i2c/Kconfig                         |    7 +
  drivers/i2c/Makefile                        |    1 +
  drivers/i2c/ast_i2c.c                       |  305 +++++++
  drivers/i2c/ast_i2c.h                       |  143 +++
  10 files changed, 1851 insertions(+), 33 deletions(-)

create mode 100644 arch/arm/dts/aspeed-g5-evb.dts create mode 100644 arch/arm/dts/aspeed-g5.dtsi create mode 100644 drivers/i2c/ast_i2c.c create mode 100644 drivers/i2c/ast_i2c.h

--
2.8.0.rc3.226.g39d4020

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Signature · 2 lines
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#20 lore raw

cover Aspeed I2C driver, using Driver Model.

Sorry, this was by mistake, please ignore.

Quoted 60 lines · Heiko Schocher

Hello Maxim,

Am 23.11.2016 um 00:56 schrieb maxims at google.com:

Quoted 4 lines

From: Maxim Sloyko <[email protected]>

This series of patches is only meant for openbmc/u-boot tree.

If this series is not for U-Boot mainline, why do you post this patches on the U-Boot Mailinglist?

bye,
Heiko

Quoted 32 lines

It adds basic support for aspeed i2c. Only single master mode is supported with synchronous transfer.

The style is inconsistent with U-Boot style guide in few places, but follows local style in those files.

Maxim Sloyko (5):
aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include
file), plus minimal device tree configuration for ast2500 eval board.
aspeed: Fixed incosistency in some SCU registers naming.
aspeed: Added function to calculate APB Clock frequency.
aspeed: Added function to configure pins for I2C devices.
aspeed: I2C driver.

  arch/arm/dts/Makefile                       |    2 +
  arch/arm/dts/aspeed-g5-evb.dts              |   28 +
  arch/arm/dts/aspeed-g5.dtsi                 | 1278
+++++++++++++++++++++++++++
  arch/arm/include/asm/arch-aspeed/ast_scu.h  |    6 +
  arch/arm/include/asm/arch-aspeed/regs-scu.h |   73 +-
  arch/arm/mach-aspeed/ast-scu.c              |   41 +-
  drivers/i2c/Kconfig                         |    7 +
  drivers/i2c/Makefile                        |    1 +
  drivers/i2c/ast_i2c.c                       |  305 +++++++
  drivers/i2c/ast_i2c.h                       |  143 +++
  10 files changed, 1851 insertions(+), 33 deletions(-)

create mode 100644 arch/arm/dts/aspeed-g5-evb.dts create mode 100644 arch/arm/dts/aspeed-g5.dtsi create mode 100644 drivers/i2c/ast_i2c.c create mode 100644 drivers/i2c/ast_i2c.h

Quoted 9 lines

--
2.8.0.rc3.226.g39d4020

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

Signature · 1 line
*M*axim *S*loyko
#21 lore raw

cover Aspeed I2C driver, using Driver Model.

Hello Maxim,

Am 23.11.2016 um 17:40 schrieb Maxim Sloyko:

Quoted 1 line

Sorry, this was by mistake, please ignore.

no problem at all!

bye,
Heiko

Quoted 67 lines · On Wed, Nov 23, 2016 at 4:28 AM, Heiko Schocher <hs at denx.de…

Hello Maxim,

Am 23.11.2016 um 00:56 schrieb maxims at google.com <mailto:[email protected]>:

From: Maxim Sloyko <maxims at google.com <mailto:[email protected]>>

This series of patches is only meant for openbmc/u-boot tree.

If this series is not for U-Boot mainline, why do you post this patches on the U-Boot Mailinglist?

bye,
Heiko

It adds basic support for aspeed i2c. Only single master mode is supported with synchronous transfer.

The style is inconsistent with U-Boot style guide in few places, but follows local style in those files.

Maxim Sloyko (5):
aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include
file), plus minimal device tree configuration for ast2500 eval board.
aspeed: Fixed incosistency in some SCU registers naming.
aspeed: Added function to calculate APB Clock frequency.
aspeed: Added function to configure pins for I2C devices.
aspeed: I2C driver.

arch/arm/dts/Makefile | 2 +
arch/arm/dts/aspeed-g5-evb.dts | 28 +
arch/arm/dts/aspeed-g5.dtsi | 1278 +++++++++++++++++++++++++++
arch/arm/include/asm/arch-aspeed/ast_scu.h | 6 +
arch/arm/include/asm/arch-aspeed/regs-scu.h | 73 +-
arch/arm/mach-aspeed/ast-scu.c | 41 +-
drivers/i2c/Kconfig | 7 +
drivers/i2c/Makefile | 1 +
drivers/i2c/ast_i2c.c | 305 +++++++
drivers/i2c/ast_i2c.h | 143 +++
10 files changed, 1851 insertions(+), 33 deletions(-) create mode 100644 arch/arm/dts/aspeed-g5-evb.dts create mode 100644 arch/arm/dts/aspeed-g5.dtsi create mode 100644 drivers/i2c/ast_i2c.c create mode 100644 drivers/i2c/ast_i2c.h

--
2.8.0.rc3.226.g39d4020

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de <mailto:[email protected]>
http://lists.denx.de/mailman/listinfo/u-boot <http://lists.denx.de/mailman/listinfo/u-boot>

--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

--
*M*axim *S*loyko

Signature · 2 lines
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#22 lore raw

PATCH 1/6 aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include file), plus minimal device tree configuration for ast2500 eval board

In reply to [email protected]

aspeed-g5.dtsi include file is copied from
https://github.com/openbmc/linux/blob/c5682cb/arch/arm/boot/dts/aspeed-g5.dtsi

---
 arch/arm/dts/Makefile          |    2 +
 arch/arm/dts/aspeed-g5-evb.dts |   28 +
 arch/arm/dts/aspeed-g5.dtsi    | 1278 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1308 insertions(+)
 create mode 100644 arch/arm/dts/aspeed-g5-evb.dts
 create mode 100644 arch/arm/dts/aspeed-g5.dtsi
arch/arm/dts/Makefile +2 -0
index ef573ec..333bf3b 100644
@@ -262,6 +262,8 @@ dtb-$(CONFIG_SOC_KEYSTONE) += k2hk-evm.dtb \
 	k2e-evm.dtb \
 	k2g-evm.dtb
 
+dtb-$(CONFIG_TARGET_AST_G5) += aspeed-g5-evb.dtb
+
 targets += $(dtb-y)
 
 # Add any required device tree compiler flags here
arch/arm/dts/aspeed-g5-evb.dts new file +28 -0
new file mode 100644
index 0000000..95dc77a
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+
+/ {
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;
+	};
+
+	aliases {
+		i2c1 = &i2c0;
+		i2c4 = &i2c3;
+		i2c8 = &i2c7;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&i2c3 {
+	status = "okay";
+};
+
+&i2c7 {
+	status = "okay";
+};
arch/arm/dts/aspeed-g5.dtsi new file +1278 -0

1,278 lines not on this page · raw message

Signature · 1 line
2.8.0.rc3.226.g39d4020
#23 lore raw

PATCH 2/6 aspeed: Fix FUC/FUN typo in SCU

Change FUC to FUN in SCU registers naming, which was a typo that go out of hand

---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 64 ++++++++++++++---------------
 arch/arm/mach-aspeed/ast-scu.c              |  2 +-
 2 files changed, 33 insertions(+), 33 deletions(-)
arch/arm/include/asm/arch-aspeed/regs-scu.h +32 -32
index b714fa9..5445023 100644
@@ -830,49 +830,49 @@
 /* AST_SCU_FUN_PIN_CTRL5		0x90 - Multi-function Pin Control#5 */
 #define SCU_FUN_PIN_SPICS1		(0x1 << 31)
 #define SCU_FUN_PIN_LPC_PLUS		(0x1 << 30)
-#define SCU_FUC_PIN_USB20_HOST		(0x1 << 29)
-#define SCU_FUC_PIN_USB11_PORT4		(0x1 << 28)
-#define SCU_FUC_PIN_I2C14		(0x1 << 27)
-#define SCU_FUC_PIN_I2C13		(0x1 << 26)
-#define SCU_FUC_PIN_I2C12		(0x1 << 25)
-#define SCU_FUC_PIN_I2C11		(0x1 << 24)
-#define SCU_FUC_PIN_I2C10		(0x1 << 23)
-#define SCU_FUC_PIN_I2C9		(0x1 << 22)
-#define SCU_FUC_PIN_I2C8		(0x1 << 21)
-#define SCU_FUC_PIN_I2C7		(0x1 << 20)
-#define SCU_FUC_PIN_I2C6		(0x1 << 19)
-#define SCU_FUC_PIN_I2C5		(0x1 << 18)
-#define SCU_FUC_PIN_I2C4		(0x1 << 17)
-#define SCU_FUC_PIN_I2C3		(0x1 << 16)
-#define SCU_FUC_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
-#define SCU_FUC_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
-#define SCU_FUC_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
-#define SCU_FUC_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
-
-#define SCU_FUC_PIN_MII2_TX_DRIV(x)	(x << 10)
-#define SCU_FUC_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
-#define SCU_FUC_PIN_MII1_TX_DRIV(x)	(x << 8)
-#define SCU_FUC_PIN_MII1_TX_DRIV_MASK	(0x3 << 8)
+#define SCU_FUN_PIN_USB20_HOST		(0x1 << 29)
+#define SCU_FUN_PIN_USB11_PORT4		(0x1 << 28)
+#define SCU_FUN_PIN_I2C14		(0x1 << 27)
+#define SCU_FUN_PIN_I2C13		(0x1 << 26)
+#define SCU_FUN_PIN_I2C12		(0x1 << 25)
+#define SCU_FUN_PIN_I2C11		(0x1 << 24)
+#define SCU_FUN_PIN_I2C10		(0x1 << 23)
+#define SCU_FUN_PIN_I2C9		(0x1 << 22)
+#define SCU_FUN_PIN_I2C8		(0x1 << 21)
+#define SCU_FUN_PIN_I2C7		(0x1 << 20)
+#define SCU_FUN_PIN_I2C6		(0x1 << 19)
+#define SCU_FUN_PIN_I2C5		(0x1 << 18)
+#define SCU_FUN_PIN_I2C4		(0x1 << 17)
+#define SCU_FUN_PIN_I2C3		(0x1 << 16)
+#define SCU_FUN_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
+#define SCU_FUN_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
+#define SCU_FUN_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
+#define SCU_FUN_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
+
+#define SCU_FUN_PIN_MII2_TX_DRIV(x)	(x << 10)
+#define SCU_FUN_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
+#define SCU_FUN_PIN_MII1_TX_DRIV(x)	(x << 8)
+#define SCU_FUN_PIN_MII1_TX_DRIV_MASK	(0x3 << 8)
 
 #define MII_NORMAL_DRIV			0x0
 #define MII_HIGH_DRIV			0x2
 
-#define SCU_FUC_PIN_UART6		(0x1 << 7)
-#define SCU_FUC_PIN_ROM_16BIT		(0x1 << 6)
-#define SCU_FUC_PIN_DIGI_V_OUT(x)	(x)
-#define SCU_FUC_PIN_DIGI_V_OUT_MASK	(0x3)
+#define SCU_FUN_PIN_UART6		(0x1 << 7)
+#define SCU_FUN_PIN_ROM_16BIT		(0x1 << 6)
+#define SCU_FUN_PIN_DIGI_V_OUT(x)	(x)
+#define SCU_FUN_PIN_DIGI_V_OUT_MASK	(0x3)
 
 #define VIDEO_DISABLE			0x0
 #define VIDEO_12BITS			0x1
 #define VIDEO_24BITS			0x2
 //#define VIDEO_DISABLE			0x3
 
-#define SCU_FUC_PIN_USB11_PORT2		(0x1 << 3)
-#define SCU_FUC_PIN_SD1_8BIT		(0x1 << 3)
+#define SCU_FUN_PIN_USB11_PORT2		(0x1 << 3)
+#define SCU_FUN_PIN_SD1_8BIT		(0x1 << 3)
 
-#define SCU_FUC_PIN_MAC1_MDIO		(0x1 << 2)
-#define SCU_FUC_PIN_SD2			(0x1 << 1)
-#define SCU_FUC_PIN_SD1			(0x1 << 0)
+#define SCU_FUN_PIN_MAC1_MDIO		(0x1 << 2)
+#define SCU_FUN_PIN_SD2			(0x1 << 1)
+#define SCU_FUN_PIN_SD1			(0x1 << 0)
 
 
 /* AST_SCU_FUN_PIN_CTRL6		0x94 - Multi-function Pin Control#6*/
arch/arm/mach-aspeed/ast-scu.c +1 -1
index 0cc0d67..280c421 100644
@@ -394,7 +394,7 @@ void ast_scu_multi_func_eth(u8 num)
 			      AST_SCU_FUN_PIN_CTRL1);
 
 		ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
-			      SCU_FUC_PIN_MAC1_MDIO,
+			      SCU_FUN_PIN_MAC1_MDIO,
 			      AST_SCU_FUN_PIN_CTRL5);
 
 		break;
Signature · 1 line
2.8.0.rc3.226.g39d4020
Reviewed-by on v1 2/6
#24 lore raw

Re: [PATCH u-boot v1 2/6] aspeed: Fix FUC/FUN typo in SCU

Quoted 8 lines · Maxim Sloyko

Change FUC to FUN in SCU registers naming, which was a typo that go out of hand

---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 64 ++++++++++++++---------------
 arch/arm/mach-aspeed/ast-scu.c              |  2 +-
 2 files changed, 33 insertions(+), 33 deletions(-)
#25 lore raw

PATCH 3/6 aspeed/scu: Add definitions needed to configure pins for I2C

In reply to Maxim Sloyko

Add missing definitions for configuring I2C pins

---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/include/asm/arch-aspeed/regs-scu.h +9 -0
index 5445023..6cb4d0d 100644
@@ -844,11 +844,15 @@
 #define SCU_FUN_PIN_I2C5		(0x1 << 18)
 #define SCU_FUN_PIN_I2C4		(0x1 << 17)
 #define SCU_FUN_PIN_I2C3		(0x1 << 16)
+#define SCU_FUN_PIN_I2C(n)		(0x1 << (16 + (n) - 3))
 #define SCU_FUN_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
 #define SCU_FUN_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
 #define SCU_FUN_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
 #define SCU_FUN_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
 
+#define SCU_I2C_MIN_BUS_NUM			(1)
+#define SCU_I2C_MAX_BUS_NUM			(14)
+
 #define SCU_FUN_PIN_MII2_TX_DRIV(x)	(x << 10)
 #define SCU_FUN_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
 #define SCU_FUN_PIN_MII1_TX_DRIV(x)	(x << 8)
@@ -914,6 +918,11 @@
 #define SCU_FUN_PIN_ROMA4		(0x1 << 18)
 #define SCU_FUN_PIN_ROMA3		(0x1 << 17)
 #define SCU_FUN_PIN_ROMA2		(0x1 << 16)
+/* AST2500 only */
+#define SCU_FUN_PIN_SDA2		(0x1 << 15)
+#define SCU_FUN_PIN_SCL2		(0x1 << 14)
+#define SCU_FUN_PIN_SDA1		(0x1 << 13)
+#define SCU_FUN_PIN_SCL1		(0x1 << 12)
 
 /* AST_SCU_FUN_PIN_CTRL9		0xA8 - Multi-function Pin Control#9 */
 #define SCU_FUN_PIN_ROMA21		(0x1 << 3)
Signature · 1 line
2.8.0.rc3.226.g39d4020
#26 lore raw

Re: [PATCH u-boot v1 3/6] aspeed/scu: Add definitions needed to configure pins for I2C

Hi Maxim,

2016-11-23 12:49 GMT-07:00 Maxim Sloyko <[email protected]>:

Quoted 3 lines

Add missing definitions for configuring I2C pins

Please add a change log (try using patman!)

Quoted 10 lines
---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/include/asm/arch-aspeed/regs-scu.h +0 -0
index 5445023..6cb4d0d 100644
@@ -844,11 +844,15 @@
 #define SCU_FUN_PIN_I2C5               (0x1 << 18)

arch/arm/include/asm/arch-aspeed/regs-scu.h line 854

Quoted 10 lines
arch/arm/include/asm/arch-aspeed/regs-scu.h +3 -0
 #define SCU_FUN_PIN_I2C4               (0x1 << 17)
 #define SCU_FUN_PIN_I2C3               (0x1 << 16)
+#define SCU_FUN_PIN_I2C(n)             (0x1 << (16 + (n) - 3))
 #define SCU_FUN_PIN_MII2_RX_DWN_DIS    (0x1 << 15)
 #define SCU_FUN_PIN_MII2_TX_DWN_DIS    (0x1 << 14)
 #define SCU_FUN_PIN_MII1_RX_DWN_DIS    (0x1 << 13)
 #define SCU_FUN_PIN_MII1_TX_DWN_DIS    (0x1 << 12)
 
+#define SCU_I2C_MIN_BUS_NUM                    (1)
+#define SCU_I2C_MAX_BUS_NUM                    (14)

Please drop the () on these

Quoted 17 lines
arch/arm/include/asm/arch-aspeed/regs-scu.h +6 -1
+
 #define SCU_FUN_PIN_MII2_TX_DRIV(x)    (x << 10)
 #define SCU_FUN_PIN_MII2_TX_DRIV_MASK  (0x3 << 10)
 #define SCU_FUN_PIN_MII1_TX_DRIV(x)    (x << 8)
@@ -914,6 +918,11 @@
 #define SCU_FUN_PIN_ROMA4              (0x1 << 18)
 #define SCU_FUN_PIN_ROMA3              (0x1 << 17)
 #define SCU_FUN_PIN_ROMA2              (0x1 << 16)
+/* AST2500 only */
+#define SCU_FUN_PIN_SDA2               (0x1 << 15)
+#define SCU_FUN_PIN_SCL2               (0x1 << 14)
+#define SCU_FUN_PIN_SDA1               (0x1 << 13)
+#define SCU_FUN_PIN_SCL1               (0x1 << 12)
 
 /* AST_SCU_FUN_PIN_CTRL9               0xA8 - Multi-function Pin Control#9 */
 #define SCU_FUN_PIN_ROMA21             (0x1 << 3)
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

#27 lore raw

PATCH 4/6 aspeed: Add function to calculate APB Clock frequency

In reply to Maxim Sloyko

This is needed by I2C driver.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  4 ++++
 arch/arm/mach-aspeed/ast-scu.c             | 13 +++++++++++++
 2 files changed, 17 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +4 -0
index d248416..6f00e37 100644
@@ -38,6 +38,10 @@ extern void ast_scu_get_who_init_dram(void);
 extern u32 ast_get_clk_source(void);
 extern u32 ast_get_h_pll_clk(void);
 extern u32 ast_get_ahbclk(void);
+/*
+ * Return the frequency of APB clock
+ */
+extern u32 ast_get_apbclk(void);
 
 extern u32 ast_scu_get_vga_memsize(void);
 
arch/arm/mach-aspeed/ast-scu.c +13 -0
index 280c421..87236e2 100644
@@ -318,6 +318,19 @@ u32 ast_get_ahbclk(void)
 
 #endif /* AST_SOC_G5 */
 
+u32 ast_get_apbclk(void)
+{
+	ulong h_pll = ast_get_h_pll_clk();
+
+	/*
+	 * The formula for converting the bit pattern to divisor is
+	 * (4 + 4 * DIV), according to datasheet
+	 */
+	ulong apb_div = 4 + 4 * SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL));
+	return h_pll / apb_div;
+}
+
+
 void ast_scu_show_system_info(void)
 {
 
Signature · 1 line
2.8.0.rc3.226.g39d4020
Reviewed-by on v1 4/6
#28 lore raw

Re: [PATCH u-boot v1 4/6] aspeed: Add function to calculate APB Clock frequency

Quoted 7 lines · Maxim Sloyko

This is needed by I2C driver.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  4 ++++
 arch/arm/mach-aspeed/ast-scu.c             | 13 +++++++++++++
 2 files changed, 17 insertions(+)

As discussed this should be a clock driver when it gets to mainline.

- Simon

#29 lore raw

PATCH 5/6 aspeed: Add function to configure pins for I2C devices

In reply to Maxim Sloyko

In the absence of pinmux driver, I2C driver will be configuring pins directly.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  6 ++++++
 arch/arm/mach-aspeed/ast-scu.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +6 -0
index 6f00e37..5ab28cc 100644
@@ -49,4 +49,10 @@ extern void ast_scu_init_eth(u8 num);
 extern void ast_scu_multi_func_eth(u8 num);
 extern void ast_scu_multi_func_romcs(u8 num);
 
+/*
+ * Enable I2C controller and pins for a particular device.
+ * Device numbering starts at 1
+ */
+extern void ast_scu_enable_i2c(u8 num);
+
 #endif
arch/arm/mach-aspeed/ast-scu.c +28 -0
index 87236e2..8232d88 100644
@@ -509,3 +509,31 @@ void ast_scu_get_who_init_dram(void)
 		break;
 	}
 }
+
+void ast_scu_enable_i2c(u8 bus_num)
+{
+	if (bus_num > SCU_I2C_MAX_BUS_NUM) {
+		debug("%s: bus_num is out of range, must be [%d - %d]\n",
+		      __func__, SCU_I2C_MIN_BUS_NUM, SCU_I2C_MAX_BUS_NUM);
+		return;
+	}
+
+	if (bus_num == 0) {
+		/* Enable I2C Controllers */
+		clrbits_le32(AST_SCU_BASE + AST_SCU_RESET, SCU_RESET_I2C);
+	} else if (bus_num >= 3) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL5,
+			     SCU_FUN_PIN_I2C(bus_num));
+	/* In earlier versions of the SoC these pins are always assigned to
+	 * respective I2C buses and require no configuration.
+	 */
+#ifdef AST_SOC_G5
+	} else if (bus_num == 1) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+			     SCU_FUN_PIN_SDA1 | SCU_FUN_PIN_SCL1);
+	} else if (bus_num == 2) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+			     SCU_FUN_PIN_SDA2 | SCU_FUN_PIN_SCL2);
+#endif
+	}
+}
Signature · 1 line
2.8.0.rc3.226.g39d4020
Reviewed-by on v1 5/6
#30 lore raw

Re: [PATCH u-boot v1 5/6] aspeed: Add function to configure pins for I2C devices

Quoted 8 lines · Maxim Sloyko

In the absence of pinmux driver, I2C driver will be configuring pins directly.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  6 ++++++
 arch/arm/mach-aspeed/ast-scu.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

(should be a pinctrl driver when this gets to mainline)

#31 lore raw

PATCH 6/6 aspeed: I2C driver.

In reply to Maxim Sloyko

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 130 ++++++++++++++++++++
 4 files changed, 474 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
drivers/i2c/Kconfig +9 -0
index 6e22bba..425766a 100644
@@ -90,6 +90,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 	  enable status register. This config option can be enabled in such
 	  cases.
 
+config SYS_I2C_AST
+	bool "Aspeed I2C Controller"
+	depends on DM_I2C
+	help
+	  Say yes here to select Aspeed I2C Host Controller. The driver
+	  supports AST2500 and AST2400 controllers, but is very limited.
+	  Only single master mode is supported and only byte-by-byte
+	  synchronous reads and writes are supported, no Pool Buffers or DMA.
+
 config SYS_I2C_INTEL
 	bool "Intel I2C/SMBUS driver"
 	depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +334 -0

334 lines not on this page · raw message

drivers/i2c/ast_i2c.h new file +130 -0

130 lines not on this page · raw message

Signature · 1 line
2.8.0.rc3.226.g39d4020
#32 lore raw

Re: [PATCH u-boot v1 6/6] aspeed: I2C driver.

Hi Maxim,

Quoted 5 lines · Maxim Sloyko

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

Quoted 8 lines
---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 130 ++++++++++++++++++++
 4 files changed, 474 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h

Please add a change log for each version.

Quoted 89 lines
drivers/i2c/Kconfig +9 -0
index 6e22bba..425766a 100644
@@ -90,6 +90,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
          enable status register. This config option can be enabled in such
          cases.
 
+config SYS_I2C_AST
+       bool "Aspeed I2C Controller"
+       depends on DM_I2C
+       help
+         Say yes here to select Aspeed I2C Host Controller. The driver
+         supports AST2500 and AST2400 controllers, but is very limited.
+         Only single master mode is supported and only byte-by-byte
+         synchronous reads and writes are supported, no Pool Buffers or DMA.
+
 config SYS_I2C_INTEL
        bool "Intel I2C/SMBUS driver"
        depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +50 -0
new file mode 100644
index 0000000..e785f22
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <i2c.h>
+
+#include <asm/arch/ast_scu.h>
+#include <asm/arch/regs-scu.h>
+#include <asm/io.h>
+#include <errno.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US 100000
+#define I2C_SLEEP_STEP_US 20
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Device private data
+ */
+struct ast_i2c {
+       /* Device registers */
+       struct ast_i2c_regs *regs;
+       /* I2C speed in Hz */
+       int speed;
+};
+
+/*
+ * Given desired divider ratio, return the value that needs to be set
+ * in Clock and AC Timing Control register
+ */
+static u32 get_clk_reg_val(ulong divider_ratio)
+{
+       ulong inc = 0, div;
+       ulong scl_low, scl_high, data;
+
+       for (div = 0; divider_ratio >= 16; div++) {
+               inc |= (divider_ratio & 1);
+               divider_ratio >>= 1;
+       }
+       divider_ratio += inc;
+       scl_low = (divider_ratio >> 1) - 1;

drivers/i2c/ast_i2c.c line 60

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       scl_high = divider_ratio - scl_low - 2;
+       data = I2CD_CACTC_BASE
+                       | (scl_high << I2CD_TCKHIGH_SHIFT)
+                       | (scl_low << I2CD_TCKLOW_SHIFT)
+                       | (div << I2CD_BASE_DIV_SHIFT);
+
+       return data;
+}
+
+static inline void ast_i2c_clear_interrupts(struct ast_i2c_regs *i2c_base)

Drop the inline

Quoted 18 lines
drivers/i2c/ast_i2c.c new file +18 -0
+{
+       writel(~0, &i2c_base->isr);
+}
+
+static void ast_i2c_init_bus(struct ast_i2c *i2c_bus)
+{
+       /* Reset device */
+       writel(0, &i2c_bus->regs->fcr);
+       /* Enable Master Mode. Assuming single-master */
+       debug("Enable Master for %p\n", i2c_bus->regs);
+       writel(I2CD_MASTER_EN
+              | I2CD_M_SDA_LOCK_EN
+              | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
+              &i2c_bus->regs->fcr);
+       debug("FCR: %p\n", &i2c_bus->regs->fcr);
+       /* Enable Interrupts */
+       writel(I2CD_INTR_TX_ACK
+              | I2CD_INTR_TX_NAK

drivers/i2c/ast_i2c.c line 88

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+              | I2CD_INTR_RX_DONE
+              | I2CD_INTR_BUS_RECOVER_DONE
+              | I2CD_INTR_NORMAL_STOP
+              | I2CD_INTR_ABNORMAL, &i2c_bus->regs->icr);
+}
+
+static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = dev_get_addr_ptr(dev);

blank line here

drivers/i2c/ast_i2c.c line 89

Quoted 1 line
drivers/i2c/ast_i2c.c new file +1 -0
+       if (IS_ERR(i2c_base))

Actually this is supposed to return NULL if it fails (see the function comment), but I see that the impl does not. It returns FDT_ADDR_T_NONE. The correct fix would be to add a new patch to update dev_get_addr_ptr() to return NULL in this case, I think.

Quoted 121 lines
drivers/i2c/ast_i2c.c new file +121 -0
+               return PTR_ERR(i2c_base);
+
+       i2c_bus->regs = i2c_base;
+
+       return 0;
+}
+
+static int ast_i2c_probe(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       debug("Enabling I2C%u\n", dev->seq);
+       ast_scu_enable_i2c(dev->seq);
+
+       ast_i2c_init_bus(i2c_bus);
+
+       return 0;
+}
+
+static inline int ast_i2c_wait_isr(struct ast_i2c_regs *i2c_base, u32 flag)
+{
+       int timeout = I2C_TIMEOUT_US;
+
+       while (!(readl(&i2c_base->isr) & flag) && timeout > 0) {
+               udelay(I2C_SLEEP_STEP_US);
+               timeout -= I2C_SLEEP_STEP_US;
+       }
+
+       ast_i2c_clear_interrupts(i2c_base);
+       if (timeout <= 0)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static inline int ast_i2c_send_stop(struct ast_i2c_regs *i2c_base)
+{
+       writel(I2CD_M_STOP_CMD, &i2c_base->csr);
+
+       return ast_i2c_wait_isr(i2c_base, I2CD_INTR_NORMAL_STOP);
+}
+
+static inline int ast_i2c_wait_tx(struct ast_i2c_regs *i2c_base)
+{
+       int timeout = I2C_TIMEOUT_US;
+       u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
+       u32 status = readl(&i2c_base->isr) & flag;
+       int ret = 0;
+
+       while (!status && timeout > 0) {
+               status = readl(&i2c_base->isr) & flag;
+               udelay(I2C_SLEEP_STEP_US);
+               timeout -= I2C_SLEEP_STEP_US;
+       }
+
+       if (status == I2CD_INTR_TX_NAK)
+               ret = -EREMOTEIO;
+
+       if (timeout <= 0)
+               ret = -ETIMEDOUT;
+
+       ast_i2c_clear_interrupts(i2c_base);
+
+       return ret;
+}
+
+static int ast_i2c_start_txn(struct ast_i2c_regs *i2c_base, uint devaddr)
+{
+       /* Start and Send Device Address */
+       writel(devaddr, &i2c_base->trbbr);
+       writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &i2c_base->csr);
+
+       return ast_i2c_wait_tx(i2c_base);
+}
+
+static int ast_i2c_read_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8 *buffer,
+                            size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       int i2c_error =
+           ast_i2c_start_txn(i2c_base, (chip_addr << 1) | I2C_M_RD);
+       u32 i2c_cmd = I2CD_M_RX_CMD;
+
+       if (i2c_error < 0)
+               return i2c_error;
+
+       for (; len > 0; len--, buffer++) {
+               if (len == 1)
+                       i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
+               writel(i2c_cmd, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_isr(i2c_base, I2CD_INTR_RX_DONE);
+               if (i2c_error < 0)
+                       return i2c_error;
+               *buffer = (readl(&i2c_base->trbbr) & I2CD_RX_DATA_MASK)
+                               >> I2CD_RX_DATA_SHIFT;
+       }
+       ast_i2c_clear_interrupts(i2c_base);
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;
+}
+
+static int ast_i2c_write_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8
+                             *buffer, size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       int i2c_error = ast_i2c_start_txn(i2c_base, (chip_addr << 1));
+
+       if (i2c_error < 0)
+               return i2c_error;
+
+       for (; len > 0; len--, buffer++) {
+               writel(*buffer, &i2c_base->trbbr);
+               writel(I2CD_M_TX_CMD, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_tx(i2c_base);
+               if (i2c_error < 0)
+                       return i2c_error;
+       }
+

drivers/i2c/ast_i2c.c line 220

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;

drop blank line

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+
+       u32 csr = readl(&i2c_base->csr);
+       bool sda_high = csr & I2CD_SDA_LINE_STS;
+       bool scl_high = csr & I2CD_SCL_LINE_STS;
+
+       int ret = 0;
+
+       if (sda_high && scl_high) {
+               /* Bus is idle, no deblocking needed. */
+               return 0;

drivers/i2c/ast_i2c.c line 240

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       } else if (sda_high) {
+               /* Send stop command */
+               debug("Unterminated TXN in (%x), sending stop\n", csr);
+               ret = ast_i2c_send_stop(i2c_base);
+       } else if (scl_high) {
+               /* Possibly stuck slave */
+               debug("Bus stuck (%x), attempting recovery\n", csr);
+               writel(I2CD_BUS_RECOVER_CMD, &i2c_base->csr);
+               ret = ast_i2c_wait_isr(
+                       i2c_base, I2CD_INTR_BUS_RECOVER_DONE);

Parameters should go on the same line as the function name - if you split over, align with the '('.

Quoted 4 lines
drivers/i2c/ast_i2c.c new file +4 -0
+       } else {
+               /* Just try to reinit the device. */
+               ast_i2c_init_bus(i2c_bus);
+       }

drivers/i2c/ast_i2c.c line 254

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+
+       return ret;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       int ret;
+
+       (void)ast_i2c_deblock(dev);

Is this because you want to ignore the error? If so please add a comment. If not, just return the error here.

Quoted 217 lines
drivers/i2c/ast_i2c.c new file +80 -0
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               if (msg->flags & I2C_M_RD) {
+                       debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret = ast_i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                               msg->len, (nmsgs == 1));
+               } else {
+                       debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret = ast_i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                                msg->len, (nmsgs == 1));
+               }
+               if (ret) {
+                       debug("%s: error (%d)\n", __func__, ret);
+                       return -EREMOTEIO;
+               }
+       }
+
+       return 0;
+}
+
+static int ast_i2c_set_speed(struct udevice *dev, unsigned int speed)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       ulong pclk, divider;
+
+       debug("Setting speed ofr I2C%d to <%u>\n", dev->seq, speed);
+       if (!speed) {
+               debug("No valid speed specified\n");
+               return -EINVAL;
+       }
+
+       pclk = ast_get_apbclk();
+       divider = pclk / speed;
+
+       i2c_bus->speed = speed;
+       if (speed > 400000) {
+               debug("Enabling High Speed\n");
+               setbits_le32(&i2c_base->fcr, I2CD_M_HIGH_SPEED_EN
+                            | I2CD_M_SDA_DRIVE_1T_EN
+                            | I2CD_SDA_DRIVE_1T_EN);
+               writel(0x3, &i2c_base->cactcr2);
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+       } else {
+               debug("Enabling Normal Speed\n");
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+               writel(I2CD_NO_TIMEOUT_CTRL, &i2c_base->cactcr2);
+       }
+
+       ast_i2c_clear_interrupts(i2c_base);
+
+       return 0;
+}
+
+static const struct dm_i2c_ops ast_i2c_ops = {
+       .xfer = ast_i2c_xfer,
+       .set_bus_speed = ast_i2c_set_speed,
+       .deblock = ast_i2c_deblock,
+};
+
+static const struct udevice_id ast_i2c_ids[] = {
+       {.compatible = "aspeed,ast2400-i2c-controller",},
+       {.compatible = "aspeed,ast2400-i2c-bus",},
+       {},
+};
+
+/* Tell GNU Indent to keep this as is: */
+/* *INDENT-OFF* */
+U_BOOT_DRIVER(i2c_aspeed) = {
+       .name = "i2c_aspeed",
+       .id = UCLASS_I2C,
+       .of_match = ast_i2c_ids,
+       .probe = ast_i2c_probe,
+       .ofdata_to_platdata = ast_i2c_ofdata_to_platdata,
+       .priv_auto_alloc_size = sizeof(struct ast_i2c),
+       .ops = &ast_i2c_ops,
+};
+/* *INDENT-ON* */
drivers/i2c/ast_i2c.h new file +130 -1
new file mode 100644
index 0000000..ecdb4fe
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#ifndef __AST_I2C_H_
+#define __AST_I2C_H_
+
+struct ast_i2c_regs {
+       u32 fcr;
+       u32 cactcr1;
+       u32 cactcr2;
+       u32 icr;
+       u32 isr;
+       u32 csr;
+       u32 sdar;
+       u32 pbcr;
+       u32 trbbr;
+#ifdef CONFIG_TARGET_AST_G5
+       u32 dma_mbar;
+       u32 dma_tlr;
+#endif
+};
+
+/* Device Register Definition */
+/* 0x00 : I2CD Function Control Register  */
+#define I2CD_BUFF_SEL_MASK                             (0x7 << 20)
+#define I2CD_BUFF_SEL(x)                               (x << 20)
+#define I2CD_M_SDA_LOCK_EN                     (0x1 << 16)
+#define I2CD_MULTI_MASTER_DIS                  (0x1 << 15)
+#define I2CD_M_SCL_DRIVE_EN            (0x1 << 14)
+#define I2CD_MSB_STS                                   (0x1 << 9)
+#define I2CD_SDA_DRIVE_1T_EN                   (0x1 << 8)
+#define I2CD_M_SDA_DRIVE_1T_EN         (0x1 << 7)
+#define I2CD_M_HIGH_SPEED_EN           (0x1 << 6)
+#define I2CD_DEF_ADDR_EN                               (0x1 << 5)
+#define I2CD_DEF_ALERT_EN                              (0x1 << 4)
+#define I2CD_DEF_ARP_EN                                        (0x1 << 3)
+#define I2CD_DEF_GCALL_EN                              (0x1 << 2)
+#define I2CD_SLAVE_EN                                  (0x1 << 1)
+#define I2CD_MASTER_EN                                 (0x1)
+
+/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
+/* Base register value. These bits are always set by the driver. */
+#define I2CD_CACTC_BASE                        0xfff00300
+#define I2CD_TCKHIGH_SHIFT                     16
+#define I2CD_TCKLOW_SHIFT                      12
+#define I2CD_THDDAT_SHIFT                      10
+#define I2CD_TO_DIV_SHIFT                      8
+#define I2CD_BASE_DIV_SHIFT                    0
+
+/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+#define I2CD_tTIMEOUT                                  1
+#define I2CD_NO_TIMEOUT_CTRL                   0
+
+/* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+ *
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
+#define I2CD_INTR_SDA_DL_TIMEOUT                       (0x1 << 14)
+#define I2CD_INTR_BUS_RECOVER_DONE                     (0x1 << 13)
+#define I2CD_INTR_SMBUS_ALERT                  (0x1 << 12)
+#define I2CD_INTR_SMBUS_ARP_ADDR                       (0x1 << 11)
+#define I2CD_INTR_SMBUS_DEV_ALERT_ADDR         (0x1 << 10)
+#define I2CD_INTR_SMBUS_DEF_ADDR                       (0x1 << 9)
+#define I2CD_INTR_GCALL_ADDR                   (0x1 << 8)
+#define I2CD_INTR_SLAVE_MATCH                  (0x1 << 7)
+#define I2CD_INTR_SCL_TIMEOUT                  (0x1 << 6)
+#define I2CD_INTR_ABNORMAL                             (0x1 << 5)
+#define I2CD_INTR_NORMAL_STOP                  (0x1 << 4)
+#define I2CD_INTR_ARBIT_LOSS                   (0x1 << 3)
+#define I2CD_INTR_RX_DONE                              (0x1 << 2)
+#define I2CD_INTR_TX_NAK                               (0x1 << 1)
+#define I2CD_INTR_TX_ACK                               (0x1 << 0)
+
+/* 0x14 : I2CD Command/Status Register   */
+#define I2CD_SDA_OE                                    (0x1 << 28)
+#define I2CD_SDA_O                                     (0x1 << 27)
+#define I2CD_SCL_OE                                    (0x1 << 26)
+#define I2CD_SCL_O                                     (0x1 << 25)
+#define I2CD_TX_TIMING                         (0x1 << 24)
+#define I2CD_TX_STATUS                         (0x1 << 23)
+
+/* Tx State Machine */
+#define I2CD_IDLE                                      0x0
+#define I2CD_MACTIVE                           0x8
+#define I2CD_MSTART                                    0x9
+#define I2CD_MSTARTR                           0xa
+#define I2CD_MSTOP                                     0xb
+#define I2CD_MTXD                                      0xc
+#define I2CD_MRXACK                                    0xd
+#define I2CD_MRXD                                      0xe
+#define I2CD_MTXACK                            0xf
+#define I2CD_SWAIT                                     0x1
+#define I2CD_SRXD                                      0x4
+#define I2CD_STXACK                            0x5
+#define I2CD_STXD                                      0x6
+#define I2CD_SRXACK                            0x7
+#define I2CD_RECOVER                           0x3
+
+#define I2CD_SCL_LINE_STS                              (0x1 << 18)
+#define I2CD_SDA_LINE_STS                              (0x1 << 17)
+#define I2CD_BUS_BUSY_STS                              (0x1 << 16)
+#define I2CD_SDA_OE_OUT_DIR                            (0x1 << 15)
+#define I2CD_SDA_O_OUT_DIR                             (0x1 << 14)
+#define I2CD_SCL_OE_OUT_DIR                            (0x1 << 13)
+#define I2CD_SCL_O_OUT_DIR                             (0x1 << 12)
+#define I2CD_BUS_RECOVER_CMD                   (0x1 << 11)
+#define I2CD_S_ALT_EN                          (0x1 << 10)
+#define I2CD_RX_DMA_ENABLE                             (0x1 << 9)
+#define I2CD_TX_DMA_ENABLE                             (0x1 << 8)
+
+/* Command Bit */
+#define I2CD_RX_BUFF_ENABLE                            (0x1 << 7)
+#define I2CD_TX_BUFF_ENABLE                            (0x1 << 6)
+#define I2CD_M_STOP_CMD                                        (0x1 << 5)
+#define I2CD_M_S_RX_CMD_LAST                   (0x1 << 4)
+#define I2CD_M_RX_CMD                                  (0x1 << 3)
+#define I2CD_S_TX_CMD                                  (0x1 << 2)
+#define I2CD_M_TX_CMD                                  (0x1 << 1)
+#define I2CD_M_START_CMD                               0x1
+
+#define I2CD_RX_DATA_SHIFT                     8
+#define I2CD_RX_DATA_MASK                      (0xff << I2CD_RX_DATA_SHIFT)
+
+#endif                         /* __AST_I2C_H_ */
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

#33 lore raw

Re: [PATCH u-boot v1 6/6] aspeed: I2C driver.

Quoted 17 lines · Simon Glass

Hi Maxim,

Quoted 5 lines · Maxim Sloyko

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

Quoted 8 lines
---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 130 ++++++++++++++++++++
 4 files changed, 474 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
Quoted 1 line

Please add a change log for each version.

Will do.

Quoted 94 lines
Quoted 94 lines
drivers/i2c/Kconfig +9 -0
index 6e22bba..425766a 100644
@@ -90,6 +90,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
          enable status register. This config option can be enabled in such
          cases.
 
+config SYS_I2C_AST
+       bool "Aspeed I2C Controller"
+       depends on DM_I2C
+       help
+         Say yes here to select Aspeed I2C Host Controller. The driver
+         supports AST2500 and AST2400 controllers, but is very limited.
+         Only single master mode is supported and only byte-by-byte
+         synchronous reads and writes are supported, no Pool Buffers or DMA.
+
 config SYS_I2C_INTEL
        bool "Intel I2C/SMBUS driver"
        depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +54 -0
new file mode 100644
index 0000000..e785f22
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <i2c.h>
+
+#include <asm/arch/ast_scu.h>
+#include <asm/arch/regs-scu.h>
+#include <asm/io.h>
+#include <errno.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US 100000
+#define I2C_SLEEP_STEP_US 20
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Device private data
+ */
+struct ast_i2c {
+       /* Device registers */
+       struct ast_i2c_regs *regs;
+       /* I2C speed in Hz */
+       int speed;
+};
+
+/*
+ * Given desired divider ratio, return the value that needs to be set
+ * in Clock and AC Timing Control register
+ */
+static u32 get_clk_reg_val(ulong divider_ratio)
+{
+       ulong inc = 0, div;
+       ulong scl_low, scl_high, data;
+
+       for (div = 0; divider_ratio >= 16; div++) {
+               inc |= (divider_ratio & 1);
+               divider_ratio >>= 1;
+       }
+       divider_ratio += inc;
+       scl_low = (divider_ratio >> 1) - 1;
+       scl_high = divider_ratio - scl_low - 2;
+       data = I2CD_CACTC_BASE
+                       | (scl_high << I2CD_TCKHIGH_SHIFT)
+                       | (scl_low << I2CD_TCKLOW_SHIFT)
Quoted 8 lines

drivers/i2c/ast_i2c.c line 60

Quoted 6 lines
drivers/i2c/ast_i2c.c new file +6 -0
+                       | (div << I2CD_BASE_DIV_SHIFT);
+
+       return data;
+}
+
+static inline void ast_i2c_clear_interrupts(struct ast_i2c_regs *i2c_base)

Drop the inline

Done

Quoted 32 lines
Quoted 19 lines
drivers/i2c/ast_i2c.c new file +18 -0
+{
+       writel(~0, &i2c_base->isr);
+}
+
+static void ast_i2c_init_bus(struct ast_i2c *i2c_bus)
+{
+       /* Reset device */
+       writel(0, &i2c_bus->regs->fcr);
+       /* Enable Master Mode. Assuming single-master */
+       debug("Enable Master for %p\n", i2c_bus->regs);
+       writel(I2CD_MASTER_EN
+              | I2CD_M_SDA_LOCK_EN
+              | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
+              &i2c_bus->regs->fcr);
+       debug("FCR: %p\n", &i2c_bus->regs->fcr);
+       /* Enable Interrupts */
+       writel(I2CD_INTR_TX_ACK
+              | I2CD_INTR_TX_NAK

drivers/i2c/ast_i2c.c line 88

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+              | I2CD_INTR_RX_DONE
+              | I2CD_INTR_BUS_RECOVER_DONE
+              | I2CD_INTR_NORMAL_STOP
+              | I2CD_INTR_ABNORMAL, &i2c_bus->regs->icr);
+}
+
+static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = dev_get_addr_ptr(dev);

blank line here

Quoted 6 lines

drivers/i2c/ast_i2c.c line 89

Quoted 1 line
drivers/i2c/ast_i2c.c new file +1 -0
+       if (IS_ERR(i2c_base))

Actually this is supposed to return NULL if it fails (see the function comment), but I see that the impl does not. It returns FDT_ADDR_T_NONE. The correct fix would be to add a new patch to update dev_get_addr_ptr() to return NULL in this case, I think.

It probably would not make sense to make this change in this fork. I reverted this back to using dev_get_addr, so it wouldn't rely on incorrect implementation.

Quoted 150 lines
Quoted 122 lines
drivers/i2c/ast_i2c.c new file +121 -0
+               return PTR_ERR(i2c_base);
+
+       i2c_bus->regs = i2c_base;
+
+       return 0;
+}
+
+static int ast_i2c_probe(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+
+       debug("Enabling I2C%u\n", dev->seq);
+       ast_scu_enable_i2c(dev->seq);
+
+       ast_i2c_init_bus(i2c_bus);
+
+       return 0;
+}
+
+static inline int ast_i2c_wait_isr(struct ast_i2c_regs *i2c_base, u32 flag)
+{
+       int timeout = I2C_TIMEOUT_US;
+
+       while (!(readl(&i2c_base->isr) & flag) && timeout > 0) {
+               udelay(I2C_SLEEP_STEP_US);
+               timeout -= I2C_SLEEP_STEP_US;
+       }
+
+       ast_i2c_clear_interrupts(i2c_base);
+       if (timeout <= 0)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static inline int ast_i2c_send_stop(struct ast_i2c_regs *i2c_base)
+{
+       writel(I2CD_M_STOP_CMD, &i2c_base->csr);
+
+       return ast_i2c_wait_isr(i2c_base, I2CD_INTR_NORMAL_STOP);
+}
+
+static inline int ast_i2c_wait_tx(struct ast_i2c_regs *i2c_base)
+{
+       int timeout = I2C_TIMEOUT_US;
+       u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
+       u32 status = readl(&i2c_base->isr) & flag;
+       int ret = 0;
+
+       while (!status && timeout > 0) {
+               status = readl(&i2c_base->isr) & flag;
+               udelay(I2C_SLEEP_STEP_US);
+               timeout -= I2C_SLEEP_STEP_US;
+       }
+
+       if (status == I2CD_INTR_TX_NAK)
+               ret = -EREMOTEIO;
+
+       if (timeout <= 0)
+               ret = -ETIMEDOUT;
+
+       ast_i2c_clear_interrupts(i2c_base);
+
+       return ret;
+}
+
+static int ast_i2c_start_txn(struct ast_i2c_regs *i2c_base, uint devaddr)
+{
+       /* Start and Send Device Address */
+       writel(devaddr, &i2c_base->trbbr);
+       writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &i2c_base->csr);
+
+       return ast_i2c_wait_tx(i2c_base);
+}
+
+static int ast_i2c_read_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8 *buffer,
+                            size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       int i2c_error =
+           ast_i2c_start_txn(i2c_base, (chip_addr << 1) | I2C_M_RD);
+       u32 i2c_cmd = I2CD_M_RX_CMD;
+
+       if (i2c_error < 0)
+               return i2c_error;
+
+       for (; len > 0; len--, buffer++) {
+               if (len == 1)
+                       i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
+               writel(i2c_cmd, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_isr(i2c_base, I2CD_INTR_RX_DONE);
+               if (i2c_error < 0)
+                       return i2c_error;
+               *buffer = (readl(&i2c_base->trbbr) & I2CD_RX_DATA_MASK)
+                               >> I2CD_RX_DATA_SHIFT;
+       }
+       ast_i2c_clear_interrupts(i2c_base);
+
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;
+}
+
+static int ast_i2c_write_data(struct ast_i2c *i2c_bus, u8 chip_addr, u8
+                             *buffer, size_t len, bool send_stop)
+{
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       int i2c_error = ast_i2c_start_txn(i2c_base, (chip_addr << 1));
+
+       if (i2c_error < 0)
+               return i2c_error;
+
+       for (; len > 0; len--, buffer++) {
+               writel(*buffer, &i2c_base->trbbr);
+               writel(I2CD_M_TX_CMD, &i2c_base->csr);
+               i2c_error = ast_i2c_wait_tx(i2c_base);
+               if (i2c_error < 0)
+                       return i2c_error;
+       }
+

drivers/i2c/ast_i2c.c line 220

Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10 -0
+       if (send_stop)
+               return ast_i2c_send_stop(i2c_base);
+
+       return 0;
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;

drop blank line

Quoted 15 lines
drivers/i2c/ast_i2c.c new file +15 -0
+
+       u32 csr = readl(&i2c_base->csr);
+       bool sda_high = csr & I2CD_SDA_LINE_STS;
+       bool scl_high = csr & I2CD_SCL_LINE_STS;
+
+       int ret = 0;
+
+       if (sda_high && scl_high) {
+               /* Bus is idle, no deblocking needed. */
+               return 0;
+       } else if (sda_high) {
+               /* Send stop command */
+               debug("Unterminated TXN in (%x), sending stop\n", csr);
+               ret = ast_i2c_send_stop(i2c_base);
+       } else if (scl_high) {
Quoted 8 lines

drivers/i2c/ast_i2c.c line 240

Quoted 5 lines
drivers/i2c/ast_i2c.c new file +5 -0
+               /* Possibly stuck slave */
+               debug("Bus stuck (%x), attempting recovery\n", csr);
+               writel(I2CD_BUS_RECOVER_CMD, &i2c_base->csr);
+               ret = ast_i2c_wait_isr(
+                       i2c_base, I2CD_INTR_BUS_RECOVER_DONE);

Parameters should go on the same line as the function name - if you split over, align with the '('.

Done. After dropping AST_ from macro name, the line is < 80 chars.

Quoted 10 lines
Quoted 10 lines
drivers/i2c/ast_i2c.c new file +9 -0
+       } else {
+               /* Just try to reinit the device. */
+               ast_i2c_init_bus(i2c_bus);
+       }
+
+       return ret;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
Quoted 8 lines

drivers/i2c/ast_i2c.c line 254

Quoted 5 lines
drivers/i2c/ast_i2c.c new file +5 -0
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       int ret;
+
+       (void)ast_i2c_deblock(dev);

Is this because you want to ignore the error? If so please add a comment. If not, just return the error here.

Done.

Quoted 223 lines
Quoted 218 lines
drivers/i2c/ast_i2c.c new file +80 -0
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               if (msg->flags & I2C_M_RD) {
+                       debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret = ast_i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                               msg->len, (nmsgs == 1));
+               } else {
+                       debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n",
+                             msg->addr, msg->len, msg->flags);
+                       ret = ast_i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                                msg->len, (nmsgs == 1));
+               }
+               if (ret) {
+                       debug("%s: error (%d)\n", __func__, ret);
+                       return -EREMOTEIO;
+               }
+       }
+
+       return 0;
+}
+
+static int ast_i2c_set_speed(struct udevice *dev, unsigned int speed)
+{
+       struct ast_i2c *i2c_bus = dev_get_priv(dev);
+       struct ast_i2c_regs *i2c_base = i2c_bus->regs;
+       ulong pclk, divider;
+
+       debug("Setting speed ofr I2C%d to <%u>\n", dev->seq, speed);
+       if (!speed) {
+               debug("No valid speed specified\n");
+               return -EINVAL;
+       }
+
+       pclk = ast_get_apbclk();
+       divider = pclk / speed;
+
+       i2c_bus->speed = speed;
+       if (speed > 400000) {
+               debug("Enabling High Speed\n");
+               setbits_le32(&i2c_base->fcr, I2CD_M_HIGH_SPEED_EN
+                            | I2CD_M_SDA_DRIVE_1T_EN
+                            | I2CD_SDA_DRIVE_1T_EN);
+               writel(0x3, &i2c_base->cactcr2);
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+       } else {
+               debug("Enabling Normal Speed\n");
+               writel(get_clk_reg_val(divider), &i2c_base->cactcr1);
+               writel(I2CD_NO_TIMEOUT_CTRL, &i2c_base->cactcr2);
+       }
+
+       ast_i2c_clear_interrupts(i2c_base);
+
+       return 0;
+}
+
+static const struct dm_i2c_ops ast_i2c_ops = {
+       .xfer = ast_i2c_xfer,
+       .set_bus_speed = ast_i2c_set_speed,
+       .deblock = ast_i2c_deblock,
+};
+
+static const struct udevice_id ast_i2c_ids[] = {
+       {.compatible = "aspeed,ast2400-i2c-controller",},
+       {.compatible = "aspeed,ast2400-i2c-bus",},
+       {},
+};
+
+/* Tell GNU Indent to keep this as is: */
+/* *INDENT-OFF* */
+U_BOOT_DRIVER(i2c_aspeed) = {
+       .name = "i2c_aspeed",
+       .id = UCLASS_I2C,
+       .of_match = ast_i2c_ids,
+       .probe = ast_i2c_probe,
+       .ofdata_to_platdata = ast_i2c_ofdata_to_platdata,
+       .priv_auto_alloc_size = sizeof(struct ast_i2c),
+       .ops = &ast_i2c_ops,
+};
+/* *INDENT-ON* */
drivers/i2c/ast_i2c.h new file +130 -1
new file mode 100644
index 0000000..ecdb4fe
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#ifndef __AST_I2C_H_
+#define __AST_I2C_H_
+
+struct ast_i2c_regs {
+       u32 fcr;
+       u32 cactcr1;
+       u32 cactcr2;
+       u32 icr;
+       u32 isr;
+       u32 csr;
+       u32 sdar;
+       u32 pbcr;
+       u32 trbbr;
+#ifdef CONFIG_TARGET_AST_G5
+       u32 dma_mbar;
+       u32 dma_tlr;
+#endif
+};
+
+/* Device Register Definition */
+/* 0x00 : I2CD Function Control Register  */
+#define I2CD_BUFF_SEL_MASK                             (0x7 << 20)
+#define I2CD_BUFF_SEL(x)                               (x << 20)
+#define I2CD_M_SDA_LOCK_EN                     (0x1 << 16)
+#define I2CD_MULTI_MASTER_DIS                  (0x1 << 15)
+#define I2CD_M_SCL_DRIVE_EN            (0x1 << 14)
+#define I2CD_MSB_STS                                   (0x1 << 9)
+#define I2CD_SDA_DRIVE_1T_EN                   (0x1 << 8)
+#define I2CD_M_SDA_DRIVE_1T_EN         (0x1 << 7)
+#define I2CD_M_HIGH_SPEED_EN           (0x1 << 6)
+#define I2CD_DEF_ADDR_EN                               (0x1 << 5)
+#define I2CD_DEF_ALERT_EN                              (0x1 << 4)
+#define I2CD_DEF_ARP_EN                                        (0x1 << 3)
+#define I2CD_DEF_GCALL_EN                              (0x1 << 2)
+#define I2CD_SLAVE_EN                                  (0x1 << 1)
+#define I2CD_MASTER_EN                                 (0x1)
+
+/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
+/* Base register value. These bits are always set by the driver. */
+#define I2CD_CACTC_BASE                        0xfff00300
+#define I2CD_TCKHIGH_SHIFT                     16
+#define I2CD_TCKLOW_SHIFT                      12
+#define I2CD_THDDAT_SHIFT                      10
+#define I2CD_TO_DIV_SHIFT                      8
+#define I2CD_BASE_DIV_SHIFT                    0
+
+/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+#define I2CD_tTIMEOUT                                  1
+#define I2CD_NO_TIMEOUT_CTRL                   0
+
+/* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+ *
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
+#define I2CD_INTR_SDA_DL_TIMEOUT                       (0x1 << 14)
+#define I2CD_INTR_BUS_RECOVER_DONE                     (0x1 << 13)
+#define I2CD_INTR_SMBUS_ALERT                  (0x1 << 12)
+#define I2CD_INTR_SMBUS_ARP_ADDR                       (0x1 << 11)
+#define I2CD_INTR_SMBUS_DEV_ALERT_ADDR         (0x1 << 10)
+#define I2CD_INTR_SMBUS_DEF_ADDR                       (0x1 << 9)
+#define I2CD_INTR_GCALL_ADDR                   (0x1 << 8)
+#define I2CD_INTR_SLAVE_MATCH                  (0x1 << 7)
+#define I2CD_INTR_SCL_TIMEOUT                  (0x1 << 6)
+#define I2CD_INTR_ABNORMAL                             (0x1 << 5)
+#define I2CD_INTR_NORMAL_STOP                  (0x1 << 4)
+#define I2CD_INTR_ARBIT_LOSS                   (0x1 << 3)
+#define I2CD_INTR_RX_DONE                              (0x1 << 2)
+#define I2CD_INTR_TX_NAK                               (0x1 << 1)
+#define I2CD_INTR_TX_ACK                               (0x1 << 0)
+
+/* 0x14 : I2CD Command/Status Register   */
+#define I2CD_SDA_OE                                    (0x1 << 28)
+#define I2CD_SDA_O                                     (0x1 << 27)
+#define I2CD_SCL_OE                                    (0x1 << 26)
+#define I2CD_SCL_O                                     (0x1 << 25)
+#define I2CD_TX_TIMING                         (0x1 << 24)
+#define I2CD_TX_STATUS                         (0x1 << 23)
+
+/* Tx State Machine */
+#define I2CD_IDLE                                      0x0
+#define I2CD_MACTIVE                           0x8
+#define I2CD_MSTART                                    0x9
+#define I2CD_MSTARTR                           0xa
+#define I2CD_MSTOP                                     0xb
+#define I2CD_MTXD                                      0xc
+#define I2CD_MRXACK                                    0xd
+#define I2CD_MRXD                                      0xe
+#define I2CD_MTXACK                            0xf
+#define I2CD_SWAIT                                     0x1
+#define I2CD_SRXD                                      0x4
+#define I2CD_STXACK                            0x5
+#define I2CD_STXD                                      0x6
+#define I2CD_SRXACK                            0x7
+#define I2CD_RECOVER                           0x3
+
+#define I2CD_SCL_LINE_STS                              (0x1 << 18)
+#define I2CD_SDA_LINE_STS                              (0x1 << 17)
+#define I2CD_BUS_BUSY_STS                              (0x1 << 16)
+#define I2CD_SDA_OE_OUT_DIR                            (0x1 << 15)
+#define I2CD_SDA_O_OUT_DIR                             (0x1 << 14)
+#define I2CD_SCL_OE_OUT_DIR                            (0x1 << 13)
+#define I2CD_SCL_O_OUT_DIR                             (0x1 << 12)
+#define I2CD_BUS_RECOVER_CMD                   (0x1 << 11)
+#define I2CD_S_ALT_EN                          (0x1 << 10)
+#define I2CD_RX_DMA_ENABLE                             (0x1 << 9)
+#define I2CD_TX_DMA_ENABLE                             (0x1 << 8)
+
+/* Command Bit */
+#define I2CD_RX_BUFF_ENABLE                            (0x1 << 7)
+#define I2CD_TX_BUFF_ENABLE                            (0x1 << 6)
+#define I2CD_M_STOP_CMD                                        (0x1 << 5)
+#define I2CD_M_S_RX_CMD_LAST                   (0x1 << 4)
+#define I2CD_M_RX_CMD                                  (0x1 << 3)
+#define I2CD_S_TX_CMD                                  (0x1 << 2)
+#define I2CD_M_TX_CMD                                  (0x1 << 1)
+#define I2CD_M_START_CMD                               0x1
+
+#define I2CD_RX_DATA_SHIFT                     8
+#define I2CD_RX_DATA_MASK                      (0xff << I2CD_RX_DATA_SHIFT)
+
+#endif                         /* __AST_I2C_H_ */
--
Quoted 2 lines

2.8.0.rc3.226.g39d4020

Regards,
Simon

Signature · 1 line
Maxim Sloyko
Reviewed-by on v1 1/6
#34 lore raw

Re: [PATCH u-boot v1 1/6] aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include file), plus minimal device tree configuration for ast2500 eval board

In reply to Maxim Sloyko
Quoted 11 lines · Maxim Sloyko

aspeed-g5.dtsi include file is copied from
https://github.com/openbmc/linux/blob/c5682cb/arch/arm/boot/dts/aspeed-g5.dtsi

---
 arch/arm/dts/Makefile          |    2 +
 arch/arm/dts/aspeed-g5-evb.dts |   28 +
 arch/arm/dts/aspeed-g5.dtsi    | 1278 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1308 insertions(+)
 create mode 100644 arch/arm/dts/aspeed-g5-evb.dts
 create mode 100644 arch/arm/dts/aspeed-g5.dtsi
#35 lore raw

PATCH v2 1/6 aspeed/g5: Device Tree for ast2500, copied from openbmc/linux (include file), plus minimal device tree configuration for ast2500 eval board

In reply to [email protected]

aspeed-g5.dtsi include file is copied from
https://github.com/openbmc/linux/blob/c5682cb/arch/arm/boot/dts/aspeed-g5.dtsi

---
 arch/arm/dts/Makefile          |    2 +
 arch/arm/dts/aspeed-g5-evb.dts |   28 +
 arch/arm/dts/aspeed-g5.dtsi    | 1278 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1308 insertions(+)
 create mode 100644 arch/arm/dts/aspeed-g5-evb.dts
 create mode 100644 arch/arm/dts/aspeed-g5.dtsi
arch/arm/dts/Makefile +2 -0
index ef573ec..333bf3b 100644
@@ -262,6 +262,8 @@ dtb-$(CONFIG_SOC_KEYSTONE) += k2hk-evm.dtb \
 	k2e-evm.dtb \
 	k2g-evm.dtb
 
+dtb-$(CONFIG_TARGET_AST_G5) += aspeed-g5-evb.dtb
+
 targets += $(dtb-y)
 
 # Add any required device tree compiler flags here
arch/arm/dts/aspeed-g5-evb.dts new file +28 -0
new file mode 100644
index 0000000..95dc77a
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+
+/ {
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;
+	};
+
+	aliases {
+		i2c1 = &i2c0;
+		i2c4 = &i2c3;
+		i2c8 = &i2c7;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&i2c3 {
+	status = "okay";
+};
+
+&i2c7 {
+	status = "okay";
+};
arch/arm/dts/aspeed-g5.dtsi new file +1278 -0

1,278 lines not on this page · raw message

Signature · 1 line
2.8.0.rc3.226.g39d4020
#36 lore raw

PATCH v2 2/6 aspeed: Fix FUC/FUN typo in SCU

Change FUC to FUN in SCU registers naming, which was a typo that go out of hand

---
Changes for v1:

	Patch split into two parts with this part only fixing the FUC->FUN typo.
---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 64 ++++++++++++++---------------
 arch/arm/mach-aspeed/ast-scu.c              |  2 +-
 2 files changed, 33 insertions(+), 33 deletions(-)
arch/arm/include/asm/arch-aspeed/regs-scu.h +32 -32
index b714fa9..5445023 100644
@@ -830,49 +830,49 @@
 /* AST_SCU_FUN_PIN_CTRL5		0x90 - Multi-function Pin Control#5 */
 #define SCU_FUN_PIN_SPICS1		(0x1 << 31)
 #define SCU_FUN_PIN_LPC_PLUS		(0x1 << 30)
-#define SCU_FUC_PIN_USB20_HOST		(0x1 << 29)
-#define SCU_FUC_PIN_USB11_PORT4		(0x1 << 28)
-#define SCU_FUC_PIN_I2C14		(0x1 << 27)
-#define SCU_FUC_PIN_I2C13		(0x1 << 26)
-#define SCU_FUC_PIN_I2C12		(0x1 << 25)
-#define SCU_FUC_PIN_I2C11		(0x1 << 24)
-#define SCU_FUC_PIN_I2C10		(0x1 << 23)
-#define SCU_FUC_PIN_I2C9		(0x1 << 22)
-#define SCU_FUC_PIN_I2C8		(0x1 << 21)
-#define SCU_FUC_PIN_I2C7		(0x1 << 20)
-#define SCU_FUC_PIN_I2C6		(0x1 << 19)
-#define SCU_FUC_PIN_I2C5		(0x1 << 18)
-#define SCU_FUC_PIN_I2C4		(0x1 << 17)
-#define SCU_FUC_PIN_I2C3		(0x1 << 16)
-#define SCU_FUC_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
-#define SCU_FUC_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
-#define SCU_FUC_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
-#define SCU_FUC_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
-
-#define SCU_FUC_PIN_MII2_TX_DRIV(x)	(x << 10)
-#define SCU_FUC_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
-#define SCU_FUC_PIN_MII1_TX_DRIV(x)	(x << 8)
-#define SCU_FUC_PIN_MII1_TX_DRIV_MASK	(0x3 << 8)
+#define SCU_FUN_PIN_USB20_HOST		(0x1 << 29)
+#define SCU_FUN_PIN_USB11_PORT4		(0x1 << 28)
+#define SCU_FUN_PIN_I2C14		(0x1 << 27)
+#define SCU_FUN_PIN_I2C13		(0x1 << 26)
+#define SCU_FUN_PIN_I2C12		(0x1 << 25)
+#define SCU_FUN_PIN_I2C11		(0x1 << 24)
+#define SCU_FUN_PIN_I2C10		(0x1 << 23)
+#define SCU_FUN_PIN_I2C9		(0x1 << 22)
+#define SCU_FUN_PIN_I2C8		(0x1 << 21)
+#define SCU_FUN_PIN_I2C7		(0x1 << 20)
+#define SCU_FUN_PIN_I2C6		(0x1 << 19)
+#define SCU_FUN_PIN_I2C5		(0x1 << 18)
+#define SCU_FUN_PIN_I2C4		(0x1 << 17)
+#define SCU_FUN_PIN_I2C3		(0x1 << 16)
+#define SCU_FUN_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
+#define SCU_FUN_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
+#define SCU_FUN_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
+#define SCU_FUN_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
+
+#define SCU_FUN_PIN_MII2_TX_DRIV(x)	(x << 10)
+#define SCU_FUN_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
+#define SCU_FUN_PIN_MII1_TX_DRIV(x)	(x << 8)
+#define SCU_FUN_PIN_MII1_TX_DRIV_MASK	(0x3 << 8)
 
 #define MII_NORMAL_DRIV			0x0
 #define MII_HIGH_DRIV			0x2
 
-#define SCU_FUC_PIN_UART6		(0x1 << 7)
-#define SCU_FUC_PIN_ROM_16BIT		(0x1 << 6)
-#define SCU_FUC_PIN_DIGI_V_OUT(x)	(x)
-#define SCU_FUC_PIN_DIGI_V_OUT_MASK	(0x3)
+#define SCU_FUN_PIN_UART6		(0x1 << 7)
+#define SCU_FUN_PIN_ROM_16BIT		(0x1 << 6)
+#define SCU_FUN_PIN_DIGI_V_OUT(x)	(x)
+#define SCU_FUN_PIN_DIGI_V_OUT_MASK	(0x3)
 
 #define VIDEO_DISABLE			0x0
 #define VIDEO_12BITS			0x1
 #define VIDEO_24BITS			0x2
 //#define VIDEO_DISABLE			0x3
 
-#define SCU_FUC_PIN_USB11_PORT2		(0x1 << 3)
-#define SCU_FUC_PIN_SD1_8BIT		(0x1 << 3)
+#define SCU_FUN_PIN_USB11_PORT2		(0x1 << 3)
+#define SCU_FUN_PIN_SD1_8BIT		(0x1 << 3)
 
-#define SCU_FUC_PIN_MAC1_MDIO		(0x1 << 2)
-#define SCU_FUC_PIN_SD2			(0x1 << 1)
-#define SCU_FUC_PIN_SD1			(0x1 << 0)
+#define SCU_FUN_PIN_MAC1_MDIO		(0x1 << 2)
+#define SCU_FUN_PIN_SD2			(0x1 << 1)
+#define SCU_FUN_PIN_SD1			(0x1 << 0)
 
 
 /* AST_SCU_FUN_PIN_CTRL6		0x94 - Multi-function Pin Control#6*/
arch/arm/mach-aspeed/ast-scu.c +1 -1
index 0cc0d67..280c421 100644
@@ -394,7 +394,7 @@ void ast_scu_multi_func_eth(u8 num)
 			      AST_SCU_FUN_PIN_CTRL1);
 
 		ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
-			      SCU_FUC_PIN_MAC1_MDIO,
+			      SCU_FUN_PIN_MAC1_MDIO,
 			      AST_SCU_FUN_PIN_CTRL5);
 
 		break;

--
2.8.0.rc3.226.g39d4020

#37 lore raw

PATCH v2 3/6 aspeed/scu: Add definitions needed to configure pins for I2C

In reply to Maxim Sloyko

Add missing definitions for configuring I2C pins

---
Changes for v1:
Split patch into two with this part adding definitions.
Changes for v2:
Dropped redundant parens.

---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/include/asm/arch-aspeed/regs-scu.h +9 -0
index 5445023..be8c8d7 100644
@@ -844,11 +844,15 @@
 #define SCU_FUN_PIN_I2C5		(0x1 << 18)
 #define SCU_FUN_PIN_I2C4		(0x1 << 17)
 #define SCU_FUN_PIN_I2C3		(0x1 << 16)
+#define SCU_FUN_PIN_I2C(n)		(0x1 << (16 + (n) - 3))
 #define SCU_FUN_PIN_MII2_RX_DWN_DIS	(0x1 << 15)
 #define SCU_FUN_PIN_MII2_TX_DWN_DIS	(0x1 << 14)
 #define SCU_FUN_PIN_MII1_RX_DWN_DIS	(0x1 << 13)
 #define SCU_FUN_PIN_MII1_TX_DWN_DIS	(0x1 << 12)
 
+#define SCU_I2C_MIN_BUS_NUM			1
+#define SCU_I2C_MAX_BUS_NUM			14
+
 #define SCU_FUN_PIN_MII2_TX_DRIV(x)	(x << 10)
 #define SCU_FUN_PIN_MII2_TX_DRIV_MASK	(0x3 << 10)
 #define SCU_FUN_PIN_MII1_TX_DRIV(x)	(x << 8)
@@ -914,6 +918,11 @@
 #define SCU_FUN_PIN_ROMA4		(0x1 << 18)
 #define SCU_FUN_PIN_ROMA3		(0x1 << 17)
 #define SCU_FUN_PIN_ROMA2		(0x1 << 16)
+/* AST2500 only */
+#define SCU_FUN_PIN_SDA2		(0x1 << 15)
+#define SCU_FUN_PIN_SCL2		(0x1 << 14)
+#define SCU_FUN_PIN_SDA1		(0x1 << 13)
+#define SCU_FUN_PIN_SCL1		(0x1 << 12)
 
 /* AST_SCU_FUN_PIN_CTRL9		0xA8 - Multi-function Pin Control#9 */
 #define SCU_FUN_PIN_ROMA21		(0x1 << 3)

--
2.8.0.rc3.226.g39d4020

Reviewed-by on v2 3/6
#38 lore raw

Re: [PATCH u-boot v2 3/6] aspeed/scu: Add definitions needed to configure pins for I2C

Quoted 11 lines · Maxim Sloyko

Add missing definitions for configuring I2C pins

---
Changes for v1:
Split patch into two with this part adding definitions.
Changes for v2:
Dropped redundant parens.

---
 arch/arm/include/asm/arch-aspeed/regs-scu.h | 9 +++++++++
 1 file changed, 9 insertions(+)
#39 lore raw

PATCH v2 4/6 aspeed: Add function to calculate APB Clock frequency

In reply to Maxim Sloyko

This is needed by I2C driver.

---
Changes for v1:
Add function comment.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  4 ++++
 arch/arm/mach-aspeed/ast-scu.c             | 13 +++++++++++++
 2 files changed, 17 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +4 -0
index d248416..6f00e37 100644
@@ -38,6 +38,10 @@ extern void ast_scu_get_who_init_dram(void);
 extern u32 ast_get_clk_source(void);
 extern u32 ast_get_h_pll_clk(void);
 extern u32 ast_get_ahbclk(void);
+/*
+ * Return the frequency of APB clock
+ */
+extern u32 ast_get_apbclk(void);
 
 extern u32 ast_scu_get_vga_memsize(void);
 
arch/arm/mach-aspeed/ast-scu.c +13 -0
index 280c421..87236e2 100644
@@ -318,6 +318,19 @@ u32 ast_get_ahbclk(void)
 
 #endif /* AST_SOC_G5 */
 
+u32 ast_get_apbclk(void)
+{
+	ulong h_pll = ast_get_h_pll_clk();
+
+	/*
+	 * The formula for converting the bit pattern to divisor is
+	 * (4 + 4 * DIV), according to datasheet
+	 */
+	ulong apb_div = 4 + 4 * SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL));
+	return h_pll / apb_div;
+}
+
+
 void ast_scu_show_system_info(void)
 {
 

--
2.8.0.rc3.226.g39d4020

Reviewed-by on v2 4/6
#40 lore raw

Re: [PATCH u-boot v2 4/6] aspeed: Add function to calculate APB Clock frequency

Quoted 10 lines · Maxim Sloyko

This is needed by I2C driver.

---
Changes for v1:
Add function comment.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  4 ++++
 arch/arm/mach-aspeed/ast-scu.c             | 13 +++++++++++++
 2 files changed, 17 insertions(+)

(for mainline you would want to add @param and @return to your function comment. See other exampes...

- Simon

#41 lore raw

PATCH v2 5/6 aspeed: Add function to configure pins for I2C devices

In reply to Maxim Sloyko

In the absence of pinmux driver, I2C driver will be configuring pins directly.

---
 arch/arm/include/asm/arch-aspeed/ast_scu.h |  6 ++++++
 arch/arm/mach-aspeed/ast-scu.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)
arch/arm/include/asm/arch-aspeed/ast_scu.h +6 -0
index 6f00e37..5ab28cc 100644
@@ -49,4 +49,10 @@ extern void ast_scu_init_eth(u8 num);
 extern void ast_scu_multi_func_eth(u8 num);
 extern void ast_scu_multi_func_romcs(u8 num);
 
+/*
+ * Enable I2C controller and pins for a particular device.
+ * Device numbering starts at 1
+ */
+extern void ast_scu_enable_i2c(u8 num);
+
 #endif
arch/arm/mach-aspeed/ast-scu.c +28 -0
index 87236e2..8232d88 100644
@@ -509,3 +509,31 @@ void ast_scu_get_who_init_dram(void)
 		break;
 	}
 }
+
+void ast_scu_enable_i2c(u8 bus_num)
+{
+	if (bus_num > SCU_I2C_MAX_BUS_NUM) {
+		debug("%s: bus_num is out of range, must be [%d - %d]\n",
+		      __func__, SCU_I2C_MIN_BUS_NUM, SCU_I2C_MAX_BUS_NUM);
+		return;
+	}
+
+	if (bus_num == 0) {
+		/* Enable I2C Controllers */
+		clrbits_le32(AST_SCU_BASE + AST_SCU_RESET, SCU_RESET_I2C);
+	} else if (bus_num >= 3) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL5,
+			     SCU_FUN_PIN_I2C(bus_num));
+	/* In earlier versions of the SoC these pins are always assigned to
+	 * respective I2C buses and require no configuration.
+	 */
+#ifdef AST_SOC_G5
+	} else if (bus_num == 1) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+			     SCU_FUN_PIN_SDA1 | SCU_FUN_PIN_SCL1);
+	} else if (bus_num == 2) {
+		setbits_le32(AST_SCU_BASE + AST_SCU_FUN_PIN_CTRL8,
+			     SCU_FUN_PIN_SDA2 | SCU_FUN_PIN_SCL2);
+#endif
+	}
+}
Signature · 1 line
2.8.0.rc3.226.g39d4020
#42 lore raw

PATCH v2 6/6 aspeed: I2C driver

In reply to Maxim Sloyko

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

---
Changes for v1:
- Style fixes: blank lines, line formatting, dropped inline from definitions
- More documentation for CONFIG_SYS_I2C_AST
- Use standard ETIMEOUT error
- Documented struct ast_i2c
- Documented get_clk_reg_val function
- Rewritten get_clk_reg_val to use register masks and shifts defined in ast_i2c.h
- Dropped AST_ prefix from AST_I2CD_ defines
Changes for v2:
- More style fixes for things missed in v1
- Return error from ast_i2c_xfer on deblock failure

---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 130 ++++++++++++++++++++
 4 files changed, 475 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
drivers/i2c/Kconfig +9 -0
index 6e22bba..425766a 100644
@@ -90,6 +90,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 	  enable status register. This config option can be enabled in such
 	  cases.
 
+config SYS_I2C_AST
+	bool "Aspeed I2C Controller"
+	depends on DM_I2C
+	help
+	  Say yes here to select Aspeed I2C Host Controller. The driver
+	  supports AST2500 and AST2400 controllers, but is very limited.
+	  Only single master mode is supported and only byte-by-byte
+	  synchronous reads and writes are supported, no Pool Buffers or DMA.
+
 config SYS_I2C_INTEL
 	bool "Intel I2C/SMBUS driver"
 	depends on DM_I2C
drivers/i2c/Makefile +1 -0
index 167424d..89e046e 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
drivers/i2c/ast_i2c.c new file +335 -0

335 lines not on this page · raw message

drivers/i2c/ast_i2c.h new file +130 -0

130 lines not on this page · raw message

--
2.8.0.rc3.226.g39d4020

Reviewed-by on v2 6/6
#43 lore raw

Re: [PATCH u-boot v2 6/6] aspeed: I2C driver

Quoted 17 lines · Maxim Sloyko

The driver is very limited: only single master mode is supported and only byte-by-byte synchronous reads and writes are supported, no Pool Buffers or DMA.

---
Changes for v1:
- Style fixes: blank lines, line formatting, dropped inline from definitions
- More documentation for CONFIG_SYS_I2C_AST
- Use standard ETIMEOUT error
- Documented struct ast_i2c
- Documented get_clk_reg_val function
- Rewritten get_clk_reg_val to use register masks and shifts defined in ast_i2c.h
- Dropped AST_ prefix from AST_I2CD_ defines
Changes for v2:
- More style fixes for things missed in v1
- Return error from ast_i2c_xfer on deblock failure

Quoted 8 lines
---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 130 ++++++++++++++++++++
 4 files changed, 475 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h