All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/15] Expand Aspeed AST2500 Support
@ 2017-04-17 19:00 ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass
  Cc: openbmc, Maxim Sloyko, Heiko Schocher, Thomas Abraham,
	Masahiro Yamada, Tom Warren, Wills Wang, Kever Yang,
	Konstantin Porotchkin, Albert Aribaud, Beniamino Galvani,
	Heiko Stübner, Minkyu Kang, Daniel Schwierzeck, Wenyou Yang,
	Stephen Warren

This series expands support for Aspeed AST2500 SoC, commonly used as
Board Management Controller in many servers.

The main goal of this series is I2C driver, the rest are
either cleanups or supporting patches. Most notable among them is
addition of Watchdog uclass, so that watchdog drivers can now use Driver
Model.

One notable thing that is *missing* from this series is Device Tree
configuration for I2C driver. The Linux Kernel I2C driver is still under
review and it may affect the details of how devices need to be
configured in the Device Tree. So, I decided to wait until it will show
up in Linux Kernel DT and then pull it into U-Boot.

I removed Network driver from this series. I will work on it separately
and will make it compatible with existing Faraday devices, but that is a
work better done outside of this already long series.

Changes in v1:
- Added link to the original version to commit message
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests
- Rename reset to expire_now
- Rename restart to reset
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now
- Rename wdt_reset call to wdt_expire_now
- Style fixes

Maxim Sloyko (15):
  aspeed: Update ast2500 Device Tree
  dm: Simple Watchdog uclass
  aspeed: Watchdog Timer Driver
  aspeed: Make SCU lock/unlock functions part of SCU API
  aspeed: Reset Driver
  aspeed: Device Tree configuration for Reset Driver
  aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  aspeed: AST2500 Pinctrl Driver
  aspeed: Enable Pinctrl Driver in AST2500 EVB
  aspeed: Add P-Bus clock in ast2500 clock driver
  aspeed: Add I2C Driver
  aspeed: Enable I2C in EVB defconfig
  aspeed: Add support for Clocks needed by MACs
  aspeed: Refactor SCU to use consistent mask & shift
  aspeed: Cleanup ast2500-u-boot.dtsi Device Tree

 arch/arm/dts/ast2500-evb.dts                   |  15 +
 arch/arm/dts/ast2500-u-boot.dtsi               |  59 +-
 arch/arm/dts/ast2500.dtsi                      | 881 ++++++++++++++++++++++++-
 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 132 +++-
 arch/arm/include/asm/arch-aspeed/wdt.h         |  38 +-
 arch/arm/mach-aspeed/Kconfig                   |   8 +-
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     |  15 +
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  17 +-
 arch/arm/mach-aspeed/ast_wdt.c                 |  47 +-
 arch/sandbox/dts/test.dts                      |   4 +
 arch/sandbox/include/asm/state.h               |   9 +
 configs/evb-ast2500_defconfig                  |   6 +
 configs/sandbox_defconfig                      |   2 +
 drivers/clk/aspeed/clk_ast2500.c               | 321 +++++++--
 drivers/i2c/Kconfig                            |   9 +
 drivers/i2c/Makefile                           |   1 +
 drivers/i2c/ast_i2c.c                          | 357 ++++++++++
 drivers/i2c/ast_i2c.h                          | 132 ++++
 drivers/pinctrl/Kconfig                        |   9 +
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 ++++
 drivers/reset/Kconfig                          |  10 +
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++
 drivers/sysreset/sysreset_ast.c                |  24 +-
 drivers/watchdog/Kconfig                       |  32 +
 drivers/watchdog/Makefile                      |   3 +
 drivers/watchdog/ast_wdt.c                     | 125 ++++
 drivers/watchdog/sandbox_wdt.c                 |  76 +++
 drivers/watchdog/wdt-uclass.c                  |  72 ++
 include/dm/uclass-id.h                         |   1 +
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 include/dt-bindings/reset/ast2500-reset.h      |  45 ++
 include/wdt.h                                  | 107 +++
 test/dm/Makefile                               |   1 +
 test/dm/wdt.c                                  |  40 ++
 38 files changed, 2721 insertions(+), 167 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c
 create mode 100644 drivers/reset/ast2500-reset.c
 create mode 100644 drivers/watchdog/ast_wdt.c
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 00/15] Expand Aspeed AST2500 Support
@ 2017-04-17 19:00 ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

This series expands support for Aspeed AST2500 SoC, commonly used as
Board Management Controller in many servers.

The main goal of this series is I2C driver, the rest are
either cleanups or supporting patches. Most notable among them is
addition of Watchdog uclass, so that watchdog drivers can now use Driver
Model.

One notable thing that is *missing* from this series is Device Tree
configuration for I2C driver. The Linux Kernel I2C driver is still under
review and it may affect the details of how devices need to be
configured in the Device Tree. So, I decided to wait until it will show
up in Linux Kernel DT and then pull it into U-Boot.

I removed Network driver from this series. I will work on it separately
and will make it compatible with existing Faraday devices, but that is a
work better done outside of this already long series.

Changes in v1:
- Added link to the original version to commit message
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests
- Rename reset to expire_now
- Rename restart to reset
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now
- Rename wdt_reset call to wdt_expire_now
- Style fixes

Maxim Sloyko (15):
  aspeed: Update ast2500 Device Tree
  dm: Simple Watchdog uclass
  aspeed: Watchdog Timer Driver
  aspeed: Make SCU lock/unlock functions part of SCU API
  aspeed: Reset Driver
  aspeed: Device Tree configuration for Reset Driver
  aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  aspeed: AST2500 Pinctrl Driver
  aspeed: Enable Pinctrl Driver in AST2500 EVB
  aspeed: Add P-Bus clock in ast2500 clock driver
  aspeed: Add I2C Driver
  aspeed: Enable I2C in EVB defconfig
  aspeed: Add support for Clocks needed by MACs
  aspeed: Refactor SCU to use consistent mask & shift
  aspeed: Cleanup ast2500-u-boot.dtsi Device Tree

 arch/arm/dts/ast2500-evb.dts                   |  15 +
 arch/arm/dts/ast2500-u-boot.dtsi               |  59 +-
 arch/arm/dts/ast2500.dtsi                      | 881 ++++++++++++++++++++++++-
 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 132 +++-
 arch/arm/include/asm/arch-aspeed/wdt.h         |  38 +-
 arch/arm/mach-aspeed/Kconfig                   |   8 +-
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     |  15 +
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  17 +-
 arch/arm/mach-aspeed/ast_wdt.c                 |  47 +-
 arch/sandbox/dts/test.dts                      |   4 +
 arch/sandbox/include/asm/state.h               |   9 +
 configs/evb-ast2500_defconfig                  |   6 +
 configs/sandbox_defconfig                      |   2 +
 drivers/clk/aspeed/clk_ast2500.c               | 321 +++++++--
 drivers/i2c/Kconfig                            |   9 +
 drivers/i2c/Makefile                           |   1 +
 drivers/i2c/ast_i2c.c                          | 357 ++++++++++
 drivers/i2c/ast_i2c.h                          | 132 ++++
 drivers/pinctrl/Kconfig                        |   9 +
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 ++++
 drivers/reset/Kconfig                          |  10 +
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++
 drivers/sysreset/sysreset_ast.c                |  24 +-
 drivers/watchdog/Kconfig                       |  32 +
 drivers/watchdog/Makefile                      |   3 +
 drivers/watchdog/ast_wdt.c                     | 125 ++++
 drivers/watchdog/sandbox_wdt.c                 |  76 +++
 drivers/watchdog/wdt-uclass.c                  |  72 ++
 include/dm/uclass-id.h                         |   1 +
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 include/dt-bindings/reset/ast2500-reset.h      |  45 ++
 include/wdt.h                                  | 107 +++
 test/dm/Makefile                               |   1 +
 test/dm/wdt.c                                  |  40 ++
 38 files changed, 2721 insertions(+), 167 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c
 create mode 100644 drivers/reset/ast2500-reset.c
 create mode 100644 drivers/watchdog/ast_wdt.c
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 01/15] aspeed: Update ast2500 Device Tree
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Pull in the Device Tree for ast2500 from the mainline Linux kernel.
The file is copied from
https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Added link to the original version to commit message

---
 arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 880 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/ast2500.dtsi b/arch/arm/dts/ast2500.dtsi
index 97fac69d11..7e0ad3a41a 100644
--- a/arch/arm/dts/ast2500.dtsi
+++ b/arch/arm/dts/ast2500.dtsi
@@ -1,6 +1,6 @@
 /*
  * This device tree is copied from
- * https://raw.githubusercontent.com/torvalds/linux/02440622/arch/arm/boot/dts/
+ * https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
  */
 #include "skeleton.dtsi"
 
@@ -36,6 +36,22 @@
 			reg = <0x1e6c0080 0x80>;
 		};
 
+		mac0: ethernet@1e660000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e660000 0x180>;
+			interrupts = <2>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
+		mac1: ethernet@1e680000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e680000 0x180>;
+			interrupts = <3>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
 		apb {
 			compatible = "simple-bus";
 			#address-cells = <1>;
@@ -48,6 +64,822 @@
 				reg = <0x1e6e2070 0x04>;
 			};
 
+			syscon: syscon@1e6e2000 {
+				compatible = "aspeed,g5-scu", "syscon", "simple-mfd";
+				reg = <0x1e6e2000 0x1a8>;
+
+				pinctrl: pinctrl {
+					compatible = "aspeed,g5-pinctrl";
+					aspeed,external-nodes = <&gfx &lhc>;
+
+					pinctrl_acpi_default: acpi_default {
+						function = "ACPI";
+						groups = "ACPI";
+					};
+
+					pinctrl_adc0_default: adc0_default {
+						function = "ADC0";
+						groups = "ADC0";
+					};
+
+					pinctrl_adc1_default: adc1_default {
+						function = "ADC1";
+						groups = "ADC1";
+					};
+
+					pinctrl_adc10_default: adc10_default {
+						function = "ADC10";
+						groups = "ADC10";
+					};
+
+					pinctrl_adc11_default: adc11_default {
+						function = "ADC11";
+						groups = "ADC11";
+					};
+
+					pinctrl_adc12_default: adc12_default {
+						function = "ADC12";
+						groups = "ADC12";
+					};
+
+					pinctrl_adc13_default: adc13_default {
+						function = "ADC13";
+						groups = "ADC13";
+					};
+
+					pinctrl_adc14_default: adc14_default {
+						function = "ADC14";
+						groups = "ADC14";
+					};
+
+					pinctrl_adc15_default: adc15_default {
+						function = "ADC15";
+						groups = "ADC15";
+					};
+
+					pinctrl_adc2_default: adc2_default {
+						function = "ADC2";
+						groups = "ADC2";
+					};
+
+					pinctrl_adc3_default: adc3_default {
+						function = "ADC3";
+						groups = "ADC3";
+					};
+
+					pinctrl_adc4_default: adc4_default {
+						function = "ADC4";
+						groups = "ADC4";
+					};
+
+					pinctrl_adc5_default: adc5_default {
+						function = "ADC5";
+						groups = "ADC5";
+					};
+
+					pinctrl_adc6_default: adc6_default {
+						function = "ADC6";
+						groups = "ADC6";
+					};
+
+					pinctrl_adc7_default: adc7_default {
+						function = "ADC7";
+						groups = "ADC7";
+					};
+
+					pinctrl_adc8_default: adc8_default {
+						function = "ADC8";
+						groups = "ADC8";
+					};
+
+					pinctrl_adc9_default: adc9_default {
+						function = "ADC9";
+						groups = "ADC9";
+					};
+
+					pinctrl_bmcint_default: bmcint_default {
+						function = "BMCINT";
+						groups = "BMCINT";
+					};
+
+					pinctrl_ddcclk_default: ddcclk_default {
+						function = "DDCCLK";
+						groups = "DDCCLK";
+					};
+
+					pinctrl_ddcdat_default: ddcdat_default {
+						function = "DDCDAT";
+						groups = "DDCDAT";
+					};
+
+					pinctrl_espi_default: espi_default {
+						function = "ESPI";
+						groups = "ESPI";
+					};
+
+					pinctrl_fwspics1_default: fwspics1_default {
+						function = "FWSPICS1";
+						groups = "FWSPICS1";
+					};
+
+					pinctrl_fwspics2_default: fwspics2_default {
+						function = "FWSPICS2";
+						groups = "FWSPICS2";
+					};
+
+					pinctrl_gpid0_default: gpid0_default {
+						function = "GPID0";
+						groups = "GPID0";
+					};
+
+					pinctrl_gpid2_default: gpid2_default {
+						function = "GPID2";
+						groups = "GPID2";
+					};
+
+					pinctrl_gpid4_default: gpid4_default {
+						function = "GPID4";
+						groups = "GPID4";
+					};
+
+					pinctrl_gpid6_default: gpid6_default {
+						function = "GPID6";
+						groups = "GPID6";
+					};
+
+					pinctrl_gpie0_default: gpie0_default {
+						function = "GPIE0";
+						groups = "GPIE0";
+					};
+
+					pinctrl_gpie2_default: gpie2_default {
+						function = "GPIE2";
+						groups = "GPIE2";
+					};
+
+					pinctrl_gpie4_default: gpie4_default {
+						function = "GPIE4";
+						groups = "GPIE4";
+					};
+
+					pinctrl_gpie6_default: gpie6_default {
+						function = "GPIE6";
+						groups = "GPIE6";
+					};
+
+					pinctrl_i2c10_default: i2c10_default {
+						function = "I2C10";
+						groups = "I2C10";
+					};
+
+					pinctrl_i2c11_default: i2c11_default {
+						function = "I2C11";
+						groups = "I2C11";
+					};
+
+					pinctrl_i2c12_default: i2c12_default {
+						function = "I2C12";
+						groups = "I2C12";
+					};
+
+					pinctrl_i2c13_default: i2c13_default {
+						function = "I2C13";
+						groups = "I2C13";
+					};
+
+					pinctrl_i2c14_default: i2c14_default {
+						function = "I2C14";
+						groups = "I2C14";
+					};
+
+					pinctrl_i2c3_default: i2c3_default {
+						function = "I2C3";
+						groups = "I2C3";
+					};
+
+					pinctrl_i2c4_default: i2c4_default {
+						function = "I2C4";
+						groups = "I2C4";
+					};
+
+					pinctrl_i2c5_default: i2c5_default {
+						function = "I2C5";
+						groups = "I2C5";
+					};
+
+					pinctrl_i2c6_default: i2c6_default {
+						function = "I2C6";
+						groups = "I2C6";
+					};
+
+					pinctrl_i2c7_default: i2c7_default {
+						function = "I2C7";
+						groups = "I2C7";
+					};
+
+					pinctrl_i2c8_default: i2c8_default {
+						function = "I2C8";
+						groups = "I2C8";
+					};
+
+					pinctrl_i2c9_default: i2c9_default {
+						function = "I2C9";
+						groups = "I2C9";
+					};
+
+					pinctrl_lad0_default: lad0_default {
+						function = "LAD0";
+						groups = "LAD0";
+					};
+
+					pinctrl_lad1_default: lad1_default {
+						function = "LAD1";
+						groups = "LAD1";
+					};
+
+					pinctrl_lad2_default: lad2_default {
+						function = "LAD2";
+						groups = "LAD2";
+					};
+
+					pinctrl_lad3_default: lad3_default {
+						function = "LAD3";
+						groups = "LAD3";
+					};
+
+					pinctrl_lclk_default: lclk_default {
+						function = "LCLK";
+						groups = "LCLK";
+					};
+
+					pinctrl_lframe_default: lframe_default {
+						function = "LFRAME";
+						groups = "LFRAME";
+					};
+
+					pinctrl_lpchc_default: lpchc_default {
+						function = "LPCHC";
+						groups = "LPCHC";
+					};
+
+					pinctrl_lpcpd_default: lpcpd_default {
+						function = "LPCPD";
+						groups = "LPCPD";
+					};
+
+					pinctrl_lpcplus_default: lpcplus_default {
+						function = "LPCPLUS";
+						groups = "LPCPLUS";
+					};
+
+					pinctrl_lpcpme_default: lpcpme_default {
+						function = "LPCPME";
+						groups = "LPCPME";
+					};
+
+					pinctrl_lpcrst_default: lpcrst_default {
+						function = "LPCRST";
+						groups = "LPCRST";
+					};
+
+					pinctrl_lpcsmi_default: lpcsmi_default {
+						function = "LPCSMI";
+						groups = "LPCSMI";
+					};
+
+					pinctrl_lsirq_default: lsirq_default {
+						function = "LSIRQ";
+						groups = "LSIRQ";
+					};
+
+					pinctrl_mac1link_default: mac1link_default {
+						function = "MAC1LINK";
+						groups = "MAC1LINK";
+					};
+
+					pinctrl_mac2link_default: mac2link_default {
+						function = "MAC2LINK";
+						groups = "MAC2LINK";
+					};
+
+					pinctrl_mdio1_default: mdio1_default {
+						function = "MDIO1";
+						groups = "MDIO1";
+					};
+
+					pinctrl_mdio2_default: mdio2_default {
+						function = "MDIO2";
+						groups = "MDIO2";
+					};
+
+					pinctrl_ncts1_default: ncts1_default {
+						function = "NCTS1";
+						groups = "NCTS1";
+					};
+
+					pinctrl_ncts2_default: ncts2_default {
+						function = "NCTS2";
+						groups = "NCTS2";
+					};
+
+					pinctrl_ncts3_default: ncts3_default {
+						function = "NCTS3";
+						groups = "NCTS3";
+					};
+
+					pinctrl_ncts4_default: ncts4_default {
+						function = "NCTS4";
+						groups = "NCTS4";
+					};
+
+					pinctrl_ndcd1_default: ndcd1_default {
+						function = "NDCD1";
+						groups = "NDCD1";
+					};
+
+					pinctrl_ndcd2_default: ndcd2_default {
+						function = "NDCD2";
+						groups = "NDCD2";
+					};
+
+					pinctrl_ndcd3_default: ndcd3_default {
+						function = "NDCD3";
+						groups = "NDCD3";
+					};
+
+					pinctrl_ndcd4_default: ndcd4_default {
+						function = "NDCD4";
+						groups = "NDCD4";
+					};
+
+					pinctrl_ndsr1_default: ndsr1_default {
+						function = "NDSR1";
+						groups = "NDSR1";
+					};
+
+					pinctrl_ndsr2_default: ndsr2_default {
+						function = "NDSR2";
+						groups = "NDSR2";
+					};
+
+					pinctrl_ndsr3_default: ndsr3_default {
+						function = "NDSR3";
+						groups = "NDSR3";
+					};
+
+					pinctrl_ndsr4_default: ndsr4_default {
+						function = "NDSR4";
+						groups = "NDSR4";
+					};
+
+					pinctrl_ndtr1_default: ndtr1_default {
+						function = "NDTR1";
+						groups = "NDTR1";
+					};
+
+					pinctrl_ndtr2_default: ndtr2_default {
+						function = "NDTR2";
+						groups = "NDTR2";
+					};
+
+					pinctrl_ndtr3_default: ndtr3_default {
+						function = "NDTR3";
+						groups = "NDTR3";
+					};
+
+					pinctrl_ndtr4_default: ndtr4_default {
+						function = "NDTR4";
+						groups = "NDTR4";
+					};
+
+					pinctrl_nri1_default: nri1_default {
+						function = "NRI1";
+						groups = "NRI1";
+					};
+
+					pinctrl_nri2_default: nri2_default {
+						function = "NRI2";
+						groups = "NRI2";
+					};
+
+					pinctrl_nri3_default: nri3_default {
+						function = "NRI3";
+						groups = "NRI3";
+					};
+
+					pinctrl_nri4_default: nri4_default {
+						function = "NRI4";
+						groups = "NRI4";
+					};
+
+					pinctrl_nrts1_default: nrts1_default {
+						function = "NRTS1";
+						groups = "NRTS1";
+					};
+
+					pinctrl_nrts2_default: nrts2_default {
+						function = "NRTS2";
+						groups = "NRTS2";
+					};
+
+					pinctrl_nrts3_default: nrts3_default {
+						function = "NRTS3";
+						groups = "NRTS3";
+					};
+
+					pinctrl_nrts4_default: nrts4_default {
+						function = "NRTS4";
+						groups = "NRTS4";
+					};
+
+					pinctrl_oscclk_default: oscclk_default {
+						function = "OSCCLK";
+						groups = "OSCCLK";
+					};
+
+					pinctrl_pewake_default: pewake_default {
+						function = "PEWAKE";
+						groups = "PEWAKE";
+					};
+
+					pinctrl_pnor_default: pnor_default {
+						function = "PNOR";
+						groups = "PNOR";
+					};
+
+					pinctrl_pwm0_default: pwm0_default {
+						function = "PWM0";
+						groups = "PWM0";
+					};
+
+					pinctrl_pwm1_default: pwm1_default {
+						function = "PWM1";
+						groups = "PWM1";
+					};
+
+					pinctrl_pwm2_default: pwm2_default {
+						function = "PWM2";
+						groups = "PWM2";
+					};
+
+					pinctrl_pwm3_default: pwm3_default {
+						function = "PWM3";
+						groups = "PWM3";
+					};
+
+					pinctrl_pwm4_default: pwm4_default {
+						function = "PWM4";
+						groups = "PWM4";
+					};
+
+					pinctrl_pwm5_default: pwm5_default {
+						function = "PWM5";
+						groups = "PWM5";
+					};
+
+					pinctrl_pwm6_default: pwm6_default {
+						function = "PWM6";
+						groups = "PWM6";
+					};
+
+					pinctrl_pwm7_default: pwm7_default {
+						function = "PWM7";
+						groups = "PWM7";
+					};
+
+					pinctrl_rgmii1_default: rgmii1_default {
+						function = "RGMII1";
+						groups = "RGMII1";
+					};
+
+					pinctrl_rgmii2_default: rgmii2_default {
+						function = "RGMII2";
+						groups = "RGMII2";
+					};
+
+					pinctrl_rmii1_default: rmii1_default {
+						function = "RMII1";
+						groups = "RMII1";
+					};
+
+					pinctrl_rmii2_default: rmii2_default {
+						function = "RMII2";
+						groups = "RMII2";
+					};
+
+					pinctrl_rxd1_default: rxd1_default {
+						function = "RXD1";
+						groups = "RXD1";
+					};
+
+					pinctrl_rxd2_default: rxd2_default {
+						function = "RXD2";
+						groups = "RXD2";
+					};
+
+					pinctrl_rxd3_default: rxd3_default {
+						function = "RXD3";
+						groups = "RXD3";
+					};
+
+					pinctrl_rxd4_default: rxd4_default {
+						function = "RXD4";
+						groups = "RXD4";
+					};
+
+					pinctrl_salt1_default: salt1_default {
+						function = "SALT1";
+						groups = "SALT1";
+					};
+
+					pinctrl_salt10_default: salt10_default {
+						function = "SALT10";
+						groups = "SALT10";
+					};
+
+					pinctrl_salt11_default: salt11_default {
+						function = "SALT11";
+						groups = "SALT11";
+					};
+
+					pinctrl_salt12_default: salt12_default {
+						function = "SALT12";
+						groups = "SALT12";
+					};
+
+					pinctrl_salt13_default: salt13_default {
+						function = "SALT13";
+						groups = "SALT13";
+					};
+
+					pinctrl_salt14_default: salt14_default {
+						function = "SALT14";
+						groups = "SALT14";
+					};
+
+					pinctrl_salt2_default: salt2_default {
+						function = "SALT2";
+						groups = "SALT2";
+					};
+
+					pinctrl_salt3_default: salt3_default {
+						function = "SALT3";
+						groups = "SALT3";
+					};
+
+					pinctrl_salt4_default: salt4_default {
+						function = "SALT4";
+						groups = "SALT4";
+					};
+
+					pinctrl_salt5_default: salt5_default {
+						function = "SALT5";
+						groups = "SALT5";
+					};
+
+					pinctrl_salt6_default: salt6_default {
+						function = "SALT6";
+						groups = "SALT6";
+					};
+
+					pinctrl_salt7_default: salt7_default {
+						function = "SALT7";
+						groups = "SALT7";
+					};
+
+					pinctrl_salt8_default: salt8_default {
+						function = "SALT8";
+						groups = "SALT8";
+					};
+
+					pinctrl_salt9_default: salt9_default {
+						function = "SALT9";
+						groups = "SALT9";
+					};
+
+					pinctrl_scl1_default: scl1_default {
+						function = "SCL1";
+						groups = "SCL1";
+					};
+
+					pinctrl_scl2_default: scl2_default {
+						function = "SCL2";
+						groups = "SCL2";
+					};
+
+					pinctrl_sd1_default: sd1_default {
+						function = "SD1";
+						groups = "SD1";
+					};
+
+					pinctrl_sd2_default: sd2_default {
+						function = "SD2";
+						groups = "SD2";
+					};
+
+					pinctrl_sda1_default: sda1_default {
+						function = "SDA1";
+						groups = "SDA1";
+					};
+
+					pinctrl_sda2_default: sda2_default {
+						function = "SDA2";
+						groups = "SDA2";
+					};
+
+					pinctrl_sgps1_default: sgps1_default {
+						function = "SGPS1";
+						groups = "SGPS1";
+					};
+
+					pinctrl_sgps2_default: sgps2_default {
+						function = "SGPS2";
+						groups = "SGPS2";
+					};
+
+					pinctrl_sioonctrl_default: sioonctrl_default {
+						function = "SIOONCTRL";
+						groups = "SIOONCTRL";
+					};
+
+					pinctrl_siopbi_default: siopbi_default {
+						function = "SIOPBI";
+						groups = "SIOPBI";
+					};
+
+					pinctrl_siopbo_default: siopbo_default {
+						function = "SIOPBO";
+						groups = "SIOPBO";
+					};
+
+					pinctrl_siopwreq_default: siopwreq_default {
+						function = "SIOPWREQ";
+						groups = "SIOPWREQ";
+					};
+
+					pinctrl_siopwrgd_default: siopwrgd_default {
+						function = "SIOPWRGD";
+						groups = "SIOPWRGD";
+					};
+
+					pinctrl_sios3_default: sios3_default {
+						function = "SIOS3";
+						groups = "SIOS3";
+					};
+
+					pinctrl_sios5_default: sios5_default {
+						function = "SIOS5";
+						groups = "SIOS5";
+					};
+
+					pinctrl_siosci_default: siosci_default {
+						function = "SIOSCI";
+						groups = "SIOSCI";
+					};
+
+					pinctrl_spi1_default: spi1_default {
+						function = "SPI1";
+						groups = "SPI1";
+					};
+
+					pinctrl_spi1cs1_default: spi1cs1_default {
+						function = "SPI1CS1";
+						groups = "SPI1CS1";
+					};
+
+					pinctrl_spi1debug_default: spi1debug_default {
+						function = "SPI1DEBUG";
+						groups = "SPI1DEBUG";
+					};
+
+					pinctrl_spi1passthru_default: spi1passthru_default {
+						function = "SPI1PASSTHRU";
+						groups = "SPI1PASSTHRU";
+					};
+
+					pinctrl_spi2ck_default: spi2ck_default {
+						function = "SPI2CK";
+						groups = "SPI2CK";
+					};
+
+					pinctrl_spi2cs0_default: spi2cs0_default {
+						function = "SPI2CS0";
+						groups = "SPI2CS0";
+					};
+
+					pinctrl_spi2cs1_default: spi2cs1_default {
+						function = "SPI2CS1";
+						groups = "SPI2CS1";
+					};
+
+					pinctrl_spi2miso_default: spi2miso_default {
+						function = "SPI2MISO";
+						groups = "SPI2MISO";
+					};
+
+					pinctrl_spi2mosi_default: spi2mosi_default {
+						function = "SPI2MOSI";
+						groups = "SPI2MOSI";
+					};
+
+					pinctrl_timer3_default: timer3_default {
+						function = "TIMER3";
+						groups = "TIMER3";
+					};
+
+					pinctrl_timer4_default: timer4_default {
+						function = "TIMER4";
+						groups = "TIMER4";
+					};
+
+					pinctrl_timer5_default: timer5_default {
+						function = "TIMER5";
+						groups = "TIMER5";
+					};
+
+					pinctrl_timer6_default: timer6_default {
+						function = "TIMER6";
+						groups = "TIMER6";
+					};
+
+					pinctrl_timer7_default: timer7_default {
+						function = "TIMER7";
+						groups = "TIMER7";
+					};
+
+					pinctrl_timer8_default: timer8_default {
+						function = "TIMER8";
+						groups = "TIMER8";
+					};
+
+					pinctrl_txd1_default: txd1_default {
+						function = "TXD1";
+						groups = "TXD1";
+					};
+
+					pinctrl_txd2_default: txd2_default {
+						function = "TXD2";
+						groups = "TXD2";
+					};
+
+					pinctrl_txd3_default: txd3_default {
+						function = "TXD3";
+						groups = "TXD3";
+					};
+
+					pinctrl_txd4_default: txd4_default {
+						function = "TXD4";
+						groups = "TXD4";
+					};
+
+					pinctrl_uart6_default: uart6_default {
+						function = "UART6";
+						groups = "UART6";
+					};
+
+					pinctrl_usbcki_default: usbcki_default {
+						function = "USBCKI";
+						groups = "USBCKI";
+					};
+
+					pinctrl_vgabiosrom_default: vgabiosrom_default {
+						function = "VGABIOSROM";
+						groups = "VGABIOSROM";
+					};
+
+					pinctrl_vgahs_default: vgahs_default {
+						function = "VGAHS";
+						groups = "VGAHS";
+					};
+
+					pinctrl_vgavs_default: vgavs_default {
+						function = "VGAVS";
+						groups = "VGAVS";
+					};
+
+					pinctrl_vpi24_default: vpi24_default {
+						function = "VPI24";
+						groups = "VPI24";
+					};
+
+					pinctrl_vpo_default: vpo_default {
+						function = "VPO";
+						groups = "VPO";
+					};
+
+					pinctrl_wdtrst1_default: wdtrst1_default {
+						function = "WDTRST1";
+						groups = "WDTRST1";
+					};
+
+					pinctrl_wdtrst2_default: wdtrst2_default {
+						function = "WDTRST2";
+						groups = "WDTRST2";
+					};
+
+				};
+			};
+
 			clk_hpll: clk_hpll@1e6e2024 {
 				#clock-cells = <0>;
 				compatible = "aspeed,g5-hpll-clock";
@@ -75,11 +907,27 @@
 				reg = <0x1e6e202c 0x4>;
 			};
 
+			gfx: display@1e6e6000 {
+				compatible = "aspeed,ast2500-gfx", "syscon";
+				reg = <0x1e6e6000 0x1000>;
+				reg-io-width = <4>;
+			};
+
 			sram@1e720000 {
 				compatible = "mmio-sram";
 				reg = <0x1e720000 0x9000>;	// 36K
 			};
 
+			gpio: gpio@1e780000 {
+				#gpio-cells = <2>;
+				gpio-controller;
+				compatible = "aspeed,ast2500-gpio";
+				reg = <0x1e780000 0x1000>;
+				interrupts = <20>;
+				gpio-ranges = <&pinctrl 0 0 220>;
+				interrupt-controller;
+			};
+
 			timer: timer@1e782000 {
 				compatible = "aspeed,ast2400-timer";
 				reg = <0x1e782000 0x90>;
@@ -90,6 +938,7 @@
 				clocks = <&clk_apb>;
 			};
 
+
 			wdt1: wdt@1e785000 {
 				compatible = "aspeed,wdt";
 				reg = <0x1e785000 0x1c>;
@@ -119,6 +968,36 @@
 				status = "disabled";
 			};
 
+			lpc: lpc@1e789000 {
+				compatible = "aspeed,ast2500-lpc", "simple-mfd";
+				reg = <0x1e789000 0x1000>;
+
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x1e789000 0x1000>;
+
+				lpc_bmc: lpc-bmc@0 {
+					compatible = "aspeed,ast2500-lpc-bmc";
+					reg = <0x0 0x80>;
+				};
+
+				lpc_host: lpc-host@80 {
+					compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
+					reg = <0x80 0x1e0>;
+
+					#address-cells = <1>;
+					#size-cells = <1>;
+					ranges = <0 0x80 0x1e0>;
+
+					reg-io-width = <4>;
+
+					lhc: lhc@20 {
+						compatible = "aspeed,ast2500-lhc";
+						reg = <0x20 0x24 0x48 0x8>;
+					};
+				};
+			};
+
 			uart2: serial@1e78d000 {
 				compatible = "ns16550a";
 				reg = <0x1e78d000 0x1000>;
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 01/15] aspeed: Update ast2500 Device Tree
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Pull in the Device Tree for ast2500 from the mainline Linux kernel.
The file is copied from
https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Added link to the original version to commit message

---
 arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 880 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/ast2500.dtsi b/arch/arm/dts/ast2500.dtsi
index 97fac69d11..7e0ad3a41a 100644
--- a/arch/arm/dts/ast2500.dtsi
+++ b/arch/arm/dts/ast2500.dtsi
@@ -1,6 +1,6 @@
 /*
  * This device tree is copied from
- * https://raw.githubusercontent.com/torvalds/linux/02440622/arch/arm/boot/dts/
+ * https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
  */
 #include "skeleton.dtsi"
 
@@ -36,6 +36,22 @@
 			reg = <0x1e6c0080 0x80>;
 		};
 
+		mac0: ethernet at 1e660000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e660000 0x180>;
+			interrupts = <2>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
+		mac1: ethernet at 1e680000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e680000 0x180>;
+			interrupts = <3>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
 		apb {
 			compatible = "simple-bus";
 			#address-cells = <1>;
@@ -48,6 +64,822 @@
 				reg = <0x1e6e2070 0x04>;
 			};
 
+			syscon: syscon at 1e6e2000 {
+				compatible = "aspeed,g5-scu", "syscon", "simple-mfd";
+				reg = <0x1e6e2000 0x1a8>;
+
+				pinctrl: pinctrl {
+					compatible = "aspeed,g5-pinctrl";
+					aspeed,external-nodes = <&gfx &lhc>;
+
+					pinctrl_acpi_default: acpi_default {
+						function = "ACPI";
+						groups = "ACPI";
+					};
+
+					pinctrl_adc0_default: adc0_default {
+						function = "ADC0";
+						groups = "ADC0";
+					};
+
+					pinctrl_adc1_default: adc1_default {
+						function = "ADC1";
+						groups = "ADC1";
+					};
+
+					pinctrl_adc10_default: adc10_default {
+						function = "ADC10";
+						groups = "ADC10";
+					};
+
+					pinctrl_adc11_default: adc11_default {
+						function = "ADC11";
+						groups = "ADC11";
+					};
+
+					pinctrl_adc12_default: adc12_default {
+						function = "ADC12";
+						groups = "ADC12";
+					};
+
+					pinctrl_adc13_default: adc13_default {
+						function = "ADC13";
+						groups = "ADC13";
+					};
+
+					pinctrl_adc14_default: adc14_default {
+						function = "ADC14";
+						groups = "ADC14";
+					};
+
+					pinctrl_adc15_default: adc15_default {
+						function = "ADC15";
+						groups = "ADC15";
+					};
+
+					pinctrl_adc2_default: adc2_default {
+						function = "ADC2";
+						groups = "ADC2";
+					};
+
+					pinctrl_adc3_default: adc3_default {
+						function = "ADC3";
+						groups = "ADC3";
+					};
+
+					pinctrl_adc4_default: adc4_default {
+						function = "ADC4";
+						groups = "ADC4";
+					};
+
+					pinctrl_adc5_default: adc5_default {
+						function = "ADC5";
+						groups = "ADC5";
+					};
+
+					pinctrl_adc6_default: adc6_default {
+						function = "ADC6";
+						groups = "ADC6";
+					};
+
+					pinctrl_adc7_default: adc7_default {
+						function = "ADC7";
+						groups = "ADC7";
+					};
+
+					pinctrl_adc8_default: adc8_default {
+						function = "ADC8";
+						groups = "ADC8";
+					};
+
+					pinctrl_adc9_default: adc9_default {
+						function = "ADC9";
+						groups = "ADC9";
+					};
+
+					pinctrl_bmcint_default: bmcint_default {
+						function = "BMCINT";
+						groups = "BMCINT";
+					};
+
+					pinctrl_ddcclk_default: ddcclk_default {
+						function = "DDCCLK";
+						groups = "DDCCLK";
+					};
+
+					pinctrl_ddcdat_default: ddcdat_default {
+						function = "DDCDAT";
+						groups = "DDCDAT";
+					};
+
+					pinctrl_espi_default: espi_default {
+						function = "ESPI";
+						groups = "ESPI";
+					};
+
+					pinctrl_fwspics1_default: fwspics1_default {
+						function = "FWSPICS1";
+						groups = "FWSPICS1";
+					};
+
+					pinctrl_fwspics2_default: fwspics2_default {
+						function = "FWSPICS2";
+						groups = "FWSPICS2";
+					};
+
+					pinctrl_gpid0_default: gpid0_default {
+						function = "GPID0";
+						groups = "GPID0";
+					};
+
+					pinctrl_gpid2_default: gpid2_default {
+						function = "GPID2";
+						groups = "GPID2";
+					};
+
+					pinctrl_gpid4_default: gpid4_default {
+						function = "GPID4";
+						groups = "GPID4";
+					};
+
+					pinctrl_gpid6_default: gpid6_default {
+						function = "GPID6";
+						groups = "GPID6";
+					};
+
+					pinctrl_gpie0_default: gpie0_default {
+						function = "GPIE0";
+						groups = "GPIE0";
+					};
+
+					pinctrl_gpie2_default: gpie2_default {
+						function = "GPIE2";
+						groups = "GPIE2";
+					};
+
+					pinctrl_gpie4_default: gpie4_default {
+						function = "GPIE4";
+						groups = "GPIE4";
+					};
+
+					pinctrl_gpie6_default: gpie6_default {
+						function = "GPIE6";
+						groups = "GPIE6";
+					};
+
+					pinctrl_i2c10_default: i2c10_default {
+						function = "I2C10";
+						groups = "I2C10";
+					};
+
+					pinctrl_i2c11_default: i2c11_default {
+						function = "I2C11";
+						groups = "I2C11";
+					};
+
+					pinctrl_i2c12_default: i2c12_default {
+						function = "I2C12";
+						groups = "I2C12";
+					};
+
+					pinctrl_i2c13_default: i2c13_default {
+						function = "I2C13";
+						groups = "I2C13";
+					};
+
+					pinctrl_i2c14_default: i2c14_default {
+						function = "I2C14";
+						groups = "I2C14";
+					};
+
+					pinctrl_i2c3_default: i2c3_default {
+						function = "I2C3";
+						groups = "I2C3";
+					};
+
+					pinctrl_i2c4_default: i2c4_default {
+						function = "I2C4";
+						groups = "I2C4";
+					};
+
+					pinctrl_i2c5_default: i2c5_default {
+						function = "I2C5";
+						groups = "I2C5";
+					};
+
+					pinctrl_i2c6_default: i2c6_default {
+						function = "I2C6";
+						groups = "I2C6";
+					};
+
+					pinctrl_i2c7_default: i2c7_default {
+						function = "I2C7";
+						groups = "I2C7";
+					};
+
+					pinctrl_i2c8_default: i2c8_default {
+						function = "I2C8";
+						groups = "I2C8";
+					};
+
+					pinctrl_i2c9_default: i2c9_default {
+						function = "I2C9";
+						groups = "I2C9";
+					};
+
+					pinctrl_lad0_default: lad0_default {
+						function = "LAD0";
+						groups = "LAD0";
+					};
+
+					pinctrl_lad1_default: lad1_default {
+						function = "LAD1";
+						groups = "LAD1";
+					};
+
+					pinctrl_lad2_default: lad2_default {
+						function = "LAD2";
+						groups = "LAD2";
+					};
+
+					pinctrl_lad3_default: lad3_default {
+						function = "LAD3";
+						groups = "LAD3";
+					};
+
+					pinctrl_lclk_default: lclk_default {
+						function = "LCLK";
+						groups = "LCLK";
+					};
+
+					pinctrl_lframe_default: lframe_default {
+						function = "LFRAME";
+						groups = "LFRAME";
+					};
+
+					pinctrl_lpchc_default: lpchc_default {
+						function = "LPCHC";
+						groups = "LPCHC";
+					};
+
+					pinctrl_lpcpd_default: lpcpd_default {
+						function = "LPCPD";
+						groups = "LPCPD";
+					};
+
+					pinctrl_lpcplus_default: lpcplus_default {
+						function = "LPCPLUS";
+						groups = "LPCPLUS";
+					};
+
+					pinctrl_lpcpme_default: lpcpme_default {
+						function = "LPCPME";
+						groups = "LPCPME";
+					};
+
+					pinctrl_lpcrst_default: lpcrst_default {
+						function = "LPCRST";
+						groups = "LPCRST";
+					};
+
+					pinctrl_lpcsmi_default: lpcsmi_default {
+						function = "LPCSMI";
+						groups = "LPCSMI";
+					};
+
+					pinctrl_lsirq_default: lsirq_default {
+						function = "LSIRQ";
+						groups = "LSIRQ";
+					};
+
+					pinctrl_mac1link_default: mac1link_default {
+						function = "MAC1LINK";
+						groups = "MAC1LINK";
+					};
+
+					pinctrl_mac2link_default: mac2link_default {
+						function = "MAC2LINK";
+						groups = "MAC2LINK";
+					};
+
+					pinctrl_mdio1_default: mdio1_default {
+						function = "MDIO1";
+						groups = "MDIO1";
+					};
+
+					pinctrl_mdio2_default: mdio2_default {
+						function = "MDIO2";
+						groups = "MDIO2";
+					};
+
+					pinctrl_ncts1_default: ncts1_default {
+						function = "NCTS1";
+						groups = "NCTS1";
+					};
+
+					pinctrl_ncts2_default: ncts2_default {
+						function = "NCTS2";
+						groups = "NCTS2";
+					};
+
+					pinctrl_ncts3_default: ncts3_default {
+						function = "NCTS3";
+						groups = "NCTS3";
+					};
+
+					pinctrl_ncts4_default: ncts4_default {
+						function = "NCTS4";
+						groups = "NCTS4";
+					};
+
+					pinctrl_ndcd1_default: ndcd1_default {
+						function = "NDCD1";
+						groups = "NDCD1";
+					};
+
+					pinctrl_ndcd2_default: ndcd2_default {
+						function = "NDCD2";
+						groups = "NDCD2";
+					};
+
+					pinctrl_ndcd3_default: ndcd3_default {
+						function = "NDCD3";
+						groups = "NDCD3";
+					};
+
+					pinctrl_ndcd4_default: ndcd4_default {
+						function = "NDCD4";
+						groups = "NDCD4";
+					};
+
+					pinctrl_ndsr1_default: ndsr1_default {
+						function = "NDSR1";
+						groups = "NDSR1";
+					};
+
+					pinctrl_ndsr2_default: ndsr2_default {
+						function = "NDSR2";
+						groups = "NDSR2";
+					};
+
+					pinctrl_ndsr3_default: ndsr3_default {
+						function = "NDSR3";
+						groups = "NDSR3";
+					};
+
+					pinctrl_ndsr4_default: ndsr4_default {
+						function = "NDSR4";
+						groups = "NDSR4";
+					};
+
+					pinctrl_ndtr1_default: ndtr1_default {
+						function = "NDTR1";
+						groups = "NDTR1";
+					};
+
+					pinctrl_ndtr2_default: ndtr2_default {
+						function = "NDTR2";
+						groups = "NDTR2";
+					};
+
+					pinctrl_ndtr3_default: ndtr3_default {
+						function = "NDTR3";
+						groups = "NDTR3";
+					};
+
+					pinctrl_ndtr4_default: ndtr4_default {
+						function = "NDTR4";
+						groups = "NDTR4";
+					};
+
+					pinctrl_nri1_default: nri1_default {
+						function = "NRI1";
+						groups = "NRI1";
+					};
+
+					pinctrl_nri2_default: nri2_default {
+						function = "NRI2";
+						groups = "NRI2";
+					};
+
+					pinctrl_nri3_default: nri3_default {
+						function = "NRI3";
+						groups = "NRI3";
+					};
+
+					pinctrl_nri4_default: nri4_default {
+						function = "NRI4";
+						groups = "NRI4";
+					};
+
+					pinctrl_nrts1_default: nrts1_default {
+						function = "NRTS1";
+						groups = "NRTS1";
+					};
+
+					pinctrl_nrts2_default: nrts2_default {
+						function = "NRTS2";
+						groups = "NRTS2";
+					};
+
+					pinctrl_nrts3_default: nrts3_default {
+						function = "NRTS3";
+						groups = "NRTS3";
+					};
+
+					pinctrl_nrts4_default: nrts4_default {
+						function = "NRTS4";
+						groups = "NRTS4";
+					};
+
+					pinctrl_oscclk_default: oscclk_default {
+						function = "OSCCLK";
+						groups = "OSCCLK";
+					};
+
+					pinctrl_pewake_default: pewake_default {
+						function = "PEWAKE";
+						groups = "PEWAKE";
+					};
+
+					pinctrl_pnor_default: pnor_default {
+						function = "PNOR";
+						groups = "PNOR";
+					};
+
+					pinctrl_pwm0_default: pwm0_default {
+						function = "PWM0";
+						groups = "PWM0";
+					};
+
+					pinctrl_pwm1_default: pwm1_default {
+						function = "PWM1";
+						groups = "PWM1";
+					};
+
+					pinctrl_pwm2_default: pwm2_default {
+						function = "PWM2";
+						groups = "PWM2";
+					};
+
+					pinctrl_pwm3_default: pwm3_default {
+						function = "PWM3";
+						groups = "PWM3";
+					};
+
+					pinctrl_pwm4_default: pwm4_default {
+						function = "PWM4";
+						groups = "PWM4";
+					};
+
+					pinctrl_pwm5_default: pwm5_default {
+						function = "PWM5";
+						groups = "PWM5";
+					};
+
+					pinctrl_pwm6_default: pwm6_default {
+						function = "PWM6";
+						groups = "PWM6";
+					};
+
+					pinctrl_pwm7_default: pwm7_default {
+						function = "PWM7";
+						groups = "PWM7";
+					};
+
+					pinctrl_rgmii1_default: rgmii1_default {
+						function = "RGMII1";
+						groups = "RGMII1";
+					};
+
+					pinctrl_rgmii2_default: rgmii2_default {
+						function = "RGMII2";
+						groups = "RGMII2";
+					};
+
+					pinctrl_rmii1_default: rmii1_default {
+						function = "RMII1";
+						groups = "RMII1";
+					};
+
+					pinctrl_rmii2_default: rmii2_default {
+						function = "RMII2";
+						groups = "RMII2";
+					};
+
+					pinctrl_rxd1_default: rxd1_default {
+						function = "RXD1";
+						groups = "RXD1";
+					};
+
+					pinctrl_rxd2_default: rxd2_default {
+						function = "RXD2";
+						groups = "RXD2";
+					};
+
+					pinctrl_rxd3_default: rxd3_default {
+						function = "RXD3";
+						groups = "RXD3";
+					};
+
+					pinctrl_rxd4_default: rxd4_default {
+						function = "RXD4";
+						groups = "RXD4";
+					};
+
+					pinctrl_salt1_default: salt1_default {
+						function = "SALT1";
+						groups = "SALT1";
+					};
+
+					pinctrl_salt10_default: salt10_default {
+						function = "SALT10";
+						groups = "SALT10";
+					};
+
+					pinctrl_salt11_default: salt11_default {
+						function = "SALT11";
+						groups = "SALT11";
+					};
+
+					pinctrl_salt12_default: salt12_default {
+						function = "SALT12";
+						groups = "SALT12";
+					};
+
+					pinctrl_salt13_default: salt13_default {
+						function = "SALT13";
+						groups = "SALT13";
+					};
+
+					pinctrl_salt14_default: salt14_default {
+						function = "SALT14";
+						groups = "SALT14";
+					};
+
+					pinctrl_salt2_default: salt2_default {
+						function = "SALT2";
+						groups = "SALT2";
+					};
+
+					pinctrl_salt3_default: salt3_default {
+						function = "SALT3";
+						groups = "SALT3";
+					};
+
+					pinctrl_salt4_default: salt4_default {
+						function = "SALT4";
+						groups = "SALT4";
+					};
+
+					pinctrl_salt5_default: salt5_default {
+						function = "SALT5";
+						groups = "SALT5";
+					};
+
+					pinctrl_salt6_default: salt6_default {
+						function = "SALT6";
+						groups = "SALT6";
+					};
+
+					pinctrl_salt7_default: salt7_default {
+						function = "SALT7";
+						groups = "SALT7";
+					};
+
+					pinctrl_salt8_default: salt8_default {
+						function = "SALT8";
+						groups = "SALT8";
+					};
+
+					pinctrl_salt9_default: salt9_default {
+						function = "SALT9";
+						groups = "SALT9";
+					};
+
+					pinctrl_scl1_default: scl1_default {
+						function = "SCL1";
+						groups = "SCL1";
+					};
+
+					pinctrl_scl2_default: scl2_default {
+						function = "SCL2";
+						groups = "SCL2";
+					};
+
+					pinctrl_sd1_default: sd1_default {
+						function = "SD1";
+						groups = "SD1";
+					};
+
+					pinctrl_sd2_default: sd2_default {
+						function = "SD2";
+						groups = "SD2";
+					};
+
+					pinctrl_sda1_default: sda1_default {
+						function = "SDA1";
+						groups = "SDA1";
+					};
+
+					pinctrl_sda2_default: sda2_default {
+						function = "SDA2";
+						groups = "SDA2";
+					};
+
+					pinctrl_sgps1_default: sgps1_default {
+						function = "SGPS1";
+						groups = "SGPS1";
+					};
+
+					pinctrl_sgps2_default: sgps2_default {
+						function = "SGPS2";
+						groups = "SGPS2";
+					};
+
+					pinctrl_sioonctrl_default: sioonctrl_default {
+						function = "SIOONCTRL";
+						groups = "SIOONCTRL";
+					};
+
+					pinctrl_siopbi_default: siopbi_default {
+						function = "SIOPBI";
+						groups = "SIOPBI";
+					};
+
+					pinctrl_siopbo_default: siopbo_default {
+						function = "SIOPBO";
+						groups = "SIOPBO";
+					};
+
+					pinctrl_siopwreq_default: siopwreq_default {
+						function = "SIOPWREQ";
+						groups = "SIOPWREQ";
+					};
+
+					pinctrl_siopwrgd_default: siopwrgd_default {
+						function = "SIOPWRGD";
+						groups = "SIOPWRGD";
+					};
+
+					pinctrl_sios3_default: sios3_default {
+						function = "SIOS3";
+						groups = "SIOS3";
+					};
+
+					pinctrl_sios5_default: sios5_default {
+						function = "SIOS5";
+						groups = "SIOS5";
+					};
+
+					pinctrl_siosci_default: siosci_default {
+						function = "SIOSCI";
+						groups = "SIOSCI";
+					};
+
+					pinctrl_spi1_default: spi1_default {
+						function = "SPI1";
+						groups = "SPI1";
+					};
+
+					pinctrl_spi1cs1_default: spi1cs1_default {
+						function = "SPI1CS1";
+						groups = "SPI1CS1";
+					};
+
+					pinctrl_spi1debug_default: spi1debug_default {
+						function = "SPI1DEBUG";
+						groups = "SPI1DEBUG";
+					};
+
+					pinctrl_spi1passthru_default: spi1passthru_default {
+						function = "SPI1PASSTHRU";
+						groups = "SPI1PASSTHRU";
+					};
+
+					pinctrl_spi2ck_default: spi2ck_default {
+						function = "SPI2CK";
+						groups = "SPI2CK";
+					};
+
+					pinctrl_spi2cs0_default: spi2cs0_default {
+						function = "SPI2CS0";
+						groups = "SPI2CS0";
+					};
+
+					pinctrl_spi2cs1_default: spi2cs1_default {
+						function = "SPI2CS1";
+						groups = "SPI2CS1";
+					};
+
+					pinctrl_spi2miso_default: spi2miso_default {
+						function = "SPI2MISO";
+						groups = "SPI2MISO";
+					};
+
+					pinctrl_spi2mosi_default: spi2mosi_default {
+						function = "SPI2MOSI";
+						groups = "SPI2MOSI";
+					};
+
+					pinctrl_timer3_default: timer3_default {
+						function = "TIMER3";
+						groups = "TIMER3";
+					};
+
+					pinctrl_timer4_default: timer4_default {
+						function = "TIMER4";
+						groups = "TIMER4";
+					};
+
+					pinctrl_timer5_default: timer5_default {
+						function = "TIMER5";
+						groups = "TIMER5";
+					};
+
+					pinctrl_timer6_default: timer6_default {
+						function = "TIMER6";
+						groups = "TIMER6";
+					};
+
+					pinctrl_timer7_default: timer7_default {
+						function = "TIMER7";
+						groups = "TIMER7";
+					};
+
+					pinctrl_timer8_default: timer8_default {
+						function = "TIMER8";
+						groups = "TIMER8";
+					};
+
+					pinctrl_txd1_default: txd1_default {
+						function = "TXD1";
+						groups = "TXD1";
+					};
+
+					pinctrl_txd2_default: txd2_default {
+						function = "TXD2";
+						groups = "TXD2";
+					};
+
+					pinctrl_txd3_default: txd3_default {
+						function = "TXD3";
+						groups = "TXD3";
+					};
+
+					pinctrl_txd4_default: txd4_default {
+						function = "TXD4";
+						groups = "TXD4";
+					};
+
+					pinctrl_uart6_default: uart6_default {
+						function = "UART6";
+						groups = "UART6";
+					};
+
+					pinctrl_usbcki_default: usbcki_default {
+						function = "USBCKI";
+						groups = "USBCKI";
+					};
+
+					pinctrl_vgabiosrom_default: vgabiosrom_default {
+						function = "VGABIOSROM";
+						groups = "VGABIOSROM";
+					};
+
+					pinctrl_vgahs_default: vgahs_default {
+						function = "VGAHS";
+						groups = "VGAHS";
+					};
+
+					pinctrl_vgavs_default: vgavs_default {
+						function = "VGAVS";
+						groups = "VGAVS";
+					};
+
+					pinctrl_vpi24_default: vpi24_default {
+						function = "VPI24";
+						groups = "VPI24";
+					};
+
+					pinctrl_vpo_default: vpo_default {
+						function = "VPO";
+						groups = "VPO";
+					};
+
+					pinctrl_wdtrst1_default: wdtrst1_default {
+						function = "WDTRST1";
+						groups = "WDTRST1";
+					};
+
+					pinctrl_wdtrst2_default: wdtrst2_default {
+						function = "WDTRST2";
+						groups = "WDTRST2";
+					};
+
+				};
+			};
+
 			clk_hpll: clk_hpll at 1e6e2024 {
 				#clock-cells = <0>;
 				compatible = "aspeed,g5-hpll-clock";
@@ -75,11 +907,27 @@
 				reg = <0x1e6e202c 0x4>;
 			};
 
+			gfx: display at 1e6e6000 {
+				compatible = "aspeed,ast2500-gfx", "syscon";
+				reg = <0x1e6e6000 0x1000>;
+				reg-io-width = <4>;
+			};
+
 			sram at 1e720000 {
 				compatible = "mmio-sram";
 				reg = <0x1e720000 0x9000>;	// 36K
 			};
 
+			gpio: gpio at 1e780000 {
+				#gpio-cells = <2>;
+				gpio-controller;
+				compatible = "aspeed,ast2500-gpio";
+				reg = <0x1e780000 0x1000>;
+				interrupts = <20>;
+				gpio-ranges = <&pinctrl 0 0 220>;
+				interrupt-controller;
+			};
+
 			timer: timer at 1e782000 {
 				compatible = "aspeed,ast2400-timer";
 				reg = <0x1e782000 0x90>;
@@ -90,6 +938,7 @@
 				clocks = <&clk_apb>;
 			};
 
+
 			wdt1: wdt at 1e785000 {
 				compatible = "aspeed,wdt";
 				reg = <0x1e785000 0x1c>;
@@ -119,6 +968,36 @@
 				status = "disabled";
 			};
 
+			lpc: lpc at 1e789000 {
+				compatible = "aspeed,ast2500-lpc", "simple-mfd";
+				reg = <0x1e789000 0x1000>;
+
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x1e789000 0x1000>;
+
+				lpc_bmc: lpc-bmc at 0 {
+					compatible = "aspeed,ast2500-lpc-bmc";
+					reg = <0x0 0x80>;
+				};
+
+				lpc_host: lpc-host at 80 {
+					compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
+					reg = <0x80 0x1e0>;
+
+					#address-cells = <1>;
+					#size-cells = <1>;
+					ranges = <0 0x80 0x1e0>;
+
+					reg-io-width = <4>;
+
+					lhc: lhc at 20 {
+						compatible = "aspeed,ast2500-lhc";
+						reg = <0x20 0x24 0x48 0x8>;
+					};
+				};
+			};
+
 			uart2: serial at 1e78d000 {
 				compatible = "ns16550a";
 				reg = <0x1e78d000 0x1000>;
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 02/15] dm: Simple Watchdog uclass
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Stephen Warren

This is a simple uclass for Watchdog Timers. It has four operations:
start, restart, reset, stop. Drivers must implement start, restart and
stop operations, while implementing reset is optional: It's default
implementation expires watchdog timer in one clock tick.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1:
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests


---
 arch/sandbox/dts/test.dts        |   4 ++
 arch/sandbox/include/asm/state.h |   9 ++++
 configs/sandbox_defconfig        |   2 +
 drivers/watchdog/Kconfig         |  21 ++++++++
 drivers/watchdog/Makefile        |   2 +
 drivers/watchdog/sandbox_wdt.c   |  76 +++++++++++++++++++++++++++
 drivers/watchdog/wdt-uclass.c    |  72 ++++++++++++++++++++++++++
 include/dm/uclass-id.h           |   1 +
 include/wdt.h                    | 107 +++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile                 |   1 +
 test/dm/wdt.c                    |  40 +++++++++++++++
 11 files changed, 335 insertions(+)
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fff175d1b7..e04ecc64cc 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -418,6 +418,10 @@
 			};
 		};
 	};
+
+	wdt0: wdt@0 {
+		compatible = "sandbox,wdt";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 149f28d873..987cc7b49d 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -39,6 +39,12 @@ struct sandbox_spi_info {
 	struct udevice *emul;
 };
 
+struct sandbox_wdt_info {
+	unsigned long long counter;
+	uint reset_count;
+	bool running;
+};
+
 /* The complete state of the test system */
 struct sandbox_state {
 	const char *cmd;		/* Command to execute */
@@ -69,6 +75,9 @@ struct sandbox_state {
 	/* Pointer to information for each SPI bus/cs */
 	struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
 					[CONFIG_SANDBOX_SPI_MAX_CS];
+
+	/* Information about Watchdog */
+	struct sandbox_wdt_info wdt;
 };
 
 /* Minimum space we guarantee in the state FDT when calling read/write*/
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 01f6f5d5c6..a5f63e027f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -171,3 +171,5 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_WDT=y
+CONFIG_WDT_SANDBOX=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e69de29bb2..7a725f1e6d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -0,0 +1,21 @@
+menu "Watchdog Timer Support"
+
+config WDT
+	bool "Enable driver model for watchdog timer drivers"
+	depends on DM
+	help
+	  Enable driver model for watchdog timer. At the moment the API
+	  is very simple and only supports four operations:
+	  start, restart, stop and reset (expire immediately).
+	  What exactly happens when the timer expires is up to a particular
+	  device/driver.
+
+config WDT_SANDBOX
+	bool "Enable Watchdog Timer support for Sandbox"
+	depends on SANDBOX && WDT
+	help
+		Enable Watchdog Timer support in Sandbox. This is a dummy device that
+		can be probed and supports all of the methods of WDT, but does not
+		really do anything.
+
+endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a007ae8234..f523d34d57 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -15,3 +15,5 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
 obj-$(CONFIG_BFIN_WATCHDOG)  += bfin_wdt.o
 obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
+obj-$(CONFIG_WDT) += wdt-uclass.o
+obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
diff --git a/drivers/watchdog/sandbox_wdt.c b/drivers/watchdog/sandbox_wdt.c
new file mode 100644
index 0000000000..34d90bee7e
--- /dev/null
+++ b/drivers/watchdog/sandbox_wdt.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/state.h>
+#include <wdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.counter = timeout;
+	state->wdt.running = true;
+
+	return 0;
+}
+
+static int sandbox_wdt_stop(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.running = false;
+
+	return 0;
+}
+
+static int sandbox_wdt_reset(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.reset_count++;
+
+	return 0;
+}
+
+static int sandbox_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	sandbox_wdt_start(dev, 1, flags);
+
+	return 0;
+}
+
+static int sandbox_wdt_probe(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	memset(&state->wdt, 0, sizeof(state->wdt));
+
+	return 0;
+}
+
+static const struct wdt_ops sandbox_wdt_ops = {
+	.start = sandbox_wdt_start,
+	.reset = sandbox_wdt_reset,
+	.stop = sandbox_wdt_stop,
+	.expire_now = sandbox_wdt_expire_now,
+};
+
+static const struct udevice_id sandbox_wdt_ids[] = {
+	{ .compatible = "sandbox,wdt" },
+	{}
+};
+
+U_BOOT_DRIVER(wdt_sandbox) = {
+	.name = "wdt_sandbox",
+	.id = UCLASS_WDT,
+	.of_match = sandbox_wdt_ids,
+	.ops = &sandbox_wdt_ops,
+	.probe = sandbox_wdt_probe,
+};
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
new file mode 100644
index 0000000000..ab8a64c354
--- /dev/null
+++ b/drivers/watchdog/wdt-uclass.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->start)
+		return -ENOSYS;
+
+	return ops->start(dev, timeout, flags);
+}
+
+int wdt_stop(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->stop)
+		return -ENOSYS;
+
+	return ops->stop(dev);
+}
+
+int wdt_reset(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->reset)
+		return -ENOSYS;
+
+	return ops->reset(dev);
+}
+
+int wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	int ret = 0;
+	const struct wdt_ops *ops;
+
+	debug("WDT Resettting: %lu\n", flags);
+	ops = device_get_ops(dev);
+	if (ops->expire_now) {
+		return ops->expire_now(dev, flags);
+	} else {
+		if (!ops->start)
+			return -ENOSYS;
+
+		ret = ops->start(dev, 1, flags);
+		if (ret < 0)
+			return ret;
+
+		hang();
+	}
+
+	return ret;
+}
+
+UCLASS_DRIVER(wdt) = {
+	.id		= UCLASS_WDT,
+	.name		= "wdt",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8c92d0b030..b73a7fd436 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -83,6 +83,7 @@ enum uclass_id {
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
+	UCLASS_WDT,		/* Watchdot Timer driver */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/wdt.h b/include/wdt.h
new file mode 100644
index 0000000000..0b5f05851a
--- /dev/null
+++ b/include/wdt.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _WDT_H_
+#define _WDT_H_
+
+/*
+ * Implement a simple watchdog uclass. Watchdog is basically a timer that
+ * is used to detect or recover from malfunction. During normal operation
+ * the watchdog would be regularly reset to prevent it from timing out.
+ * If, due to a hardware fault or program error, the computer fails to reset
+ * the watchdog, the timer will elapse and generate a timeout signal.
+ * The timeout signal is used to initiate corrective action or actions,
+ * which typically include placing the system in a safe, known state.
+ */
+
+/*
+ * Start the timer
+ *
+ * @dev: WDT Device
+ * @timeout: Number of ticks before timer expires
+ * @flags: Driver specific flags. This might be used to specify
+ * which action needs to be executed when the timer expires
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags);
+
+/*
+ * Stop the timer, thus disabling the Watchdog. Use wdt_start to start it again.
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_stop(struct udevice *dev);
+
+/*
+ * Reset the timer, typically restoring the counter to
+ * the value configured by start()
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_reset(struct udevice *dev);
+
+/*
+ * Expire the timer, thus executing its action immediately.
+ * This is typically used to reset the board or peripherals.
+ *
+ * @dev: WDT Device
+ * @flags: Driver specific flags
+ * @return 0 if OK -ve on error. If wdt action is system reset,
+ * this function may never return.
+ */
+int wdt_expire_now(struct udevice *dev, ulong flags);
+
+/*
+ * struct wdt_ops - Driver model wdt operations
+ *
+ * The uclass interface is implemented by all wdt devices which use
+ * driver model.
+ */
+struct wdt_ops {
+	/*
+	 * Start the timer
+	 *
+	 * @dev: WDT Device
+	 * @timeout: Number of ticks before the timer expires
+	 * @flags: Driver specific flags. This might be used to specify
+	 * which action needs to be executed when the timer expires
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*start)(struct udevice *dev, u64 timeout, ulong flags);
+	/*
+	 * Stop the timer
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*stop)(struct udevice *dev);
+	/*
+	 * Reset the timer, typically restoring the counter to
+	 * the value configured by start()
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*reset)(struct udevice *dev);
+	/*
+	 * Expire the timer, thus executing the action immediately (optional)
+	 *
+	 * If this function is not provided, a default implementation
+	 * will be used, which sets the counter to 1
+	 * and waits forever. This is good enough for system level
+	 * reset, where the function is not expected to return, but might not be
+	 * good enough for other use cases.
+	 *
+	 * @dev: WDT Device
+	 * @flags: Driver specific flags
+	 * @return 0 if OK -ve on error. May not return.
+	 */
+	int (*expire_now)(struct udevice *dev, ulong flags);
+};
+
+#endif  /* _WDT_H_ */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1885e17c38..78d14c27e6 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -41,4 +41,5 @@ obj-$(CONFIG_TIMER) += timer.o
 obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 obj-$(CONFIG_SPMI) += spmi.o
+obj-$(CONFIG_WDT) += wdt.o
 endif
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
new file mode 100644
index 0000000000..2ecfceaaff
--- /dev/null
+++ b/test/dm/wdt.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Test that watchdog driver functions are called */
+static int dm_test_wdt_base(struct unit_test_state *uts)
+{
+	struct sandbox_state *state = state_get_current();
+	struct udevice *dev;
+	const u64 timeout = 42;
+
+	ut_assertok(uclass_get_device(UCLASS_WDT, 0, &dev));
+	ut_asserteq(0, state->wdt.counter);
+	ut_asserteq(false, state->wdt.running);
+
+	ut_assertok(wdt_start(dev, timeout, 0));
+	ut_asserteq(timeout, state->wdt.counter);
+	ut_asserteq(true, state->wdt.running);
+
+	uint reset_count = state->wdt.reset_count;
+	ut_assertok(wdt_reset(dev));
+	ut_asserteq(reset_count + 1, state->wdt.reset_count);
+	ut_asserteq(true, state->wdt.running);
+
+	ut_assertok(wdt_stop(dev));
+	ut_asserteq(false, state->wdt.running);
+
+	return 0;
+}
+DM_TEST(dm_test_wdt_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 02/15] dm: Simple Watchdog uclass
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

This is a simple uclass for Watchdog Timers. It has four operations:
start, restart, reset, stop. Drivers must implement start, restart and
stop operations, while implementing reset is optional: It's default
implementation expires watchdog timer in one clock tick.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1:
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests


---
 arch/sandbox/dts/test.dts        |   4 ++
 arch/sandbox/include/asm/state.h |   9 ++++
 configs/sandbox_defconfig        |   2 +
 drivers/watchdog/Kconfig         |  21 ++++++++
 drivers/watchdog/Makefile        |   2 +
 drivers/watchdog/sandbox_wdt.c   |  76 +++++++++++++++++++++++++++
 drivers/watchdog/wdt-uclass.c    |  72 ++++++++++++++++++++++++++
 include/dm/uclass-id.h           |   1 +
 include/wdt.h                    | 107 +++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile                 |   1 +
 test/dm/wdt.c                    |  40 +++++++++++++++
 11 files changed, 335 insertions(+)
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fff175d1b7..e04ecc64cc 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -418,6 +418,10 @@
 			};
 		};
 	};
+
+	wdt0: wdt at 0 {
+		compatible = "sandbox,wdt";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 149f28d873..987cc7b49d 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -39,6 +39,12 @@ struct sandbox_spi_info {
 	struct udevice *emul;
 };
 
+struct sandbox_wdt_info {
+	unsigned long long counter;
+	uint reset_count;
+	bool running;
+};
+
 /* The complete state of the test system */
 struct sandbox_state {
 	const char *cmd;		/* Command to execute */
@@ -69,6 +75,9 @@ struct sandbox_state {
 	/* Pointer to information for each SPI bus/cs */
 	struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
 					[CONFIG_SANDBOX_SPI_MAX_CS];
+
+	/* Information about Watchdog */
+	struct sandbox_wdt_info wdt;
 };
 
 /* Minimum space we guarantee in the state FDT when calling read/write*/
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 01f6f5d5c6..a5f63e027f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -171,3 +171,5 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_WDT=y
+CONFIG_WDT_SANDBOX=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e69de29bb2..7a725f1e6d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -0,0 +1,21 @@
+menu "Watchdog Timer Support"
+
+config WDT
+	bool "Enable driver model for watchdog timer drivers"
+	depends on DM
+	help
+	  Enable driver model for watchdog timer. At the moment the API
+	  is very simple and only supports four operations:
+	  start, restart, stop and reset (expire immediately).
+	  What exactly happens when the timer expires is up to a particular
+	  device/driver.
+
+config WDT_SANDBOX
+	bool "Enable Watchdog Timer support for Sandbox"
+	depends on SANDBOX && WDT
+	help
+		Enable Watchdog Timer support in Sandbox. This is a dummy device that
+		can be probed and supports all of the methods of WDT, but does not
+		really do anything.
+
+endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a007ae8234..f523d34d57 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -15,3 +15,5 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
 obj-$(CONFIG_BFIN_WATCHDOG)  += bfin_wdt.o
 obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
+obj-$(CONFIG_WDT) += wdt-uclass.o
+obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
diff --git a/drivers/watchdog/sandbox_wdt.c b/drivers/watchdog/sandbox_wdt.c
new file mode 100644
index 0000000000..34d90bee7e
--- /dev/null
+++ b/drivers/watchdog/sandbox_wdt.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/state.h>
+#include <wdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.counter = timeout;
+	state->wdt.running = true;
+
+	return 0;
+}
+
+static int sandbox_wdt_stop(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.running = false;
+
+	return 0;
+}
+
+static int sandbox_wdt_reset(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.reset_count++;
+
+	return 0;
+}
+
+static int sandbox_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	sandbox_wdt_start(dev, 1, flags);
+
+	return 0;
+}
+
+static int sandbox_wdt_probe(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	memset(&state->wdt, 0, sizeof(state->wdt));
+
+	return 0;
+}
+
+static const struct wdt_ops sandbox_wdt_ops = {
+	.start = sandbox_wdt_start,
+	.reset = sandbox_wdt_reset,
+	.stop = sandbox_wdt_stop,
+	.expire_now = sandbox_wdt_expire_now,
+};
+
+static const struct udevice_id sandbox_wdt_ids[] = {
+	{ .compatible = "sandbox,wdt" },
+	{}
+};
+
+U_BOOT_DRIVER(wdt_sandbox) = {
+	.name = "wdt_sandbox",
+	.id = UCLASS_WDT,
+	.of_match = sandbox_wdt_ids,
+	.ops = &sandbox_wdt_ops,
+	.probe = sandbox_wdt_probe,
+};
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
new file mode 100644
index 0000000000..ab8a64c354
--- /dev/null
+++ b/drivers/watchdog/wdt-uclass.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->start)
+		return -ENOSYS;
+
+	return ops->start(dev, timeout, flags);
+}
+
+int wdt_stop(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->stop)
+		return -ENOSYS;
+
+	return ops->stop(dev);
+}
+
+int wdt_reset(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->reset)
+		return -ENOSYS;
+
+	return ops->reset(dev);
+}
+
+int wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	int ret = 0;
+	const struct wdt_ops *ops;
+
+	debug("WDT Resettting: %lu\n", flags);
+	ops = device_get_ops(dev);
+	if (ops->expire_now) {
+		return ops->expire_now(dev, flags);
+	} else {
+		if (!ops->start)
+			return -ENOSYS;
+
+		ret = ops->start(dev, 1, flags);
+		if (ret < 0)
+			return ret;
+
+		hang();
+	}
+
+	return ret;
+}
+
+UCLASS_DRIVER(wdt) = {
+	.id		= UCLASS_WDT,
+	.name		= "wdt",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8c92d0b030..b73a7fd436 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -83,6 +83,7 @@ enum uclass_id {
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
+	UCLASS_WDT,		/* Watchdot Timer driver */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/wdt.h b/include/wdt.h
new file mode 100644
index 0000000000..0b5f05851a
--- /dev/null
+++ b/include/wdt.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _WDT_H_
+#define _WDT_H_
+
+/*
+ * Implement a simple watchdog uclass. Watchdog is basically a timer that
+ * is used to detect or recover from malfunction. During normal operation
+ * the watchdog would be regularly reset to prevent it from timing out.
+ * If, due to a hardware fault or program error, the computer fails to reset
+ * the watchdog, the timer will elapse and generate a timeout signal.
+ * The timeout signal is used to initiate corrective action or actions,
+ * which typically include placing the system in a safe, known state.
+ */
+
+/*
+ * Start the timer
+ *
+ * @dev: WDT Device
+ * @timeout: Number of ticks before timer expires
+ * @flags: Driver specific flags. This might be used to specify
+ * which action needs to be executed when the timer expires
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags);
+
+/*
+ * Stop the timer, thus disabling the Watchdog. Use wdt_start to start it again.
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_stop(struct udevice *dev);
+
+/*
+ * Reset the timer, typically restoring the counter to
+ * the value configured by start()
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_reset(struct udevice *dev);
+
+/*
+ * Expire the timer, thus executing its action immediately.
+ * This is typically used to reset the board or peripherals.
+ *
+ * @dev: WDT Device
+ * @flags: Driver specific flags
+ * @return 0 if OK -ve on error. If wdt action is system reset,
+ * this function may never return.
+ */
+int wdt_expire_now(struct udevice *dev, ulong flags);
+
+/*
+ * struct wdt_ops - Driver model wdt operations
+ *
+ * The uclass interface is implemented by all wdt devices which use
+ * driver model.
+ */
+struct wdt_ops {
+	/*
+	 * Start the timer
+	 *
+	 * @dev: WDT Device
+	 * @timeout: Number of ticks before the timer expires
+	 * @flags: Driver specific flags. This might be used to specify
+	 * which action needs to be executed when the timer expires
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*start)(struct udevice *dev, u64 timeout, ulong flags);
+	/*
+	 * Stop the timer
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*stop)(struct udevice *dev);
+	/*
+	 * Reset the timer, typically restoring the counter to
+	 * the value configured by start()
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*reset)(struct udevice *dev);
+	/*
+	 * Expire the timer, thus executing the action immediately (optional)
+	 *
+	 * If this function is not provided, a default implementation
+	 * will be used, which sets the counter to 1
+	 * and waits forever. This is good enough for system level
+	 * reset, where the function is not expected to return, but might not be
+	 * good enough for other use cases.
+	 *
+	 * @dev: WDT Device
+	 * @flags: Driver specific flags
+	 * @return 0 if OK -ve on error. May not return.
+	 */
+	int (*expire_now)(struct udevice *dev, ulong flags);
+};
+
+#endif  /* _WDT_H_ */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1885e17c38..78d14c27e6 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -41,4 +41,5 @@ obj-$(CONFIG_TIMER) += timer.o
 obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 obj-$(CONFIG_SPMI) += spmi.o
+obj-$(CONFIG_WDT) += wdt.o
 endif
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
new file mode 100644
index 0000000000..2ecfceaaff
--- /dev/null
+++ b/test/dm/wdt.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Test that watchdog driver functions are called */
+static int dm_test_wdt_base(struct unit_test_state *uts)
+{
+	struct sandbox_state *state = state_get_current();
+	struct udevice *dev;
+	const u64 timeout = 42;
+
+	ut_assertok(uclass_get_device(UCLASS_WDT, 0, &dev));
+	ut_asserteq(0, state->wdt.counter);
+	ut_asserteq(false, state->wdt.running);
+
+	ut_assertok(wdt_start(dev, timeout, 0));
+	ut_asserteq(timeout, state->wdt.counter);
+	ut_asserteq(true, state->wdt.running);
+
+	uint reset_count = state->wdt.reset_count;
+	ut_assertok(wdt_reset(dev));
+	ut_asserteq(reset_count + 1, state->wdt.reset_count);
+	ut_asserteq(true, state->wdt.running);
+
+	ut_assertok(wdt_stop(dev));
+	ut_asserteq(false, state->wdt.running);
+
+	return 0;
+}
+DM_TEST(dm_test_wdt_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 03/15] aspeed: Watchdog Timer Driver
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

This driver supports ast2500 and ast2400 SoCs.
Only ast2500 supports reset_mask and thus the option of resettting
individual peripherals using WDT.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Rename reset to expire_now
- Rename restart to reset


---
 arch/arm/include/asm/arch-aspeed/wdt.h |  53 ++++++++++++--
 arch/arm/mach-aspeed/ast_wdt.c         |  40 ++++++++---
 drivers/watchdog/Kconfig               |  11 +++
 drivers/watchdog/Makefile              |   1 +
 drivers/watchdog/ast_wdt.c             | 125 +++++++++++++++++++++++++++++++++
 5 files changed, 217 insertions(+), 13 deletions(-)
 create mode 100644 drivers/watchdog/ast_wdt.c

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index b292a0e67b..981fa05a56 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -67,15 +67,60 @@ struct ast_wdt {
 	u32 timeout_status;
 	u32 clr_timeout_status;
 	u32 reset_width;
-#ifdef CONFIG_ASPEED_AST2500
+	/* On pre-ast2500 SoCs this register is reserved. */
 	u32 reset_mask;
-#else
-	u32 reserved0;
-#endif
 };
 
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mode value from it.
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mode value
+ */
+u32 ast_reset_mode_from_flags(ulong flags);
+
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mask value from it. Reset Mask is only supported on ast2500
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mask value
+ */
+u32 ast_reset_mask_from_flags(ulong flags);
+
+/**
+ * Given Reset Mask and Reset Mode values, converts them to flags,
+ * suitable for passing into wdt_start or wdt_reset uclass functions.
+ *
+ * On ast2500 Reset Mask is 25 bits wide and Reset Mode is 2 bits wide, so they
+ * can both be packed into single 32 bits wide value.
+ *
+ * @reset_mode: Reset Mode
+ * @reset_mask: Reset Mask
+ */
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
+
+#ifndef CONFIG_WDT
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to stop
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_stop(struct ast_wdt *wdt);
+
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to start
+ * @timeout	watchdog timeout in number of clock ticks
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_start(struct ast_wdt *wdt, u32 timeout);
+#endif  /* CONFIG_WDT */
 
 /**
  * Reset peripherals specified by mask
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 22481ab7ea..895fba3366 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -9,6 +9,27 @@
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
+u32 ast_reset_mode_from_flags(ulong flags)
+{
+	return flags & WDT_CTRL_RESET_MASK;
+}
+
+u32 ast_reset_mask_from_flags(ulong flags)
+{
+	return flags >> 2;
+}
+
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
+{
+	ulong ret = reset_mode & WDT_CTRL_RESET_MASK;
+
+	if (ret == WDT_CTRL_RESET_SOC)
+		ret |= (reset_mask << 2);
+
+	return ret;
+}
+
+#ifndef CONFIG_WDT
 void wdt_stop(struct ast_wdt *wdt)
 {
 	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
@@ -26,15 +47,7 @@ void wdt_start(struct ast_wdt *wdt, u32 timeout)
 	setbits_le32(&wdt->ctrl,
 		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
 }
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
+#endif  /* CONFIG_WDT */
 
 int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 {
@@ -57,3 +70,12 @@ int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 	return -EINVAL;
 #endif
 }
+
+struct ast_wdt *ast_get_wdt(u8 wdt_number)
+{
+	if (wdt_number > CONFIG_WDT_NUM - 1)
+		return ERR_PTR(-EINVAL);
+
+	return (struct ast_wdt *)(WDT_BASE +
+				  sizeof(struct ast_wdt) * wdt_number);
+}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7a725f1e6d..fab8dc9034 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -18,4 +18,15 @@ config WDT_SANDBOX
 		can be probed and supports all of the methods of WDT, but does not
 		really do anything.
 
+config WDT_ASPEED
+	bool "Aspeed ast2400/ast2500 watchdog timer support"
+	depends on WDT
+	default y if ARCH_ASPEED
+	help
+	  Select this to enable watchdog timer for Aspeed ast2500/ast2400 devices.
+	  The watchdog timer is stopped when initialized. It performs reset, either
+	  full SoC reset or CPU or just some peripherals, based on the flags.
+	  It currently does not support Boot Flash Addressing Mode Detection or
+	  Second Boot.
+
 endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f523d34d57..a30dd661b1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
 obj-$(CONFIG_WDT) += wdt-uclass.o
 obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
+obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
new file mode 100644
index 0000000000..b2bd912ad5
--- /dev/null
+++ b/drivers/watchdog/ast_wdt.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/wdt.h>
+
+#define WDT_AST2500	2500
+#define WDT_AST2400	2400
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast_wdt_priv {
+	struct ast_wdt *regs;
+};
+
+static int ast_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	ulong driver_data = dev_get_driver_data(dev);
+	u32 reset_mode = ast_reset_mode_from_flags(flags);
+
+	clrsetbits_le32(&priv->regs->ctrl,
+			WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT,
+			reset_mode << WDT_CTRL_RESET_MODE_SHIFT);
+
+	if (driver_data >= WDT_AST2500 && reset_mode == WDT_CTRL_RESET_SOC)
+		writel(ast_reset_mask_from_flags(flags),
+		       &priv->regs->reset_mask);
+
+	writel((u32) timeout, &priv->regs->counter_reload_val);
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+	/*
+	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
+	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
+	 * read-only
+	 */
+	setbits_le32(&priv->regs->ctrl,
+		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
+
+	return 0;
+}
+
+static int ast_wdt_stop(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN);
+
+	return 0;
+}
+
+static int ast_wdt_reset(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+
+	return 0;
+}
+
+static int ast_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_wdt_start(dev, 1, flags);
+	if (ret)
+		return ret;
+
+	while (readl(&priv->regs->ctrl) & WDT_CTRL_EN)
+		;
+
+	return ast_wdt_stop(dev);
+}
+
+static int ast_wdt_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	return 0;
+}
+
+static const struct wdt_ops ast_wdt_ops = {
+	.start = ast_wdt_start,
+	.reset = ast_wdt_reset,
+	.stop = ast_wdt_stop,
+	.expire_now = ast_wdt_expire_now,
+};
+
+static const struct udevice_id ast_wdt_ids[] = {
+	{ .compatible = "aspeed,wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2500-wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2400-wdt", .data = WDT_AST2400 },
+	{}
+};
+
+static int ast_wdt_probe(struct udevice *dev)
+{
+	debug("%s() wdt%u\n", __func__, dev->seq);
+	ast_wdt_stop(dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(ast_wdt) = {
+	.name = "ast_wdt",
+	.id = UCLASS_WDT,
+	.of_match = ast_wdt_ids,
+	.probe = ast_wdt_probe,
+	.priv_auto_alloc_size = sizeof(struct ast_wdt_priv),
+	.ofdata_to_platdata = ast_wdt_ofdata_to_platdata,
+	.ops = &ast_wdt_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 03/15] aspeed: Watchdog Timer Driver
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

This driver supports ast2500 and ast2400 SoCs.
Only ast2500 supports reset_mask and thus the option of resettting
individual peripherals using WDT.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Rename reset to expire_now
- Rename restart to reset


---
 arch/arm/include/asm/arch-aspeed/wdt.h |  53 ++++++++++++--
 arch/arm/mach-aspeed/ast_wdt.c         |  40 ++++++++---
 drivers/watchdog/Kconfig               |  11 +++
 drivers/watchdog/Makefile              |   1 +
 drivers/watchdog/ast_wdt.c             | 125 +++++++++++++++++++++++++++++++++
 5 files changed, 217 insertions(+), 13 deletions(-)
 create mode 100644 drivers/watchdog/ast_wdt.c

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index b292a0e67b..981fa05a56 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -67,15 +67,60 @@ struct ast_wdt {
 	u32 timeout_status;
 	u32 clr_timeout_status;
 	u32 reset_width;
-#ifdef CONFIG_ASPEED_AST2500
+	/* On pre-ast2500 SoCs this register is reserved. */
 	u32 reset_mask;
-#else
-	u32 reserved0;
-#endif
 };
 
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mode value from it.
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mode value
+ */
+u32 ast_reset_mode_from_flags(ulong flags);
+
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mask value from it. Reset Mask is only supported on ast2500
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mask value
+ */
+u32 ast_reset_mask_from_flags(ulong flags);
+
+/**
+ * Given Reset Mask and Reset Mode values, converts them to flags,
+ * suitable for passing into wdt_start or wdt_reset uclass functions.
+ *
+ * On ast2500 Reset Mask is 25 bits wide and Reset Mode is 2 bits wide, so they
+ * can both be packed into single 32 bits wide value.
+ *
+ * @reset_mode: Reset Mode
+ * @reset_mask: Reset Mask
+ */
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
+
+#ifndef CONFIG_WDT
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to stop
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_stop(struct ast_wdt *wdt);
+
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to start
+ * @timeout	watchdog timeout in number of clock ticks
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_start(struct ast_wdt *wdt, u32 timeout);
+#endif  /* CONFIG_WDT */
 
 /**
  * Reset peripherals specified by mask
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 22481ab7ea..895fba3366 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -9,6 +9,27 @@
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
+u32 ast_reset_mode_from_flags(ulong flags)
+{
+	return flags & WDT_CTRL_RESET_MASK;
+}
+
+u32 ast_reset_mask_from_flags(ulong flags)
+{
+	return flags >> 2;
+}
+
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
+{
+	ulong ret = reset_mode & WDT_CTRL_RESET_MASK;
+
+	if (ret == WDT_CTRL_RESET_SOC)
+		ret |= (reset_mask << 2);
+
+	return ret;
+}
+
+#ifndef CONFIG_WDT
 void wdt_stop(struct ast_wdt *wdt)
 {
 	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
@@ -26,15 +47,7 @@ void wdt_start(struct ast_wdt *wdt, u32 timeout)
 	setbits_le32(&wdt->ctrl,
 		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
 }
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
+#endif  /* CONFIG_WDT */
 
 int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 {
@@ -57,3 +70,12 @@ int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 	return -EINVAL;
 #endif
 }
+
+struct ast_wdt *ast_get_wdt(u8 wdt_number)
+{
+	if (wdt_number > CONFIG_WDT_NUM - 1)
+		return ERR_PTR(-EINVAL);
+
+	return (struct ast_wdt *)(WDT_BASE +
+				  sizeof(struct ast_wdt) * wdt_number);
+}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7a725f1e6d..fab8dc9034 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -18,4 +18,15 @@ config WDT_SANDBOX
 		can be probed and supports all of the methods of WDT, but does not
 		really do anything.
 
+config WDT_ASPEED
+	bool "Aspeed ast2400/ast2500 watchdog timer support"
+	depends on WDT
+	default y if ARCH_ASPEED
+	help
+	  Select this to enable watchdog timer for Aspeed ast2500/ast2400 devices.
+	  The watchdog timer is stopped when initialized. It performs reset, either
+	  full SoC reset or CPU or just some peripherals, based on the flags.
+	  It currently does not support Boot Flash Addressing Mode Detection or
+	  Second Boot.
+
 endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f523d34d57..a30dd661b1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
 obj-$(CONFIG_WDT) += wdt-uclass.o
 obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
+obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
new file mode 100644
index 0000000000..b2bd912ad5
--- /dev/null
+++ b/drivers/watchdog/ast_wdt.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/wdt.h>
+
+#define WDT_AST2500	2500
+#define WDT_AST2400	2400
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast_wdt_priv {
+	struct ast_wdt *regs;
+};
+
+static int ast_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	ulong driver_data = dev_get_driver_data(dev);
+	u32 reset_mode = ast_reset_mode_from_flags(flags);
+
+	clrsetbits_le32(&priv->regs->ctrl,
+			WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT,
+			reset_mode << WDT_CTRL_RESET_MODE_SHIFT);
+
+	if (driver_data >= WDT_AST2500 && reset_mode == WDT_CTRL_RESET_SOC)
+		writel(ast_reset_mask_from_flags(flags),
+		       &priv->regs->reset_mask);
+
+	writel((u32) timeout, &priv->regs->counter_reload_val);
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+	/*
+	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
+	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
+	 * read-only
+	 */
+	setbits_le32(&priv->regs->ctrl,
+		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
+
+	return 0;
+}
+
+static int ast_wdt_stop(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN);
+
+	return 0;
+}
+
+static int ast_wdt_reset(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+
+	return 0;
+}
+
+static int ast_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_wdt_start(dev, 1, flags);
+	if (ret)
+		return ret;
+
+	while (readl(&priv->regs->ctrl) & WDT_CTRL_EN)
+		;
+
+	return ast_wdt_stop(dev);
+}
+
+static int ast_wdt_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	return 0;
+}
+
+static const struct wdt_ops ast_wdt_ops = {
+	.start = ast_wdt_start,
+	.reset = ast_wdt_reset,
+	.stop = ast_wdt_stop,
+	.expire_now = ast_wdt_expire_now,
+};
+
+static const struct udevice_id ast_wdt_ids[] = {
+	{ .compatible = "aspeed,wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2500-wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2400-wdt", .data = WDT_AST2400 },
+	{}
+};
+
+static int ast_wdt_probe(struct udevice *dev)
+{
+	debug("%s() wdt%u\n", __func__, dev->seq);
+	ast_wdt_stop(dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(ast_wdt) = {
+	.name = "ast_wdt",
+	.id = UCLASS_WDT,
+	.of_match = ast_wdt_ids,
+	.probe = ast_wdt_probe,
+	.priv_auto_alloc_size = sizeof(struct ast_wdt_priv),
+	.ofdata_to_platdata = ast_wdt_ofdata_to_platdata,
+	.ops = &ast_wdt_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Make functions for locking and unlocking SCU part of SCU API.
Many drivers need to modify settings in SCU and thus need to unlock it
first. This change makes it possible.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 14 ++++++++++++++
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     | 15 +++++++++++++++
 drivers/clk/aspeed/clk_ast2500.c               | 18 ++----------------
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fc0c01ae33..0fa3ecb9b9 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -120,6 +120,20 @@ int ast_get_clk(struct udevice **devp);
  */
 void *ast_get_scu(void);
 
+/**
+ * ast_scu_unlock() - unlock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_unlock(struct ast2500_scu *scu);
+
+/**
+ * ast_scu_lock() - lock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_lock(struct ast2500_scu *scu);
+
 #endif  /* __ASSEMBLY__ */
 
 #endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
index 079909fa64..30cfac1af0 100644
--- a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 
 int ast_get_clk(struct udevice **devp)
@@ -28,3 +29,17 @@ void *ast_get_scu(void)
 
 	return priv->scu;
 }
+
+void ast_scu_unlock(struct ast2500_scu *scu)
+{
+	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (!readl(&scu->protection_key))
+		;
+}
+
+void ast_scu_lock(struct ast2500_scu *scu)
+{
+	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (readl(&scu->protection_key))
+		;
+}
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 26a5e58221..504731271c 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -132,20 +132,6 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static void ast2500_scu_unlock(struct ast2500_scu *scu)
-{
-	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (!readl(&scu->protection_key))
-		;
-}
-
-static void ast2500_scu_lock(struct ast2500_scu *scu)
-{
-	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (readl(&scu->protection_key))
-		;
-}
-
 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 {
 	ulong clkin = ast2500_get_clkin(scu);
@@ -197,9 +183,9 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	    | (best_num << SCU_MPLL_NUM_SHIFT)
 	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
 
-	ast2500_scu_unlock(scu);
+	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
-	ast2500_scu_lock(scu);
+	ast_scu_lock(scu);
 
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Make functions for locking and unlocking SCU part of SCU API.
Many drivers need to modify settings in SCU and thus need to unlock it
first. This change makes it possible.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 14 ++++++++++++++
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     | 15 +++++++++++++++
 drivers/clk/aspeed/clk_ast2500.c               | 18 ++----------------
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fc0c01ae33..0fa3ecb9b9 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -120,6 +120,20 @@ int ast_get_clk(struct udevice **devp);
  */
 void *ast_get_scu(void);
 
+/**
+ * ast_scu_unlock() - unlock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_unlock(struct ast2500_scu *scu);
+
+/**
+ * ast_scu_lock() - lock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_lock(struct ast2500_scu *scu);
+
 #endif  /* __ASSEMBLY__ */
 
 #endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
index 079909fa64..30cfac1af0 100644
--- a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 
 int ast_get_clk(struct udevice **devp)
@@ -28,3 +29,17 @@ void *ast_get_scu(void)
 
 	return priv->scu;
 }
+
+void ast_scu_unlock(struct ast2500_scu *scu)
+{
+	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (!readl(&scu->protection_key))
+		;
+}
+
+void ast_scu_lock(struct ast2500_scu *scu)
+{
+	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (readl(&scu->protection_key))
+		;
+}
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 26a5e58221..504731271c 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -132,20 +132,6 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static void ast2500_scu_unlock(struct ast2500_scu *scu)
-{
-	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (!readl(&scu->protection_key))
-		;
-}
-
-static void ast2500_scu_lock(struct ast2500_scu *scu)
-{
-	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (readl(&scu->protection_key))
-		;
-}
-
 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 {
 	ulong clkin = ast2500_get_clkin(scu);
@@ -197,9 +183,9 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	    | (best_num << SCU_MPLL_NUM_SHIFT)
 	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
 
-	ast2500_scu_unlock(scu);
+	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
-	ast2500_scu_lock(scu);
+	ast_scu_lock(scu);
 
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 05/15] aspeed: Reset Driver
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass
  Cc: openbmc, Maxim Sloyko, Masahiro Yamada, Tom Warren,
	Albert Aribaud, Stephen Warren

Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
perform resets and thus depends on it. The actual Watchdog device used
needs to be configured in Device Tree using "aspeed,wdt" property, which
must be WDT phandle, for example:

rst: reset-controller {
    compatible = "aspeed,ast2500-reset";
    aspeed,wdt = <&wdt1>;
}

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  28 +++++++
 drivers/reset/Kconfig                          |  10 +++
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++++++++++++++++++++++++
 4 files changed, 145 insertions(+)
 create mode 100644 drivers/reset/ast2500-reset.c

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 0fa3ecb9b9..e2556f920d 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -31,6 +31,34 @@
 
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
 
+/*
+ * SYSRESET is actually more like a Power register,
+ * except that corresponding bit set to 1 means that
+ * the peripheral is off.
+ */
+#define SCU_SYSRESET_XDMA		(1 << 25)
+#define SCU_SYSRESET_MCTP		(1 << 24)
+#define SCU_SYSRESET_ADC		(1 << 23)
+#define SCU_SYSRESET_JTAG		(1 << 22)
+#define SCU_SYSRESET_MIC		(1 << 18)
+#define SCU_SYSRESET_SDIO		(1 << 16)
+#define SCU_SYSRESET_USB11HOST		(1 << 15)
+#define SCU_SYSRESET_USBHUB		(1 << 14)
+#define SCU_SYSRESET_CRT		(1 << 13)
+#define SCU_SYSRESET_MAC2		(1 << 12)
+#define SCU_SYSRESET_MAC1		(1 << 11)
+#define SCU_SYSRESET_PECI		(1 << 10)
+#define SCU_SYSRESET_PWM		(1 << 9)
+#define SCU_SYSRESET_PCI_VGA		(1 << 8)
+#define SCU_SYSRESET_2D			(1 << 7)
+#define SCU_SYSRESET_VIDEO		(1 << 6)
+#define SCU_SYSRESET_LPC		(1 << 5)
+#define SCU_SYSRESET_HAC		(1 << 4)
+#define SCU_SYSRESET_USBHID		(1 << 3)
+#define SCU_SYSRESET_I2C		(1 << 2)
+#define SCU_SYSRESET_AHB		(1 << 1)
+#define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c42b0bcf0e..eb54189d4b 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -43,4 +43,14 @@ config RESET_UNIPHIER
 	  Say Y if you want to control reset signals provided by System Control
 	  block, Media I/O block, Peripheral Block.
 
+config AST2500_RESET
+	bool "Reset controller driver for AST2500 SoCs"
+	depends on DM_RESET && WDT_ASPEED
+	default y if ASPEED_AST2500
+	help
+	  Support for reset controller on AST2500 SoC. This controller uses
+	  watchdog to reset different peripherals and thus only supports
+	  resets that are supported by watchdog. The main limitation though
+	  is that some reset signals, like I2C or MISC reset multiple devices.
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 5c4305cc1d..16ad7eed5b 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
 obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
 obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
diff --git a/drivers/reset/ast2500-reset.c b/drivers/reset/ast2500-reset.c
new file mode 100644
index 0000000000..b2c89e1f1e
--- /dev/null
+++ b/drivers/reset/ast2500-reset.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <reset.h>
+#include <reset-uclass.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+#include <asm/arch/wdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast2500_reset_priv {
+	/* WDT used to perform resets. */
+	struct udevice *wdt;
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt",
+					   &priv->wdt);
+	if (ret) {
+		debug("%s: can't find WDT for reset controller", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast2500_reset_assert(struct reset_ctl *reset_ctl)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	u32 reset_mode, reset_mask;
+	bool reset_sdram;
+	int ret;
+
+	/*
+	 * To reset SDRAM, a specifal flag in SYSRESET register
+	 * needs to be enabled first
+	 */
+	reset_mode = ast_reset_mode_from_flags(reset_ctl->id);
+	reset_mask = ast_reset_mask_from_flags(reset_ctl->id);
+	reset_sdram = reset_mode == WDT_CTRL_RESET_SOC &&
+		(reset_mask & WDT_RESET_SDRAM);
+
+	if (reset_sdram) {
+		ast_scu_unlock(priv->scu);
+		setbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+		clrbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ast_scu_lock(priv->scu);
+	} else {
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+	}
+
+	return ret;
+}
+
+static int ast2500_reset_request(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int ast2500_reset_probe(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+static const struct udevice_id ast2500_reset_ids[] = {
+	{ .compatible = "aspeed,ast2500-reset" },
+	{ }
+};
+
+struct reset_ops ast2500_reset_ops = {
+	.rst_assert = ast2500_reset_assert,
+	.request = ast2500_reset_request,
+};
+
+U_BOOT_DRIVER(ast2500_reset) = {
+	.name		= "ast2500_reset",
+	.id		= UCLASS_RESET,
+	.of_match = ast2500_reset_ids,
+	.probe = ast2500_reset_probe,
+	.ops = &ast2500_reset_ops,
+	.ofdata_to_platdata = ast2500_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct ast2500_reset_priv),
+};
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 05/15] aspeed: Reset Driver
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
perform resets and thus depends on it. The actual Watchdog device used
needs to be configured in Device Tree using "aspeed,wdt" property, which
must be WDT phandle, for example:

rst: reset-controller {
    compatible = "aspeed,ast2500-reset";
    aspeed,wdt = <&wdt1>;
}

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  28 +++++++
 drivers/reset/Kconfig                          |  10 +++
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++++++++++++++++++++++++
 4 files changed, 145 insertions(+)
 create mode 100644 drivers/reset/ast2500-reset.c

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 0fa3ecb9b9..e2556f920d 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -31,6 +31,34 @@
 
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
 
+/*
+ * SYSRESET is actually more like a Power register,
+ * except that corresponding bit set to 1 means that
+ * the peripheral is off.
+ */
+#define SCU_SYSRESET_XDMA		(1 << 25)
+#define SCU_SYSRESET_MCTP		(1 << 24)
+#define SCU_SYSRESET_ADC		(1 << 23)
+#define SCU_SYSRESET_JTAG		(1 << 22)
+#define SCU_SYSRESET_MIC		(1 << 18)
+#define SCU_SYSRESET_SDIO		(1 << 16)
+#define SCU_SYSRESET_USB11HOST		(1 << 15)
+#define SCU_SYSRESET_USBHUB		(1 << 14)
+#define SCU_SYSRESET_CRT		(1 << 13)
+#define SCU_SYSRESET_MAC2		(1 << 12)
+#define SCU_SYSRESET_MAC1		(1 << 11)
+#define SCU_SYSRESET_PECI		(1 << 10)
+#define SCU_SYSRESET_PWM		(1 << 9)
+#define SCU_SYSRESET_PCI_VGA		(1 << 8)
+#define SCU_SYSRESET_2D			(1 << 7)
+#define SCU_SYSRESET_VIDEO		(1 << 6)
+#define SCU_SYSRESET_LPC		(1 << 5)
+#define SCU_SYSRESET_HAC		(1 << 4)
+#define SCU_SYSRESET_USBHID		(1 << 3)
+#define SCU_SYSRESET_I2C		(1 << 2)
+#define SCU_SYSRESET_AHB		(1 << 1)
+#define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c42b0bcf0e..eb54189d4b 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -43,4 +43,14 @@ config RESET_UNIPHIER
 	  Say Y if you want to control reset signals provided by System Control
 	  block, Media I/O block, Peripheral Block.
 
+config AST2500_RESET
+	bool "Reset controller driver for AST2500 SoCs"
+	depends on DM_RESET && WDT_ASPEED
+	default y if ASPEED_AST2500
+	help
+	  Support for reset controller on AST2500 SoC. This controller uses
+	  watchdog to reset different peripherals and thus only supports
+	  resets that are supported by watchdog. The main limitation though
+	  is that some reset signals, like I2C or MISC reset multiple devices.
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 5c4305cc1d..16ad7eed5b 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
 obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
 obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
diff --git a/drivers/reset/ast2500-reset.c b/drivers/reset/ast2500-reset.c
new file mode 100644
index 0000000000..b2c89e1f1e
--- /dev/null
+++ b/drivers/reset/ast2500-reset.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <reset.h>
+#include <reset-uclass.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+#include <asm/arch/wdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast2500_reset_priv {
+	/* WDT used to perform resets. */
+	struct udevice *wdt;
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt",
+					   &priv->wdt);
+	if (ret) {
+		debug("%s: can't find WDT for reset controller", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast2500_reset_assert(struct reset_ctl *reset_ctl)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	u32 reset_mode, reset_mask;
+	bool reset_sdram;
+	int ret;
+
+	/*
+	 * To reset SDRAM, a specifal flag in SYSRESET register
+	 * needs to be enabled first
+	 */
+	reset_mode = ast_reset_mode_from_flags(reset_ctl->id);
+	reset_mask = ast_reset_mask_from_flags(reset_ctl->id);
+	reset_sdram = reset_mode == WDT_CTRL_RESET_SOC &&
+		(reset_mask & WDT_RESET_SDRAM);
+
+	if (reset_sdram) {
+		ast_scu_unlock(priv->scu);
+		setbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+		clrbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ast_scu_lock(priv->scu);
+	} else {
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+	}
+
+	return ret;
+}
+
+static int ast2500_reset_request(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int ast2500_reset_probe(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+static const struct udevice_id ast2500_reset_ids[] = {
+	{ .compatible = "aspeed,ast2500-reset" },
+	{ }
+};
+
+struct reset_ops ast2500_reset_ops = {
+	.rst_assert = ast2500_reset_assert,
+	.request = ast2500_reset_request,
+};
+
+U_BOOT_DRIVER(ast2500_reset) = {
+	.name		= "ast2500_reset",
+	.id		= UCLASS_RESET,
+	.of_match = ast2500_reset_ids,
+	.probe = ast2500_reset_probe,
+	.ops = &ast2500_reset_ops,
+	.ofdata_to_platdata = ast2500_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct ast2500_reset_priv),
+};
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 06/15] aspeed: Device Tree configuration for Reset Driver
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
for various reset signals

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/dts/ast2500-evb.dts              | 15 +++++++++++
 arch/arm/dts/ast2500-u-boot.dtsi          | 10 +++++++
 include/dt-bindings/reset/ast2500-reset.h | 45 +++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+)
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h

diff --git a/arch/arm/dts/ast2500-evb.dts b/arch/arm/dts/ast2500-evb.dts
index dc13952fb8..723941ac0b 100644
--- a/arch/arm/dts/ast2500-evb.dts
+++ b/arch/arm/dts/ast2500-evb.dts
@@ -21,3 +21,18 @@
 &sdrammc {
 	clock-frequency = <400000000>;
 };
+
+&wdt1 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt2 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt3 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index c95a7ba835..faeeec1be4 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -1,4 +1,5 @@
 #include <dt-bindings/clock/ast2500-scu.h>
+#include <dt-bindings/reset/ast2500-reset.h>
 
 #include "ast2500.dtsi"
 
@@ -11,12 +12,21 @@
 		#reset-cells = <1>;
 	};
 
+	rst: reset-controller {
+		u-boot,dm-pre-reloc;
+		compatible = "aspeed,ast2500-reset";
+		aspeed,wdt = <&wdt1>;
+		#reset-cells = <1>;
+	};
+
 	sdrammc: sdrammc@1e6e0000 {
 		u-boot,dm-pre-reloc;
 		compatible = "aspeed,ast2500-sdrammc";
 		reg = <0x1e6e0000 0x174
 			0x1e6e0200 0x1d4 >;
+		#reset-cells = <1>;
 		clocks = <&scu PLL_MPLL>;
+		resets = <&rst AST_RESET_SDRAM>;
 	};
 
 	ahb {
diff --git a/include/dt-bindings/reset/ast2500-reset.h b/include/dt-bindings/reset/ast2500-reset.h
new file mode 100644
index 0000000000..eb5e1db97b
--- /dev/null
+++ b/include/dt-bindings/reset/ast2500-reset.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ABI_MACH_ASPEED_AST2500_RESET_H_
+#define _ABI_MACH_ASPEED_AST2500_RESET_H_
+
+/*
+ * The values are intentionally layed out as flags in
+ * WDT reset parameter.
+ */
+
+#define AST_RESET_SOC			0
+#define AST_RESET_CHIP			1
+#define AST_RESET_CPU			(1 << 1)
+#define AST_RESET_ARM			(1 << 2)
+#define AST_RESET_COPROC		(1 << 3)
+#define AST_RESET_SDRAM			(1 << 4)
+#define AST_RESET_AHB			(1 << 5)
+#define AST_RESET_I2C			(1 << 6)
+#define AST_RESET_MAC1			(1 << 7)
+#define AST_RESET_MAC2			(1 << 8)
+#define AST_RESET_GCRT			(1 << 9)
+#define AST_RESET_USB20			(1 << 10)
+#define AST_RESET_USB11_HOST		(1 << 11)
+#define AST_RESET_USB11_HID		(1 << 12)
+#define AST_RESET_VIDEO			(1 << 13)
+#define AST_RESET_HAC			(1 << 14)
+#define AST_RESET_LPC			(1 << 15)
+#define AST_RESET_SDIO			(1 << 16)
+#define AST_RESET_MIC			(1 << 17)
+#define AST_RESET_CRT2D			(1 << 18)
+#define AST_RESET_PWM			(1 << 19)
+#define AST_RESET_PECI			(1 << 20)
+#define AST_RESET_JTAG			(1 << 21)
+#define AST_RESET_ADC			(1 << 22)
+#define AST_RESET_GPIO			(1 << 23)
+#define AST_RESET_MCTP			(1 << 24)
+#define AST_RESET_XDMA			(1 << 25)
+#define AST_RESET_SPI			(1 << 26)
+#define AST_RESET_MISC			(1 << 27)
+
+#endif  /* _ABI_MACH_ASPEED_AST2500_RESET_H_ */
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 06/15] aspeed: Device Tree configuration for Reset Driver
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
for various reset signals

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/dts/ast2500-evb.dts              | 15 +++++++++++
 arch/arm/dts/ast2500-u-boot.dtsi          | 10 +++++++
 include/dt-bindings/reset/ast2500-reset.h | 45 +++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+)
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h

diff --git a/arch/arm/dts/ast2500-evb.dts b/arch/arm/dts/ast2500-evb.dts
index dc13952fb8..723941ac0b 100644
--- a/arch/arm/dts/ast2500-evb.dts
+++ b/arch/arm/dts/ast2500-evb.dts
@@ -21,3 +21,18 @@
 &sdrammc {
 	clock-frequency = <400000000>;
 };
+
+&wdt1 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt2 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt3 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index c95a7ba835..faeeec1be4 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -1,4 +1,5 @@
 #include <dt-bindings/clock/ast2500-scu.h>
+#include <dt-bindings/reset/ast2500-reset.h>
 
 #include "ast2500.dtsi"
 
@@ -11,12 +12,21 @@
 		#reset-cells = <1>;
 	};
 
+	rst: reset-controller {
+		u-boot,dm-pre-reloc;
+		compatible = "aspeed,ast2500-reset";
+		aspeed,wdt = <&wdt1>;
+		#reset-cells = <1>;
+	};
+
 	sdrammc: sdrammc at 1e6e0000 {
 		u-boot,dm-pre-reloc;
 		compatible = "aspeed,ast2500-sdrammc";
 		reg = <0x1e6e0000 0x174
 			0x1e6e0200 0x1d4 >;
+		#reset-cells = <1>;
 		clocks = <&scu PLL_MPLL>;
+		resets = <&rst AST_RESET_SDRAM>;
 	};
 
 	ahb {
diff --git a/include/dt-bindings/reset/ast2500-reset.h b/include/dt-bindings/reset/ast2500-reset.h
new file mode 100644
index 0000000000..eb5e1db97b
--- /dev/null
+++ b/include/dt-bindings/reset/ast2500-reset.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ABI_MACH_ASPEED_AST2500_RESET_H_
+#define _ABI_MACH_ASPEED_AST2500_RESET_H_
+
+/*
+ * The values are intentionally layed out as flags in
+ * WDT reset parameter.
+ */
+
+#define AST_RESET_SOC			0
+#define AST_RESET_CHIP			1
+#define AST_RESET_CPU			(1 << 1)
+#define AST_RESET_ARM			(1 << 2)
+#define AST_RESET_COPROC		(1 << 3)
+#define AST_RESET_SDRAM			(1 << 4)
+#define AST_RESET_AHB			(1 << 5)
+#define AST_RESET_I2C			(1 << 6)
+#define AST_RESET_MAC1			(1 << 7)
+#define AST_RESET_MAC2			(1 << 8)
+#define AST_RESET_GCRT			(1 << 9)
+#define AST_RESET_USB20			(1 << 10)
+#define AST_RESET_USB11_HOST		(1 << 11)
+#define AST_RESET_USB11_HID		(1 << 12)
+#define AST_RESET_VIDEO			(1 << 13)
+#define AST_RESET_HAC			(1 << 14)
+#define AST_RESET_LPC			(1 << 15)
+#define AST_RESET_SDIO			(1 << 16)
+#define AST_RESET_MIC			(1 << 17)
+#define AST_RESET_CRT2D			(1 << 18)
+#define AST_RESET_PWM			(1 << 19)
+#define AST_RESET_PECI			(1 << 20)
+#define AST_RESET_JTAG			(1 << 21)
+#define AST_RESET_ADC			(1 << 22)
+#define AST_RESET_GPIO			(1 << 23)
+#define AST_RESET_MCTP			(1 << 24)
+#define AST_RESET_XDMA			(1 << 25)
+#define AST_RESET_SPI			(1 << 26)
+#define AST_RESET_MISC			(1 << 27)
+
+#endif  /* _ABI_MACH_ASPEED_AST2500_RESET_H_ */
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

This change switches all existing users of ast2500 Watchdog to Driver
Model based Watchdog driver.

To perform system reset Sysreset Driver uses first Watchdog device found
via uclass_first_device call. Since the system is going to be reset
anyway it does not make much difference which watchdog is used.

Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
driver to do that.

These were the only users of the old Watchdog API, so that API is
removed.

This all is done in one change to avoid having to maintain dual API for
watchdog in between.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/wdt.h       | 39 ---------------------
 arch/arm/mach-aspeed/Kconfig                 |  8 +----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c | 12 +++++--
 arch/arm/mach-aspeed/ast_wdt.c               | 51 ----------------------------
 configs/evb-ast2500_defconfig                |  2 ++
 drivers/sysreset/sysreset_ast.c              | 24 ++++++-------
 6 files changed, 24 insertions(+), 112 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index 981fa05a56..db8ecbcbe4 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -100,45 +100,6 @@ u32 ast_reset_mask_from_flags(ulong flags);
  * @reset_mask: Reset Mask
  */
 ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
-
-#ifndef CONFIG_WDT
-/**
- * Stop WDT
- *
- * @wdt: watchdog to stop
- *
- * When using driver model this function has different signature
- */
-void wdt_stop(struct ast_wdt *wdt);
-
-/**
- * Stop WDT
- *
- * @wdt: watchdog to start
- * @timeout	watchdog timeout in number of clock ticks
- *
- * When using driver model this function has different signature
- */
-void wdt_start(struct ast_wdt *wdt, u32 timeout);
-#endif  /* CONFIG_WDT */
-
-/**
- * Reset peripherals specified by mask
- *
- * Note, that this is only supported by ast2500 SoC
- *
- * @wdt: watchdog to use for this reset
- * @mask: reset mask.
- */
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask);
-
-/**
- * ast_get_wdt() - get a pointer to watchdog registers
- *
- * @wdt_number: 0-based WDT peripheral number
- * @return pointer to registers or -ve error on error
- */
-struct ast_wdt *ast_get_wdt(u8 wdt_number);
 #endif  /* __ASSEMBLY__ */
 
 #endif /* _ASM_ARCH_WDT_H */
diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig
index c5b90bd96a..4f021baa06 100644
--- a/arch/arm/mach-aspeed/Kconfig
+++ b/arch/arm/mach-aspeed/Kconfig
@@ -11,19 +11,13 @@ config SYS_TEXT_BASE
 
 config ASPEED_AST2500
 	bool "Support Aspeed AST2500 SoC"
+	depends on DM_RESET
 	select CPU_ARM1176
 	help
 	  The Aspeed AST2500 is a ARM-based SoC with arm1176 CPU.
 	  It is used as Board Management Controller on many server boards,
 	  which is enabled by support of LPC and eSPI peripherals.
 
-config WDT_NUM
-	int "Number of Watchdog Timers"
-	default 3 if ASPEED_AST2500
-	help
-	  The number of Watchdot Timers on a SoC.
-	  AST2500 has three WDTsk earlier versions have two or fewer.
-
 source "arch/arm/mach-aspeed/ast2500/Kconfig"
 
 endif
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index cb6e03fa34..efcf452b17 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <ram.h>
 #include <regmap.h>
+#include <reset.h>
 #include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 #include <asm/arch/sdram_ast2500.h>
@@ -328,6 +329,7 @@ static void ast2500_sdrammc_lock(struct dram_info *info)
 
 static int ast2500_sdrammc_probe(struct udevice *dev)
 {
+	struct reset_ctl reset_ctl;
 	struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
 	struct ast2500_sdrammc_regs *regs = priv->regs;
 	int i;
@@ -345,9 +347,15 @@ static int ast2500_sdrammc_probe(struct udevice *dev)
 	}
 
 	clk_set_rate(&priv->ddr_clk, priv->clock_rate);
-	ret = ast_wdt_reset_masked(ast_get_wdt(0), WDT_RESET_SDRAM);
+	ret = reset_get_by_index(dev, 0, &reset_ctl);
 	if (ret) {
-		debug("%s(): SDRAM reset failed\n", __func__);
+		debug("%s(): Failed to get reset signal\n", __func__);
+		return ret;
+	}
+
+	ret = reset_assert(&reset_ctl);
+	if (ret) {
+		debug("%s(): SDRAM reset failed: %u\n", __func__, ret);
 		return ret;
 	}
 
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 895fba3366..1a858b1020 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -28,54 +28,3 @@ ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
 
 	return ret;
 }
-
-#ifndef CONFIG_WDT
-void wdt_stop(struct ast_wdt *wdt)
-{
-	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
-}
-
-void wdt_start(struct ast_wdt *wdt, u32 timeout)
-{
-	writel(timeout, &wdt->counter_reload_val);
-	writel(WDT_COUNTER_RESTART_VAL, &wdt->counter_restart);
-	/*
-	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
-	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
-	 * read-only
-	 */
-	setbits_le32(&wdt->ctrl,
-		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
-}
-#endif  /* CONFIG_WDT */
-
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
-{
-#ifdef CONFIG_ASPEED_AST2500
-	if (!mask)
-		return -EINVAL;
-
-	writel(mask, &wdt->reset_mask);
-	clrbits_le32(&wdt->ctrl,
-		     WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT);
-	wdt_start(wdt, 1);
-
-	/* Wait for WDT to reset */
-	while (readl(&wdt->ctrl) & WDT_CTRL_EN)
-		;
-	wdt_stop(wdt);
-
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index cc5fea9a81..74808a71ee 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -15,3 +15,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_TIMER=y
+CONFIG_WDT=y
+CONFIG_DM_RESET=y
diff --git a/drivers/sysreset/sysreset_ast.c b/drivers/sysreset/sysreset_ast.c
index a0ab12851d..3c3f552df8 100644
--- a/drivers/sysreset/sysreset_ast.c
+++ b/drivers/sysreset/sysreset_ast.c
@@ -8,21 +8,19 @@
 #include <dm.h>
 #include <errno.h>
 #include <sysreset.h>
+#include <wdt.h>
 #include <asm/io.h>
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
-/* Number of Watchdog Timer ticks before reset */
-#define AST_WDT_RESET_TIMEOUT	10
-#define AST_WDT_FOR_RESET	0
-
 static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
-	struct ast_wdt *wdt = ast_get_wdt(AST_WDT_FOR_RESET);
-	u32 reset_mode = 0;
+	struct udevice *wdt;
+	u32 reset_mode;
+	int ret = uclass_first_device(UCLASS_WDT, &wdt);
 
-	if (IS_ERR(wdt))
-		return PTR_ERR(wdt);
+	if (ret)
+		return ret;
 
 	switch (type) {
 	case SYSRESET_WARM:
@@ -35,11 +33,11 @@ static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 		return -EPROTONOSUPPORT;
 	}
 
-	/* Clear reset mode bits */
-	clrsetbits_le32(&wdt->ctrl,
-			(WDT_CTRL_RESET_MODE_MASK << WDT_CTRL_RESET_MODE_SHIFT),
-			(reset_mode << WDT_CTRL_RESET_MODE_SHIFT));
-	wdt_start(wdt, AST_WDT_RESET_TIMEOUT);
+	ret = wdt_expire_now(wdt, reset_mode);
+	if (ret) {
+		debug("Sysreset failed: %d", ret);
+		return ret;
+	}
 
 	return -EINPROGRESS;
 }
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

This change switches all existing users of ast2500 Watchdog to Driver
Model based Watchdog driver.

To perform system reset Sysreset Driver uses first Watchdog device found
via uclass_first_device call. Since the system is going to be reset
anyway it does not make much difference which watchdog is used.

Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
driver to do that.

These were the only users of the old Watchdog API, so that API is
removed.

This all is done in one change to avoid having to maintain dual API for
watchdog in between.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/wdt.h       | 39 ---------------------
 arch/arm/mach-aspeed/Kconfig                 |  8 +----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c | 12 +++++--
 arch/arm/mach-aspeed/ast_wdt.c               | 51 ----------------------------
 configs/evb-ast2500_defconfig                |  2 ++
 drivers/sysreset/sysreset_ast.c              | 24 ++++++-------
 6 files changed, 24 insertions(+), 112 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index 981fa05a56..db8ecbcbe4 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -100,45 +100,6 @@ u32 ast_reset_mask_from_flags(ulong flags);
  * @reset_mask: Reset Mask
  */
 ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
-
-#ifndef CONFIG_WDT
-/**
- * Stop WDT
- *
- * @wdt: watchdog to stop
- *
- * When using driver model this function has different signature
- */
-void wdt_stop(struct ast_wdt *wdt);
-
-/**
- * Stop WDT
- *
- * @wdt: watchdog to start
- * @timeout	watchdog timeout in number of clock ticks
- *
- * When using driver model this function has different signature
- */
-void wdt_start(struct ast_wdt *wdt, u32 timeout);
-#endif  /* CONFIG_WDT */
-
-/**
- * Reset peripherals specified by mask
- *
- * Note, that this is only supported by ast2500 SoC
- *
- * @wdt: watchdog to use for this reset
- * @mask: reset mask.
- */
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask);
-
-/**
- * ast_get_wdt() - get a pointer to watchdog registers
- *
- * @wdt_number: 0-based WDT peripheral number
- * @return pointer to registers or -ve error on error
- */
-struct ast_wdt *ast_get_wdt(u8 wdt_number);
 #endif  /* __ASSEMBLY__ */
 
 #endif /* _ASM_ARCH_WDT_H */
diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig
index c5b90bd96a..4f021baa06 100644
--- a/arch/arm/mach-aspeed/Kconfig
+++ b/arch/arm/mach-aspeed/Kconfig
@@ -11,19 +11,13 @@ config SYS_TEXT_BASE
 
 config ASPEED_AST2500
 	bool "Support Aspeed AST2500 SoC"
+	depends on DM_RESET
 	select CPU_ARM1176
 	help
 	  The Aspeed AST2500 is a ARM-based SoC with arm1176 CPU.
 	  It is used as Board Management Controller on many server boards,
 	  which is enabled by support of LPC and eSPI peripherals.
 
-config WDT_NUM
-	int "Number of Watchdog Timers"
-	default 3 if ASPEED_AST2500
-	help
-	  The number of Watchdot Timers on a SoC.
-	  AST2500 has three WDTsk earlier versions have two or fewer.
-
 source "arch/arm/mach-aspeed/ast2500/Kconfig"
 
 endif
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index cb6e03fa34..efcf452b17 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <ram.h>
 #include <regmap.h>
+#include <reset.h>
 #include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 #include <asm/arch/sdram_ast2500.h>
@@ -328,6 +329,7 @@ static void ast2500_sdrammc_lock(struct dram_info *info)
 
 static int ast2500_sdrammc_probe(struct udevice *dev)
 {
+	struct reset_ctl reset_ctl;
 	struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
 	struct ast2500_sdrammc_regs *regs = priv->regs;
 	int i;
@@ -345,9 +347,15 @@ static int ast2500_sdrammc_probe(struct udevice *dev)
 	}
 
 	clk_set_rate(&priv->ddr_clk, priv->clock_rate);
-	ret = ast_wdt_reset_masked(ast_get_wdt(0), WDT_RESET_SDRAM);
+	ret = reset_get_by_index(dev, 0, &reset_ctl);
 	if (ret) {
-		debug("%s(): SDRAM reset failed\n", __func__);
+		debug("%s(): Failed to get reset signal\n", __func__);
+		return ret;
+	}
+
+	ret = reset_assert(&reset_ctl);
+	if (ret) {
+		debug("%s(): SDRAM reset failed: %u\n", __func__, ret);
 		return ret;
 	}
 
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 895fba3366..1a858b1020 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -28,54 +28,3 @@ ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
 
 	return ret;
 }
-
-#ifndef CONFIG_WDT
-void wdt_stop(struct ast_wdt *wdt)
-{
-	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
-}
-
-void wdt_start(struct ast_wdt *wdt, u32 timeout)
-{
-	writel(timeout, &wdt->counter_reload_val);
-	writel(WDT_COUNTER_RESTART_VAL, &wdt->counter_restart);
-	/*
-	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
-	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
-	 * read-only
-	 */
-	setbits_le32(&wdt->ctrl,
-		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
-}
-#endif  /* CONFIG_WDT */
-
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
-{
-#ifdef CONFIG_ASPEED_AST2500
-	if (!mask)
-		return -EINVAL;
-
-	writel(mask, &wdt->reset_mask);
-	clrbits_le32(&wdt->ctrl,
-		     WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT);
-	wdt_start(wdt, 1);
-
-	/* Wait for WDT to reset */
-	while (readl(&wdt->ctrl) & WDT_CTRL_EN)
-		;
-	wdt_stop(wdt);
-
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index cc5fea9a81..74808a71ee 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -15,3 +15,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_TIMER=y
+CONFIG_WDT=y
+CONFIG_DM_RESET=y
diff --git a/drivers/sysreset/sysreset_ast.c b/drivers/sysreset/sysreset_ast.c
index a0ab12851d..3c3f552df8 100644
--- a/drivers/sysreset/sysreset_ast.c
+++ b/drivers/sysreset/sysreset_ast.c
@@ -8,21 +8,19 @@
 #include <dm.h>
 #include <errno.h>
 #include <sysreset.h>
+#include <wdt.h>
 #include <asm/io.h>
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
-/* Number of Watchdog Timer ticks before reset */
-#define AST_WDT_RESET_TIMEOUT	10
-#define AST_WDT_FOR_RESET	0
-
 static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
-	struct ast_wdt *wdt = ast_get_wdt(AST_WDT_FOR_RESET);
-	u32 reset_mode = 0;
+	struct udevice *wdt;
+	u32 reset_mode;
+	int ret = uclass_first_device(UCLASS_WDT, &wdt);
 
-	if (IS_ERR(wdt))
-		return PTR_ERR(wdt);
+	if (ret)
+		return ret;
 
 	switch (type) {
 	case SYSRESET_WARM:
@@ -35,11 +33,11 @@ static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 		return -EPROTONOSUPPORT;
 	}
 
-	/* Clear reset mode bits */
-	clrsetbits_le32(&wdt->ctrl,
-			(WDT_CTRL_RESET_MODE_MASK << WDT_CTRL_RESET_MODE_SHIFT),
-			(reset_mode << WDT_CTRL_RESET_MODE_SHIFT));
-	wdt_start(wdt, AST_WDT_RESET_TIMEOUT);
+	ret = wdt_expire_now(wdt, reset_mode);
+	if (ret) {
+		debug("Sysreset failed: %d", ret);
+		return ret;
+	}
 
 	return -EINPROGRESS;
 }
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 08/15] aspeed: AST2500 Pinctrl Driver
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass
  Cc: openbmc, Maxim Sloyko, Konstantin Porotchkin, Thomas Abraham,
	Wills Wang, Kever Yang, Albert Aribaud, Beniamino Galvani,
	Heiko Stübner, Minkyu Kang, Daniel Schwierzeck, Wenyou Yang

This driver uses Generic Pinctrl framework and is compatible with
the Linux driver for ast2500: it uses the same device tree
configuration.

Not all pins are supported by the driver at the moment, so it actually
compatible with ast2400. In general, however, there are differences that
in the future would be easier to maintain separately.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++++++++++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  19 ++++
 drivers/pinctrl/Kconfig                        |   9 ++
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 +++++++++++++++++++++++++
 6 files changed, 209 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c

diff --git a/arch/arm/include/asm/arch-aspeed/pinctrl.h b/arch/arm/include/asm/arch-aspeed/pinctrl.h
new file mode 100644
index 0000000000..365dc21dbc
--- /dev/null
+++ b/arch/arm/include/asm/arch-aspeed/pinctrl.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _ASM_ARCH_PERIPH_H
+#define _ASM_ARCH_PERIPH_H
+
+/*
+ * Peripherals supported by the hardware.
+ * These are used to specify pinctrl settings.
+ */
+
+enum periph_id {
+	PERIPH_ID_UART1,
+	PERIPH_ID_UART2,
+	PERIPH_ID_UART3,
+	PERIPH_ID_UART4,
+	PERIPH_ID_LPC,
+	PERIPH_ID_PWM0,
+	PERIPH_ID_PWM1,
+	PERIPH_ID_PWM2,
+	PERIPH_ID_PWM3,
+	PERIPH_ID_PWM4,
+	PERIPH_ID_PWM5,
+	PERIPH_ID_PWM6,
+	PERIPH_ID_PWM7,
+	PERIPH_ID_PWM8,
+	PERIPH_ID_MAC1,
+	PERIPH_ID_MAC2,
+	PERIPH_ID_VIDEO,
+	PERIPH_ID_SPI1,
+	PERIPH_ID_SPI2,
+	PERIPH_ID_I2C1,
+	PERIPH_ID_I2C2,
+	PERIPH_ID_I2C3,
+	PERIPH_ID_I2C4,
+	PERIPH_ID_I2C5,
+	PERIPH_ID_I2C6,
+	PERIPH_ID_I2C7,
+	PERIPH_ID_I2C8,
+	PERIPH_ID_I2C9,
+	PERIPH_ID_I2C10,
+	PERIPH_ID_I2C11,
+	PERIPH_ID_I2C12,
+	PERIPH_ID_I2C13,
+	PERIPH_ID_I2C14,
+	PERIPH_ID_SD1,
+	PERIPH_ID_SD2,
+};
+
+#endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index e2556f920d..1cdd3b9198 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -10,6 +10,8 @@
 
 #define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
+#define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
 #define SCU_HWSTRAP_CLKIN_25MHZ		(1 << 23)
 
@@ -59,6 +61,23 @@
 #define SCU_SYSRESET_AHB		(1 << 1)
 #define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
 
+/* Bits 16-27 in the register control pin functions for I2C devices 3-14 */
+#define SCU_PINMUX_CTRL5_I2C		(1 << 16)
+
+/*
+ * The values are grouped by function, not by register.
+ * They are actually scattered across multiple loosely related registers.
+ */
+#define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
+#define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
+#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
+#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_SCL1		(1 << 12)
+#define SCU_PIN_FUN_SCL2		(1 << 14)
+#define SCU_PIN_FUN_SDA1		(1 << 13)
+#define SCU_PIN_FUN_SDA2		(1 << 15)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index efcb4c0003..3b7dd5f0c5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -175,6 +175,15 @@ config PIC32_PINCTRL
 	  by a device tree node which contains both GPIO defintion and pin control
 	  functions.
 
+config ASPEED_AST2500_PINCTRL
+  bool "Aspeed AST2500 pin control driver"
+  depends on DM && PINCTRL_GENERIC && ASPEED_AST2500
+  default y
+  help
+    Support pin multiplexing control on Aspeed ast2500 SoC. The driver uses
+	Generic Pinctrl framework and is compatible with the Linux driver,
+	i.e. it uses the same device tree configuration.
+
 endif
 
 source "drivers/pinctrl/meson/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 512112af64..5392c3ed45 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
 obj-$(CONFIG_PINCTRL_MVEBU)	+= mvebu/
+obj-$(CONFIG_ARCH_ASPEED) += aspeed/
diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
new file mode 100644
index 0000000000..2e6ed604c8
--- /dev/null
+++ b/drivers/pinctrl/aspeed/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ASPEED_AST2500_PINCTRL) += pinctrl_ast2500.o
diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2500.c b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
new file mode 100644
index 0000000000..01f97c1b48
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/pinctrl.h>
+#include <asm/arch/scu_ast2500.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This driver works with very simple configuration that has the same name
+ * for group and function. This way it is compatible with the Linux Kernel
+ * driver.
+ */
+
+struct ast2500_pinctrl_priv {
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_pinctrl_probe(struct udevice *dev)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+struct ast2500_group_config {
+	char *group_name;
+	/* Control register number (1-10) */
+	unsigned reg_num;
+	/* The mask of control bits in the register */
+	u32 ctrl_bit_mask;
+};
+
+static const struct ast2500_group_config ast2500_groups[] = {
+	{ "I2C1", 8, (1 << 13) | (1 << 12) },
+	{ "I2C2", 8, (1 << 15) | (1 << 14) },
+	{ "I2C3", 8, (1 << 16) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C5", 5, (1 << 18) },
+	{ "I2C6", 5, (1 << 19) },
+	{ "I2C7", 5, (1 << 20) },
+	{ "I2C8", 5, (1 << 21) },
+	{ "I2C9", 5, (1 << 22) },
+	{ "I2C10", 5, (1 << 23) },
+	{ "I2C11", 5, (1 << 24) },
+	{ "I2C12", 5, (1 << 25) },
+	{ "I2C13", 5, (1 << 26) },
+	{ "I2C14", 5, (1 << 27) },
+	{ "MAC1LINK", 1, (1 << 0) },
+	{ "MDIO1", 3, (1 << 31) | (1 << 30) },
+	{ "MAC2LINK", 1, (1 << 1) },
+	{ "MDIO2", 5, (1 << 2) },
+};
+
+static int ast2500_pinctrl_get_groups_count(struct udevice *dev)
+{
+	debug("PINCTRL: get_(functions/groups)_count\n");
+
+	return ARRAY_SIZE(ast2500_groups);
+}
+
+static const char *ast2500_pinctrl_get_group_name(struct udevice *dev,
+						  unsigned selector)
+{
+	debug("PINCTRL: get_(function/group)_name %u\n", selector);
+
+	return ast2500_groups[selector].group_name;
+}
+
+static int ast2500_pinctrl_group_set(struct udevice *dev, unsigned selector,
+				     unsigned func_selector)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct ast2500_group_config *config;
+	u32 *ctrl_reg;
+
+	debug("PINCTRL: group_set <%u, %u>\n", selector, func_selector);
+	if (selector >= ARRAY_SIZE(ast2500_groups))
+		return -EINVAL;
+
+	config = &ast2500_groups[selector];
+	if (config->reg_num > 6)
+		ctrl_reg = &priv->scu->pinmux_ctrl1[config->reg_num - 7];
+	else
+		ctrl_reg = &priv->scu->pinmux_ctrl[config->reg_num - 1];
+
+	ast_scu_unlock(priv->scu);
+	setbits_le32(ctrl_reg, config->ctrl_bit_mask);
+	ast_scu_lock(priv->scu);
+
+	return 0;
+}
+
+static struct pinctrl_ops ast2500_pinctrl_ops = {
+	.set_state = pinctrl_generic_set_state,
+	.get_groups_count = ast2500_pinctrl_get_groups_count,
+	.get_group_name = ast2500_pinctrl_get_group_name,
+	.get_functions_count = ast2500_pinctrl_get_groups_count,
+	.get_function_name = ast2500_pinctrl_get_group_name,
+	.pinmux_group_set = ast2500_pinctrl_group_set,
+};
+
+static const struct udevice_id ast2500_pinctrl_ids[] = {
+	{ .compatible = "aspeed,ast2500-pinctrl" },
+	{ .compatible = "aspeed,g5-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_ast2500) = {
+	.name = "aspeed_ast2500_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = ast2500_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct ast2500_pinctrl_priv),
+	.ops = &ast2500_pinctrl_ops,
+	.probe = ast2500_pinctrl_probe,
+};
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 08/15] aspeed: AST2500 Pinctrl Driver
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

This driver uses Generic Pinctrl framework and is compatible with
the Linux driver for ast2500: it uses the same device tree
configuration.

Not all pins are supported by the driver at the moment, so it actually
compatible with ast2400. In general, however, there are differences that
in the future would be easier to maintain separately.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++++++++++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  19 ++++
 drivers/pinctrl/Kconfig                        |   9 ++
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 +++++++++++++++++++++++++
 6 files changed, 209 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c

diff --git a/arch/arm/include/asm/arch-aspeed/pinctrl.h b/arch/arm/include/asm/arch-aspeed/pinctrl.h
new file mode 100644
index 0000000000..365dc21dbc
--- /dev/null
+++ b/arch/arm/include/asm/arch-aspeed/pinctrl.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _ASM_ARCH_PERIPH_H
+#define _ASM_ARCH_PERIPH_H
+
+/*
+ * Peripherals supported by the hardware.
+ * These are used to specify pinctrl settings.
+ */
+
+enum periph_id {
+	PERIPH_ID_UART1,
+	PERIPH_ID_UART2,
+	PERIPH_ID_UART3,
+	PERIPH_ID_UART4,
+	PERIPH_ID_LPC,
+	PERIPH_ID_PWM0,
+	PERIPH_ID_PWM1,
+	PERIPH_ID_PWM2,
+	PERIPH_ID_PWM3,
+	PERIPH_ID_PWM4,
+	PERIPH_ID_PWM5,
+	PERIPH_ID_PWM6,
+	PERIPH_ID_PWM7,
+	PERIPH_ID_PWM8,
+	PERIPH_ID_MAC1,
+	PERIPH_ID_MAC2,
+	PERIPH_ID_VIDEO,
+	PERIPH_ID_SPI1,
+	PERIPH_ID_SPI2,
+	PERIPH_ID_I2C1,
+	PERIPH_ID_I2C2,
+	PERIPH_ID_I2C3,
+	PERIPH_ID_I2C4,
+	PERIPH_ID_I2C5,
+	PERIPH_ID_I2C6,
+	PERIPH_ID_I2C7,
+	PERIPH_ID_I2C8,
+	PERIPH_ID_I2C9,
+	PERIPH_ID_I2C10,
+	PERIPH_ID_I2C11,
+	PERIPH_ID_I2C12,
+	PERIPH_ID_I2C13,
+	PERIPH_ID_I2C14,
+	PERIPH_ID_SD1,
+	PERIPH_ID_SD2,
+};
+
+#endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index e2556f920d..1cdd3b9198 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -10,6 +10,8 @@
 
 #define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
+#define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
 #define SCU_HWSTRAP_CLKIN_25MHZ		(1 << 23)
 
@@ -59,6 +61,23 @@
 #define SCU_SYSRESET_AHB		(1 << 1)
 #define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
 
+/* Bits 16-27 in the register control pin functions for I2C devices 3-14 */
+#define SCU_PINMUX_CTRL5_I2C		(1 << 16)
+
+/*
+ * The values are grouped by function, not by register.
+ * They are actually scattered across multiple loosely related registers.
+ */
+#define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
+#define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
+#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
+#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_SCL1		(1 << 12)
+#define SCU_PIN_FUN_SCL2		(1 << 14)
+#define SCU_PIN_FUN_SDA1		(1 << 13)
+#define SCU_PIN_FUN_SDA2		(1 << 15)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index efcb4c0003..3b7dd5f0c5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -175,6 +175,15 @@ config PIC32_PINCTRL
 	  by a device tree node which contains both GPIO defintion and pin control
 	  functions.
 
+config ASPEED_AST2500_PINCTRL
+  bool "Aspeed AST2500 pin control driver"
+  depends on DM && PINCTRL_GENERIC && ASPEED_AST2500
+  default y
+  help
+    Support pin multiplexing control on Aspeed ast2500 SoC. The driver uses
+	Generic Pinctrl framework and is compatible with the Linux driver,
+	i.e. it uses the same device tree configuration.
+
 endif
 
 source "drivers/pinctrl/meson/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 512112af64..5392c3ed45 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
 obj-$(CONFIG_PINCTRL_MVEBU)	+= mvebu/
+obj-$(CONFIG_ARCH_ASPEED) += aspeed/
diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
new file mode 100644
index 0000000000..2e6ed604c8
--- /dev/null
+++ b/drivers/pinctrl/aspeed/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ASPEED_AST2500_PINCTRL) += pinctrl_ast2500.o
diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2500.c b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
new file mode 100644
index 0000000000..01f97c1b48
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/pinctrl.h>
+#include <asm/arch/scu_ast2500.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This driver works with very simple configuration that has the same name
+ * for group and function. This way it is compatible with the Linux Kernel
+ * driver.
+ */
+
+struct ast2500_pinctrl_priv {
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_pinctrl_probe(struct udevice *dev)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+struct ast2500_group_config {
+	char *group_name;
+	/* Control register number (1-10) */
+	unsigned reg_num;
+	/* The mask of control bits in the register */
+	u32 ctrl_bit_mask;
+};
+
+static const struct ast2500_group_config ast2500_groups[] = {
+	{ "I2C1", 8, (1 << 13) | (1 << 12) },
+	{ "I2C2", 8, (1 << 15) | (1 << 14) },
+	{ "I2C3", 8, (1 << 16) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C5", 5, (1 << 18) },
+	{ "I2C6", 5, (1 << 19) },
+	{ "I2C7", 5, (1 << 20) },
+	{ "I2C8", 5, (1 << 21) },
+	{ "I2C9", 5, (1 << 22) },
+	{ "I2C10", 5, (1 << 23) },
+	{ "I2C11", 5, (1 << 24) },
+	{ "I2C12", 5, (1 << 25) },
+	{ "I2C13", 5, (1 << 26) },
+	{ "I2C14", 5, (1 << 27) },
+	{ "MAC1LINK", 1, (1 << 0) },
+	{ "MDIO1", 3, (1 << 31) | (1 << 30) },
+	{ "MAC2LINK", 1, (1 << 1) },
+	{ "MDIO2", 5, (1 << 2) },
+};
+
+static int ast2500_pinctrl_get_groups_count(struct udevice *dev)
+{
+	debug("PINCTRL: get_(functions/groups)_count\n");
+
+	return ARRAY_SIZE(ast2500_groups);
+}
+
+static const char *ast2500_pinctrl_get_group_name(struct udevice *dev,
+						  unsigned selector)
+{
+	debug("PINCTRL: get_(function/group)_name %u\n", selector);
+
+	return ast2500_groups[selector].group_name;
+}
+
+static int ast2500_pinctrl_group_set(struct udevice *dev, unsigned selector,
+				     unsigned func_selector)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct ast2500_group_config *config;
+	u32 *ctrl_reg;
+
+	debug("PINCTRL: group_set <%u, %u>\n", selector, func_selector);
+	if (selector >= ARRAY_SIZE(ast2500_groups))
+		return -EINVAL;
+
+	config = &ast2500_groups[selector];
+	if (config->reg_num > 6)
+		ctrl_reg = &priv->scu->pinmux_ctrl1[config->reg_num - 7];
+	else
+		ctrl_reg = &priv->scu->pinmux_ctrl[config->reg_num - 1];
+
+	ast_scu_unlock(priv->scu);
+	setbits_le32(ctrl_reg, config->ctrl_bit_mask);
+	ast_scu_lock(priv->scu);
+
+	return 0;
+}
+
+static struct pinctrl_ops ast2500_pinctrl_ops = {
+	.set_state = pinctrl_generic_set_state,
+	.get_groups_count = ast2500_pinctrl_get_groups_count,
+	.get_group_name = ast2500_pinctrl_get_group_name,
+	.get_functions_count = ast2500_pinctrl_get_groups_count,
+	.get_function_name = ast2500_pinctrl_get_group_name,
+	.pinmux_group_set = ast2500_pinctrl_group_set,
+};
+
+static const struct udevice_id ast2500_pinctrl_ids[] = {
+	{ .compatible = "aspeed,ast2500-pinctrl" },
+	{ .compatible = "aspeed,g5-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_ast2500) = {
+	.name = "aspeed_ast2500_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = ast2500_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct ast2500_pinctrl_priv),
+	.ops = &ast2500_pinctrl_ops,
+	.probe = ast2500_pinctrl_probe,
+};
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko

Enable Pinctrl Driver in AST2500 Eval Board's defconfig

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 configs/evb-ast2500_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index 74808a71ee..f8ef9b779c 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -17,3 +17,4 @@ CONFIG_SYSRESET=y
 CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
+CONFIG_PINCTRL=y
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Enable Pinctrl Driver in AST2500 Eval Board's defconfig

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 configs/evb-ast2500_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index 74808a71ee..f8ef9b779c 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -17,3 +17,4 @@ CONFIG_SYSRESET=y
 CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
+CONFIG_PINCTRL=y
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Add P-Bus Clock support to ast2500 clock driver.
This is the clock used by I2C devices.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  3 ++-
 drivers/clk/aspeed/clk_ast2500.c               | 11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 1cdd3b9198..319d75e05c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -21,7 +21,8 @@
 #define SCU_MPLL_NUM_MASK		0xff
 #define SCU_MPLL_POST_SHIFT		13
 #define SCU_MPLL_POST_MASK		0x3f
-
+#define SCU_PCLK_DIV_SHIFT		23
+#define SCU_PCLK_DIV_MASK		7
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 504731271c..9e4c66ea85 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -110,6 +110,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 		rate = ast2500_get_mpll_rate(clkin,
 					     readl(&priv->scu->m_pll_param));
 		break;
+	case BCLK_PCLK:
+		{
+			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
+						  >> SCU_PCLK_DIV_SHIFT) &
+						 SCU_PCLK_DIV_MASK);
+			rate = ast2500_get_hpll_rate(clkin,
+						     readl(&priv->scu->
+							   h_pll_param));
+			rate = rate / apb_div;
+		}
+		break;
 	case PCLK_UART1:
 		rate = ast2500_get_uart_clk_rate(priv->scu, 1);
 		break;
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Add P-Bus Clock support to ast2500 clock driver.
This is the clock used by I2C devices.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  3 ++-
 drivers/clk/aspeed/clk_ast2500.c               | 11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 1cdd3b9198..319d75e05c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -21,7 +21,8 @@
 #define SCU_MPLL_NUM_MASK		0xff
 #define SCU_MPLL_POST_SHIFT		13
 #define SCU_MPLL_POST_MASK		0x3f
-
+#define SCU_PCLK_DIV_SHIFT		23
+#define SCU_PCLK_DIV_MASK		7
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 504731271c..9e4c66ea85 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -110,6 +110,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 		rate = ast2500_get_mpll_rate(clkin,
 					     readl(&priv->scu->m_pll_param));
 		break;
+	case BCLK_PCLK:
+		{
+			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
+						  >> SCU_PCLK_DIV_SHIFT) &
+						 SCU_PCLK_DIV_MASK);
+			rate = ast2500_get_hpll_rate(clkin,
+						     readl(&priv->scu->
+							   h_pll_param));
+			rate = rate / apb_div;
+		}
+		break;
 	case PCLK_UART1:
 		rate = ast2500_get_uart_clk_rate(priv->scu, 1);
 		break;
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 11/15] aspeed: Add I2C Driver
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Heiko Schocher

Add Device Model based I2C driver for ast2500/ast2400 SoCs.
The driver is very limited, it only supports master mode and
synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Style fixes


---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
 4 files changed, 499 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 39f62daf5d..e661a308b0 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 	  enable status register. This config option can be enabled in such
 	  cases.
 
+config SYS_I2C_ASPEED
+	bool "Aspeed I2C Controller"
+	depends on DM_I2C && ARCH_ASPEED
+	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
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 7c86198863..229fd476db 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -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_ASPEED) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
new file mode 100644
index 0000000000..16dfb57066
--- /dev/null
+++ b/drivers/i2c/ast_i2c.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 Google, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US 100000
+#define I2C_SLEEP_STEP_US 20
+
+#define HIGHSPEED_TTIMEOUT		3
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Device private data
+ */
+struct ast_i2c_priv {
+	/* This device's clock */
+	struct clk clk;
+	/* 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)
+			| (div << I2CD_BASE_DIV_SHIFT);
+
+	return data;
+}
+
+static void ast_i2c_clear_interrupts(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(~0, &priv->regs->isr);
+}
+
+static void ast_i2c_init_bus(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Reset device */
+	writel(0, &priv->regs->fcr);
+	/* Enable Master Mode. Assuming single-master */
+	writel(I2CD_MASTER_EN
+	       | I2CD_M_SDA_LOCK_EN
+	       | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
+	       &priv->regs->fcr);
+	/* Enable Interrupts */
+	writel(I2CD_INTR_TX_ACK
+	       | I2CD_INTR_TX_NAK
+	       | I2CD_INTR_RX_DONE
+	       | I2CD_INTR_BUS_RECOVER_DONE
+	       | I2CD_INTR_NORMAL_STOP
+	       | I2CD_INTR_ABNORMAL, &priv->regs->icr);
+}
+
+static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret < 0) {
+		debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
+		      ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast_i2c_probe(struct udevice *dev)
+{
+	struct ast2500_scu *scu;
+
+	debug("Enabling I2C%u\n", dev->seq);
+
+	/*
+	 * Get all I2C devices out of Reset.
+	 * Only needs to be done once, but doing it for every
+	 * device does not hurt.
+	 */
+	scu = ast_get_scu();
+	ast_scu_unlock(scu);
+	clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
+	ast_scu_lock(scu);
+
+	ast_i2c_init_bus(dev);
+
+	return 0;
+}
+
+static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+
+	while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
+		udelay(I2C_SLEEP_STEP_US);
+		timeout -= I2C_SLEEP_STEP_US;
+	}
+
+	ast_i2c_clear_interrupts(dev);
+	if (timeout <= 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int ast_i2c_send_stop(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(I2CD_M_STOP_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
+}
+
+static int ast_i2c_wait_tx(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+	u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
+	u32 status = readl(&priv->regs->isr) & flag;
+	int ret = 0;
+
+	while (!status && timeout > 0) {
+		status = readl(&priv->regs->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(dev);
+
+	return ret;
+}
+
+static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Start and Send Device Address */
+	writel(devaddr, &priv->regs->trbbr);
+	writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_tx(dev);
+}
+
+static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8 *buffer,
+			     size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	u32 i2c_cmd = I2CD_M_RX_CMD;
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		if (len == 1)
+			i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
+		writel(i2c_cmd, &priv->regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
+		if (ret < 0)
+			return ret;
+		*buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
+				>> I2CD_RX_DATA_SHIFT;
+	}
+	ast_i2c_clear_interrupts(dev);
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
+			      *buffer, size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1));
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		writel(*buffer, &priv->regs->trbbr);
+		writel(I2CD_M_TX_CMD, &priv->regs->csr);
+		ret = ast_i2c_wait_tx(dev);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	u32 csr = readl(&regs->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(dev);
+	} else if (scl_high) {
+		/* Possibly stuck slave */
+		debug("Bus stuck (%x), attempting recovery\n", csr);
+		writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
+	} else {
+		/* Just try to reinit the device. */
+		ast_i2c_init_bus(dev);
+	}
+
+	return ret;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+	int ret;
+
+	ret = ast_i2c_deblock(dev);
+	if (ret < 0)
+		return ret;
+
+	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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	ulong i2c_rate, divider;
+
+	debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
+	if (!speed) {
+		debug("No valid speed specified\n");
+		return -EINVAL;
+	}
+
+	i2c_rate = clk_get_rate(&priv->clk);
+	divider = i2c_rate / speed;
+
+	priv->speed = speed;
+	if (speed > I2C_HIGHSPEED_RATE) {
+		debug("Enable High Speed\n");
+		setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
+			     | I2CD_M_SDA_DRIVE_1T_EN
+			     | I2CD_SDA_DRIVE_1T_EN);
+		writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
+	} else {
+		debug("Enabling Normal Speed\n");
+		writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
+	}
+
+	writel(get_clk_reg_val(divider), &regs->cactcr1);
+	ast_i2c_clear_interrupts(dev);
+
+	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-bus" },
+	{ .compatible = "aspeed,ast2500-i2c-bus" },
+	{ },
+};
+
+U_BOOT_DRIVER(ast_i2c) = {
+	.name = "ast_i2c",
+	.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_priv),
+	.ops = &ast_i2c_ops,
+};
diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
new file mode 100644
index 0000000000..e5dec7a480
--- /dev/null
+++ b/drivers/i2c/ast_i2c.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 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_ASPEED_AST2500
+	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)
+
+#define I2C_HIGHSPEED_RATE    400000
+
+#endif				/* __AST_I2C_H_ */
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 11/15] aspeed: Add I2C Driver
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Add Device Model based I2C driver for ast2500/ast2400 SoCs.
The driver is very limited, it only supports master mode and
synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1:
- Style fixes


---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
 4 files changed, 499 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 39f62daf5d..e661a308b0 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 	  enable status register. This config option can be enabled in such
 	  cases.
 
+config SYS_I2C_ASPEED
+	bool "Aspeed I2C Controller"
+	depends on DM_I2C && ARCH_ASPEED
+	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
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 7c86198863..229fd476db 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -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_ASPEED) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
new file mode 100644
index 0000000000..16dfb57066
--- /dev/null
+++ b/drivers/i2c/ast_i2c.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 Google, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US 100000
+#define I2C_SLEEP_STEP_US 20
+
+#define HIGHSPEED_TTIMEOUT		3
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Device private data
+ */
+struct ast_i2c_priv {
+	/* This device's clock */
+	struct clk clk;
+	/* 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)
+			| (div << I2CD_BASE_DIV_SHIFT);
+
+	return data;
+}
+
+static void ast_i2c_clear_interrupts(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(~0, &priv->regs->isr);
+}
+
+static void ast_i2c_init_bus(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Reset device */
+	writel(0, &priv->regs->fcr);
+	/* Enable Master Mode. Assuming single-master */
+	writel(I2CD_MASTER_EN
+	       | I2CD_M_SDA_LOCK_EN
+	       | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
+	       &priv->regs->fcr);
+	/* Enable Interrupts */
+	writel(I2CD_INTR_TX_ACK
+	       | I2CD_INTR_TX_NAK
+	       | I2CD_INTR_RX_DONE
+	       | I2CD_INTR_BUS_RECOVER_DONE
+	       | I2CD_INTR_NORMAL_STOP
+	       | I2CD_INTR_ABNORMAL, &priv->regs->icr);
+}
+
+static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret < 0) {
+		debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
+		      ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast_i2c_probe(struct udevice *dev)
+{
+	struct ast2500_scu *scu;
+
+	debug("Enabling I2C%u\n", dev->seq);
+
+	/*
+	 * Get all I2C devices out of Reset.
+	 * Only needs to be done once, but doing it for every
+	 * device does not hurt.
+	 */
+	scu = ast_get_scu();
+	ast_scu_unlock(scu);
+	clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
+	ast_scu_lock(scu);
+
+	ast_i2c_init_bus(dev);
+
+	return 0;
+}
+
+static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+
+	while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
+		udelay(I2C_SLEEP_STEP_US);
+		timeout -= I2C_SLEEP_STEP_US;
+	}
+
+	ast_i2c_clear_interrupts(dev);
+	if (timeout <= 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int ast_i2c_send_stop(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(I2CD_M_STOP_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
+}
+
+static int ast_i2c_wait_tx(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+	u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
+	u32 status = readl(&priv->regs->isr) & flag;
+	int ret = 0;
+
+	while (!status && timeout > 0) {
+		status = readl(&priv->regs->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(dev);
+
+	return ret;
+}
+
+static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Start and Send Device Address */
+	writel(devaddr, &priv->regs->trbbr);
+	writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_tx(dev);
+}
+
+static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8 *buffer,
+			     size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	u32 i2c_cmd = I2CD_M_RX_CMD;
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		if (len == 1)
+			i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
+		writel(i2c_cmd, &priv->regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
+		if (ret < 0)
+			return ret;
+		*buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
+				>> I2CD_RX_DATA_SHIFT;
+	}
+	ast_i2c_clear_interrupts(dev);
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
+			      *buffer, size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1));
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		writel(*buffer, &priv->regs->trbbr);
+		writel(I2CD_M_TX_CMD, &priv->regs->csr);
+		ret = ast_i2c_wait_tx(dev);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	u32 csr = readl(&regs->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(dev);
+	} else if (scl_high) {
+		/* Possibly stuck slave */
+		debug("Bus stuck (%x), attempting recovery\n", csr);
+		writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
+	} else {
+		/* Just try to reinit the device. */
+		ast_i2c_init_bus(dev);
+	}
+
+	return ret;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+	int ret;
+
+	ret = ast_i2c_deblock(dev);
+	if (ret < 0)
+		return ret;
+
+	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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	ulong i2c_rate, divider;
+
+	debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
+	if (!speed) {
+		debug("No valid speed specified\n");
+		return -EINVAL;
+	}
+
+	i2c_rate = clk_get_rate(&priv->clk);
+	divider = i2c_rate / speed;
+
+	priv->speed = speed;
+	if (speed > I2C_HIGHSPEED_RATE) {
+		debug("Enable High Speed\n");
+		setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
+			     | I2CD_M_SDA_DRIVE_1T_EN
+			     | I2CD_SDA_DRIVE_1T_EN);
+		writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
+	} else {
+		debug("Enabling Normal Speed\n");
+		writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
+	}
+
+	writel(get_clk_reg_val(divider), &regs->cactcr1);
+	ast_i2c_clear_interrupts(dev);
+
+	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-bus" },
+	{ .compatible = "aspeed,ast2500-i2c-bus" },
+	{ },
+};
+
+U_BOOT_DRIVER(ast_i2c) = {
+	.name = "ast_i2c",
+	.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_priv),
+	.ops = &ast_i2c_ops,
+};
diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
new file mode 100644
index 0000000000..e5dec7a480
--- /dev/null
+++ b/drivers/i2c/ast_i2c.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 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_ASPEED_AST2500
+	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)
+
+#define I2C_HIGHSPEED_RATE    400000
+
+#endif				/* __AST_I2C_H_ */
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 12/15] aspeed: Enable I2C in EVB defconfig
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko

Enable I2C driver in ast2500 Eval Board defconfig.
Also enable i2c command.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 configs/evb-ast2500_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index f8ef9b779c..08b5f85a34 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -18,3 +18,6 @@ CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
 CONFIG_PINCTRL=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_ASPEED=y
+CONFIG_CMD_I2C=y
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 12/15] aspeed: Enable I2C in EVB defconfig
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Enable I2C driver in ast2500 Eval Board defconfig.
Also enable i2c command.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 configs/evb-ast2500_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index f8ef9b779c..08b5f85a34 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -18,3 +18,6 @@ CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
 CONFIG_PINCTRL=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_ASPEED=y
+CONFIG_CMD_I2C=y
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 13/15] aspeed: Add support for Clocks needed by MACs
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Add support for clocks needed by MACs to ast2500 clock driver.
The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
PCLK_MAC2 for MAC1 and MAC2 respectively.

The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
SDK. It is not entirely clear from the datasheet how this clock is used
by MACs, so not clear if the rate would ever need to be different. So,
for now, hardcoding it is probably safer.

The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
hardware strapping.

So, the network driver would only need to enable these clocks, no need
to configure the rate.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/dts/ast2500-u-boot.dtsi               |   8 +
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  62 +++++-
 drivers/clk/aspeed/clk_ast2500.c               | 265 ++++++++++++++++++++++---
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 4 files changed, 304 insertions(+), 33 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index faeeec1be4..f826646095 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -61,3 +61,11 @@
 		};
 	};
 };
+
+&mac0 {
+	clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;
+};
+
+&mac1 {
+	clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>;
+};
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 319d75e05c..fe877b5430 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -30,9 +30,36 @@
 #define SCU_HPLL_POST_SHIFT		13
 #define SCU_HPLL_POST_MASK		0x3f
 
+#define SCU_MACCLK_SHIFT		16
+#define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
+
+#define SCU_MISC2_RGMII_HPLL		(1 << 23)
+#define SCU_MISC2_RGMII_CLKDIV_SHIFT	20
+#define SCU_MISC2_RGMII_CLKDIV_MASK	(3 << SCU_MISC2_RGMII_CLKDIV_SHIFT)
+#define SCU_MISC2_RMII_MPLL		(1 << 19)
+#define SCU_MISC2_RMII_CLKDIV_SHIFT	16
+#define SCU_MISC2_RMII_CLKDIV_MASK	(3 << SCU_MISC2_RMII_CLKDIV_SHIFT)
 #define SCU_MISC2_UARTCLK_SHIFT		24
 
+#define SCU_MISC_D2PLL_OFF		(1 << 4)
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
+#define SCU_MISC_GCRT_USB20CLK		(1 << 21)
+
+#define SCU_MICDS_MAC1RGMII_TXDLY_SHIFT	0
+#define SCU_MICDS_MAC1RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC2RGMII_TXDLY_SHIFT	6
+#define SCU_MICDS_MAC2RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_RDLY_SHIFT	12
+#define SCU_MICDS_MAC1RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC2RMII_RDLY_SHIFT	18
+#define SCU_MICDS_MAC2RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_TXFALL	(1 << 24)
+#define SCU_MICDS_MAC2RMII_TXFALL	(1 << 25)
+#define SCU_MICDS_RMII1_RCLKEN		(1 << 29)
+#define SCU_MICDS_RMII2_RCLKEN		(1 << 30)
+#define SCU_MICDS_RGMIIPLL		(1 << 31)
 
 /*
  * SYSRESET is actually more like a Power register,
@@ -71,14 +98,45 @@
  */
 #define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
 #define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
-#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC1_PHY_LINK	(1 << 0)
 #define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
-#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_MAC2_PHY_LINK	(1 << 1)
 #define SCU_PIN_FUN_SCL1		(1 << 12)
 #define SCU_PIN_FUN_SCL2		(1 << 14)
 #define SCU_PIN_FUN_SDA1		(1 << 13)
 #define SCU_PIN_FUN_SDA2		(1 << 15)
 
+#define SCU_CLKSTOP_MAC1		(1 << 20)
+#define SCU_CLKSTOP_MAC2		(1 << 21)
+
+#define SCU_D2PLL_EXT1_OFF		(1 << 0)
+#define SCU_D2PLL_EXT1_BYPASS		(1 << 1)
+#define SCU_D2PLL_EXT1_RESET		(1 << 2)
+#define SCU_D2PLL_EXT1_MODE_SHIFT	3
+#define SCU_D2PLL_EXT1_MODE_MASK	(3 << SCU_D2PLL_EXT1_MODE_SHIFT)
+#define SCU_D2PLL_EXT1_PARAM_SHIFT	5
+#define SCU_D2PLL_EXT1_PARAM_MASK	(0x1ff << SCU_D2PLL_EXT1_PARAM_SHIFT)
+
+#define SCU_D2PLL_NUM_SHIFT		0
+#define SCU_D2PLL_NUM_MASK		(0xff << SCU_D2PLL_NUM_SHIFT)
+#define SCU_D2PLL_DENUM_SHIFT		8
+#define SCU_D2PLL_DENUM_MASK		(0x1f << SCU_D2PLL_DENUM_SHIFT)
+#define SCU_D2PLL_POST_SHIFT		13
+#define SCU_D2PLL_POST_MASK		(0x3f << SCU_D2PLL_POST_SHIFT)
+#define SCU_D2PLL_ODIV_SHIFT		19
+#define SCU_D2PLL_ODIV_MASK		(7 << SCU_D2PLL_ODIV_SHIFT)
+#define SCU_D2PLL_SIC_SHIFT		22
+#define SCU_D2PLL_SIC_MASK		(0x1f << SCU_D2PLL_SIC_SHIFT)
+#define SCU_D2PLL_SIP_SHIFT		27
+#define SCU_D2PLL_SIP_MASK		(0x1f << SCU_D2PLL_SIP_SHIFT)
+
+#define SCU_CLKDUTY_DCLK_SHIFT		0
+#define SCU_CLKDUTY_DCLK_MASK		(0x3f << SCU_CLKDUTY_DCLK_SHIFT)
+#define SCU_CLKDUTY_RGMII1TXCK_SHIFT	8
+#define SCU_CLKDUTY_RGMII1TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII1TXCK_SHIFT)
+#define SCU_CLKDUTY_RGMII2TXCK_SHIFT	16
+#define SCU_CLKDUTY_RGMII2TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 9e4c66ea85..7b4b5c64ac 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -12,16 +12,39 @@
 #include <dm/lists.h>
 #include <dt-bindings/clock/ast2500-scu.h>
 
+/*
+ * MAC Clock Delay settings, taken from Aspeed SDK
+ */
+#define RGMII_TXCLK_ODLY		8
+#define RMII_RXCLK_IDLY		2
+
+/*
+ * TGMII Clock Duty constants, taken from Aspeed SDK
+ */
+#define RGMII2_TXCK_DUTY	0x66
+#define RGMII1_TXCK_DUTY	0x64
+
+#define D2PLL_DEFAULT_RATE	(250 * 1000 * 1000)
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
+ * Clock divider/multiplier configuration struct.
  * For H-PLL and M-PLL the formula is
  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
  * M - Numerator
  * N - Denumerator
  * P - Post Divider
  * They have the same layout in their control register.
+ *
+ * D-PLL and D2-PLL have extra divider (OD + 1), which is not
+ * yet needed and ignored by clock configurations.
  */
+struct ast2500_div_config {
+	unsigned int num;
+	unsigned int denum;
+	unsigned int post_div;
+};
 
 /*
  * Get the rate of the M-PLL clock from input clock frequency and
@@ -143,30 +166,41 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+/*
+ * @input_rate - the rate of input clock in Hz
+ * @requested_rate - desired output rate in Hz
+ * @div - this is an IN/OUT parameter, at input all fields of the config
+ * need to be set to their maximum allowed values.
+ * The result (the best config we could find), would also be returned
+ * in this structure.
+ *
+ * @return The clock rate, when the resulting div_config is used.
+ */
+static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
+				       struct ast2500_div_config *cfg)
 {
-	ulong clkin = ast2500_get_clkin(scu);
-	u32 mpll_reg;
-
 	/*
-	 * There are not that many combinations of numerator, denumerator
-	 * and post divider, so just brute force the best combination.
-	 * However, to avoid overflow when multiplying, use kHz.
+	 * The assumption is that kHz precision is good enough and
+	 * also enough to avoid overflow when multiplying.
 	 */
-	const ulong clkin_khz = clkin / 1000;
-	const ulong rate_khz = rate / 1000;
-	ulong best_num = 0;
-	ulong best_denum = 0;
-	ulong best_post = 0;
-	ulong delta = rate;
-	ulong num, denum, post;
-
-	for (denum = 0; denum <= SCU_MPLL_DENUM_MASK; ++denum) {
-		for (post = 0; post <= SCU_MPLL_POST_MASK; ++post) {
-			num = (rate_khz * (post + 1) / clkin_khz) * (denum + 1);
-			ulong new_rate_khz = (clkin_khz
-					      * ((num + 1) / (denum + 1)))
-					     / (post + 1);
+	const ulong input_rate_khz = input_rate / 1000;
+	const ulong rate_khz = requested_rate / 1000;
+	const struct ast2500_div_config max_vals = *cfg;
+	struct ast2500_div_config it = { 0, 0, 0 };
+	ulong delta = rate_khz;
+	ulong new_rate_khz = 0;
+
+	for (; it.denum <= max_vals.denum; ++it.denum) {
+		for (it.post_div = 0; it.post_div <= max_vals.post_div;
+		     ++it.post_div) {
+			it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
+			    * (it.denum + 1);
+			if (it.num > max_vals.num)
+				continue;
+
+			new_rate_khz = (input_rate_khz
+					* ((it.num + 1) / (it.denum + 1)))
+			    / (it.post_div + 1);
 
 			/* Keep the rate below requested one. */
 			if (new_rate_khz > rate_khz)
@@ -174,25 +208,35 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 
 			if (new_rate_khz - rate_khz < delta) {
 				delta = new_rate_khz - rate_khz;
-
-				best_num = num;
-				best_denum = denum;
-				best_post = post;
-
+				*cfg = it;
 				if (delta == 0)
-					goto rate_calc_done;
+					return new_rate_khz * 1000;
 			}
 		}
 	}
 
- rate_calc_done:
+	return new_rate_khz * 1000;
+}
+
+static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	u32 mpll_reg;
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_MPLL_NUM_MASK,
+		.denum = SCU_MPLL_DENUM_MASK,
+		.post_div = SCU_MPLL_POST_MASK
+	};
+
+	ast2500_calc_clock_config(clkin, rate, &div_cfg);
+
 	mpll_reg = readl(&scu->m_pll_param);
 	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
 		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
 		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
-	mpll_reg |= (best_post << SCU_MPLL_POST_SHIFT)
-	    | (best_num << SCU_MPLL_NUM_SHIFT)
-	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
+	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
+	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
+	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
 
 	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
@@ -201,6 +245,136 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
 
+static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong hpll_rate = ast2500_get_hpll_rate(clkin,
+						readl(&scu->h_pll_param));
+	ulong required_rate;
+	u32 hwstrap;
+	u32 divisor;
+	u32 reset_bit;
+	u32 clkstop_bit;
+
+	/*
+	 * According to data sheet, for 10/100 mode the MAC clock frequency
+	 * should be at least 25MHz and for 1000 mode at least 100MHz
+	 */
+	hwstrap = readl(&scu->hwstrap);
+	if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
+		required_rate = 100 * 1000 * 1000;
+	else
+		required_rate = 25 * 1000 * 1000;
+
+	divisor = hpll_rate / required_rate;
+
+	if (divisor < 4) {
+		/* Clock can't run fast enough, but let's try anyway */
+		debug("MAC clock too slow\n");
+		divisor = 4;
+	} else if (divisor > 16) {
+		/* Can't slow down the clock enough, but let's try anyway */
+		debug("MAC clock too fast\n");
+		divisor = 16;
+	}
+
+	switch (index) {
+	case 1:
+		reset_bit = SCU_SYSRESET_MAC1;
+		clkstop_bit = SCU_CLKSTOP_MAC1;
+		break;
+	case 2:
+		reset_bit = SCU_SYSRESET_MAC2;
+		clkstop_bit = SCU_CLKSTOP_MAC2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ast_scu_unlock(scu);
+	clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
+			((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
+
+	/*
+	 * Disable MAC, start its clock and re-enable it.
+	 * The procedure and the delays (100us & 10ms) are
+	 * specified in the datasheet.
+	 */
+	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
+	udelay(100);
+	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
+	mdelay(10);
+	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
+
+	writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+	       | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
+	       &scu->clk_duty_sel);
+
+	ast_scu_lock(scu);
+
+	return required_rate;
+}
+
+static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
+{
+	/*
+	 * The values and the meaning of the next three
+	 * parameters are undocumented. Taken from Aspeed SDK.
+	 */
+	const u32 d2_pll_ext_param = 0x2c;
+	const u32 d2_pll_sip = 0x11;
+	const u32 d2_pll_sic = 0x18;
+	u32 clk_delay_settings =
+	    (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+	    | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
+		.denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
+		.post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
+	};
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong new_rate;
+
+	ast_scu_unlock(scu);
+	writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
+	       | SCU_D2PLL_EXT1_OFF
+	       | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
+
+	/*
+	 * Select USB2.0 port1 PHY clock as a clock source for GCRT.
+	 * This would disconnect it from D2-PLL.
+	 */
+	clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
+			SCU_MISC_GCRT_USB20CLK);
+
+	new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
+	writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
+	       | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
+	       | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
+	       | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
+	       | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
+	       &scu->d2_pll_param);
+
+	clrbits_le32(&scu->d2_pll_ext_param[0],
+		     SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
+
+	clrsetbits_le32(&scu->misc_ctrl2,
+			SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
+			| SCU_MISC2_RGMII_CLKDIV_MASK |
+			SCU_MISC2_RMII_CLKDIV_MASK,
+			(4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
+
+	writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
+	writel(clk_delay_settings, &scu->mac_clk_delay_100M);
+	writel(clk_delay_settings, &scu->mac_clk_delay_10M);
+
+	ast_scu_lock(scu);
+
+	return new_rate;
+}
+
 static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 {
 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
@@ -211,6 +385,9 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	case MCLK_DDR:
 		new_rate = ast2500_configure_ddr(priv->scu, rate);
 		break;
+	case PLL_D2PLL:
+		new_rate = ast2500_configure_d2pll(priv->scu, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -218,9 +395,35 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	return new_rate;
 }
 
+static int ast2500_clk_enable(struct clk *clk)
+{
+	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	/*
+	 * For MAC clocks the clock rate is
+	 * configured based on whether RGMII or RMII mode has been selected
+	 * through hardware strapping.
+	 */
+	case PCLK_MAC1:
+		ast2500_configure_mac(priv->scu, 1);
+		break;
+	case PCLK_MAC2:
+		ast2500_configure_mac(priv->scu, 2);
+		break;
+	case PLL_D2PLL:
+		ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
+	default:
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
 struct clk_ops ast2500_clk_ops = {
 	.get_rate = ast2500_clk_get_rate,
 	.set_rate = ast2500_clk_set_rate,
+	.enable = ast2500_clk_enable,
 };
 
 static int ast2500_clk_probe(struct udevice *dev)
diff --git a/include/dt-bindings/clock/ast2500-scu.h b/include/dt-bindings/clock/ast2500-scu.h
index ca58b12943..e2d7aaf9fe 100644
--- a/include/dt-bindings/clock/ast2500-scu.h
+++ b/include/dt-bindings/clock/ast2500-scu.h
@@ -27,3 +27,5 @@
 #define PCLK_UART3	503
 #define PCLK_UART4	504
 #define PCLK_UART5	505
+#define PCLK_MAC1	506
+#define PCLK_MAC2	507
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 13/15] aspeed: Add support for Clocks needed by MACs
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Add support for clocks needed by MACs to ast2500 clock driver.
The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
PCLK_MAC2 for MAC1 and MAC2 respectively.

The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
SDK. It is not entirely clear from the datasheet how this clock is used
by MACs, so not clear if the rate would ever need to be different. So,
for now, hardcoding it is probably safer.

The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
hardware strapping.

So, the network driver would only need to enable these clocks, no need
to configure the rate.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/dts/ast2500-u-boot.dtsi               |   8 +
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  62 +++++-
 drivers/clk/aspeed/clk_ast2500.c               | 265 ++++++++++++++++++++++---
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 4 files changed, 304 insertions(+), 33 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index faeeec1be4..f826646095 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -61,3 +61,11 @@
 		};
 	};
 };
+
+&mac0 {
+	clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;
+};
+
+&mac1 {
+	clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>;
+};
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 319d75e05c..fe877b5430 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -30,9 +30,36 @@
 #define SCU_HPLL_POST_SHIFT		13
 #define SCU_HPLL_POST_MASK		0x3f
 
+#define SCU_MACCLK_SHIFT		16
+#define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
+
+#define SCU_MISC2_RGMII_HPLL		(1 << 23)
+#define SCU_MISC2_RGMII_CLKDIV_SHIFT	20
+#define SCU_MISC2_RGMII_CLKDIV_MASK	(3 << SCU_MISC2_RGMII_CLKDIV_SHIFT)
+#define SCU_MISC2_RMII_MPLL		(1 << 19)
+#define SCU_MISC2_RMII_CLKDIV_SHIFT	16
+#define SCU_MISC2_RMII_CLKDIV_MASK	(3 << SCU_MISC2_RMII_CLKDIV_SHIFT)
 #define SCU_MISC2_UARTCLK_SHIFT		24
 
+#define SCU_MISC_D2PLL_OFF		(1 << 4)
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
+#define SCU_MISC_GCRT_USB20CLK		(1 << 21)
+
+#define SCU_MICDS_MAC1RGMII_TXDLY_SHIFT	0
+#define SCU_MICDS_MAC1RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC2RGMII_TXDLY_SHIFT	6
+#define SCU_MICDS_MAC2RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_RDLY_SHIFT	12
+#define SCU_MICDS_MAC1RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC2RMII_RDLY_SHIFT	18
+#define SCU_MICDS_MAC2RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_TXFALL	(1 << 24)
+#define SCU_MICDS_MAC2RMII_TXFALL	(1 << 25)
+#define SCU_MICDS_RMII1_RCLKEN		(1 << 29)
+#define SCU_MICDS_RMII2_RCLKEN		(1 << 30)
+#define SCU_MICDS_RGMIIPLL		(1 << 31)
 
 /*
  * SYSRESET is actually more like a Power register,
@@ -71,14 +98,45 @@
  */
 #define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
 #define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
-#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC1_PHY_LINK	(1 << 0)
 #define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
-#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_MAC2_PHY_LINK	(1 << 1)
 #define SCU_PIN_FUN_SCL1		(1 << 12)
 #define SCU_PIN_FUN_SCL2		(1 << 14)
 #define SCU_PIN_FUN_SDA1		(1 << 13)
 #define SCU_PIN_FUN_SDA2		(1 << 15)
 
+#define SCU_CLKSTOP_MAC1		(1 << 20)
+#define SCU_CLKSTOP_MAC2		(1 << 21)
+
+#define SCU_D2PLL_EXT1_OFF		(1 << 0)
+#define SCU_D2PLL_EXT1_BYPASS		(1 << 1)
+#define SCU_D2PLL_EXT1_RESET		(1 << 2)
+#define SCU_D2PLL_EXT1_MODE_SHIFT	3
+#define SCU_D2PLL_EXT1_MODE_MASK	(3 << SCU_D2PLL_EXT1_MODE_SHIFT)
+#define SCU_D2PLL_EXT1_PARAM_SHIFT	5
+#define SCU_D2PLL_EXT1_PARAM_MASK	(0x1ff << SCU_D2PLL_EXT1_PARAM_SHIFT)
+
+#define SCU_D2PLL_NUM_SHIFT		0
+#define SCU_D2PLL_NUM_MASK		(0xff << SCU_D2PLL_NUM_SHIFT)
+#define SCU_D2PLL_DENUM_SHIFT		8
+#define SCU_D2PLL_DENUM_MASK		(0x1f << SCU_D2PLL_DENUM_SHIFT)
+#define SCU_D2PLL_POST_SHIFT		13
+#define SCU_D2PLL_POST_MASK		(0x3f << SCU_D2PLL_POST_SHIFT)
+#define SCU_D2PLL_ODIV_SHIFT		19
+#define SCU_D2PLL_ODIV_MASK		(7 << SCU_D2PLL_ODIV_SHIFT)
+#define SCU_D2PLL_SIC_SHIFT		22
+#define SCU_D2PLL_SIC_MASK		(0x1f << SCU_D2PLL_SIC_SHIFT)
+#define SCU_D2PLL_SIP_SHIFT		27
+#define SCU_D2PLL_SIP_MASK		(0x1f << SCU_D2PLL_SIP_SHIFT)
+
+#define SCU_CLKDUTY_DCLK_SHIFT		0
+#define SCU_CLKDUTY_DCLK_MASK		(0x3f << SCU_CLKDUTY_DCLK_SHIFT)
+#define SCU_CLKDUTY_RGMII1TXCK_SHIFT	8
+#define SCU_CLKDUTY_RGMII1TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII1TXCK_SHIFT)
+#define SCU_CLKDUTY_RGMII2TXCK_SHIFT	16
+#define SCU_CLKDUTY_RGMII2TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 9e4c66ea85..7b4b5c64ac 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -12,16 +12,39 @@
 #include <dm/lists.h>
 #include <dt-bindings/clock/ast2500-scu.h>
 
+/*
+ * MAC Clock Delay settings, taken from Aspeed SDK
+ */
+#define RGMII_TXCLK_ODLY		8
+#define RMII_RXCLK_IDLY		2
+
+/*
+ * TGMII Clock Duty constants, taken from Aspeed SDK
+ */
+#define RGMII2_TXCK_DUTY	0x66
+#define RGMII1_TXCK_DUTY	0x64
+
+#define D2PLL_DEFAULT_RATE	(250 * 1000 * 1000)
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
+ * Clock divider/multiplier configuration struct.
  * For H-PLL and M-PLL the formula is
  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
  * M - Numerator
  * N - Denumerator
  * P - Post Divider
  * They have the same layout in their control register.
+ *
+ * D-PLL and D2-PLL have extra divider (OD + 1), which is not
+ * yet needed and ignored by clock configurations.
  */
+struct ast2500_div_config {
+	unsigned int num;
+	unsigned int denum;
+	unsigned int post_div;
+};
 
 /*
  * Get the rate of the M-PLL clock from input clock frequency and
@@ -143,30 +166,41 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+/*
+ * @input_rate - the rate of input clock in Hz
+ * @requested_rate - desired output rate in Hz
+ * @div - this is an IN/OUT parameter, at input all fields of the config
+ * need to be set to their maximum allowed values.
+ * The result (the best config we could find), would also be returned
+ * in this structure.
+ *
+ * @return The clock rate, when the resulting div_config is used.
+ */
+static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
+				       struct ast2500_div_config *cfg)
 {
-	ulong clkin = ast2500_get_clkin(scu);
-	u32 mpll_reg;
-
 	/*
-	 * There are not that many combinations of numerator, denumerator
-	 * and post divider, so just brute force the best combination.
-	 * However, to avoid overflow when multiplying, use kHz.
+	 * The assumption is that kHz precision is good enough and
+	 * also enough to avoid overflow when multiplying.
 	 */
-	const ulong clkin_khz = clkin / 1000;
-	const ulong rate_khz = rate / 1000;
-	ulong best_num = 0;
-	ulong best_denum = 0;
-	ulong best_post = 0;
-	ulong delta = rate;
-	ulong num, denum, post;
-
-	for (denum = 0; denum <= SCU_MPLL_DENUM_MASK; ++denum) {
-		for (post = 0; post <= SCU_MPLL_POST_MASK; ++post) {
-			num = (rate_khz * (post + 1) / clkin_khz) * (denum + 1);
-			ulong new_rate_khz = (clkin_khz
-					      * ((num + 1) / (denum + 1)))
-					     / (post + 1);
+	const ulong input_rate_khz = input_rate / 1000;
+	const ulong rate_khz = requested_rate / 1000;
+	const struct ast2500_div_config max_vals = *cfg;
+	struct ast2500_div_config it = { 0, 0, 0 };
+	ulong delta = rate_khz;
+	ulong new_rate_khz = 0;
+
+	for (; it.denum <= max_vals.denum; ++it.denum) {
+		for (it.post_div = 0; it.post_div <= max_vals.post_div;
+		     ++it.post_div) {
+			it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
+			    * (it.denum + 1);
+			if (it.num > max_vals.num)
+				continue;
+
+			new_rate_khz = (input_rate_khz
+					* ((it.num + 1) / (it.denum + 1)))
+			    / (it.post_div + 1);
 
 			/* Keep the rate below requested one. */
 			if (new_rate_khz > rate_khz)
@@ -174,25 +208,35 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 
 			if (new_rate_khz - rate_khz < delta) {
 				delta = new_rate_khz - rate_khz;
-
-				best_num = num;
-				best_denum = denum;
-				best_post = post;
-
+				*cfg = it;
 				if (delta == 0)
-					goto rate_calc_done;
+					return new_rate_khz * 1000;
 			}
 		}
 	}
 
- rate_calc_done:
+	return new_rate_khz * 1000;
+}
+
+static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	u32 mpll_reg;
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_MPLL_NUM_MASK,
+		.denum = SCU_MPLL_DENUM_MASK,
+		.post_div = SCU_MPLL_POST_MASK
+	};
+
+	ast2500_calc_clock_config(clkin, rate, &div_cfg);
+
 	mpll_reg = readl(&scu->m_pll_param);
 	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
 		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
 		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
-	mpll_reg |= (best_post << SCU_MPLL_POST_SHIFT)
-	    | (best_num << SCU_MPLL_NUM_SHIFT)
-	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
+	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
+	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
+	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
 
 	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
@@ -201,6 +245,136 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
 
+static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong hpll_rate = ast2500_get_hpll_rate(clkin,
+						readl(&scu->h_pll_param));
+	ulong required_rate;
+	u32 hwstrap;
+	u32 divisor;
+	u32 reset_bit;
+	u32 clkstop_bit;
+
+	/*
+	 * According to data sheet, for 10/100 mode the MAC clock frequency
+	 * should be at least 25MHz and for 1000 mode at least 100MHz
+	 */
+	hwstrap = readl(&scu->hwstrap);
+	if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
+		required_rate = 100 * 1000 * 1000;
+	else
+		required_rate = 25 * 1000 * 1000;
+
+	divisor = hpll_rate / required_rate;
+
+	if (divisor < 4) {
+		/* Clock can't run fast enough, but let's try anyway */
+		debug("MAC clock too slow\n");
+		divisor = 4;
+	} else if (divisor > 16) {
+		/* Can't slow down the clock enough, but let's try anyway */
+		debug("MAC clock too fast\n");
+		divisor = 16;
+	}
+
+	switch (index) {
+	case 1:
+		reset_bit = SCU_SYSRESET_MAC1;
+		clkstop_bit = SCU_CLKSTOP_MAC1;
+		break;
+	case 2:
+		reset_bit = SCU_SYSRESET_MAC2;
+		clkstop_bit = SCU_CLKSTOP_MAC2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ast_scu_unlock(scu);
+	clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
+			((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
+
+	/*
+	 * Disable MAC, start its clock and re-enable it.
+	 * The procedure and the delays (100us & 10ms) are
+	 * specified in the datasheet.
+	 */
+	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
+	udelay(100);
+	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
+	mdelay(10);
+	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
+
+	writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+	       | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
+	       &scu->clk_duty_sel);
+
+	ast_scu_lock(scu);
+
+	return required_rate;
+}
+
+static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
+{
+	/*
+	 * The values and the meaning of the next three
+	 * parameters are undocumented. Taken from Aspeed SDK.
+	 */
+	const u32 d2_pll_ext_param = 0x2c;
+	const u32 d2_pll_sip = 0x11;
+	const u32 d2_pll_sic = 0x18;
+	u32 clk_delay_settings =
+	    (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+	    | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
+		.denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
+		.post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
+	};
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong new_rate;
+
+	ast_scu_unlock(scu);
+	writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
+	       | SCU_D2PLL_EXT1_OFF
+	       | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
+
+	/*
+	 * Select USB2.0 port1 PHY clock as a clock source for GCRT.
+	 * This would disconnect it from D2-PLL.
+	 */
+	clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
+			SCU_MISC_GCRT_USB20CLK);
+
+	new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
+	writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
+	       | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
+	       | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
+	       | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
+	       | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
+	       &scu->d2_pll_param);
+
+	clrbits_le32(&scu->d2_pll_ext_param[0],
+		     SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
+
+	clrsetbits_le32(&scu->misc_ctrl2,
+			SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
+			| SCU_MISC2_RGMII_CLKDIV_MASK |
+			SCU_MISC2_RMII_CLKDIV_MASK,
+			(4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
+
+	writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
+	writel(clk_delay_settings, &scu->mac_clk_delay_100M);
+	writel(clk_delay_settings, &scu->mac_clk_delay_10M);
+
+	ast_scu_lock(scu);
+
+	return new_rate;
+}
+
 static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 {
 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
@@ -211,6 +385,9 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	case MCLK_DDR:
 		new_rate = ast2500_configure_ddr(priv->scu, rate);
 		break;
+	case PLL_D2PLL:
+		new_rate = ast2500_configure_d2pll(priv->scu, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -218,9 +395,35 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	return new_rate;
 }
 
+static int ast2500_clk_enable(struct clk *clk)
+{
+	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	/*
+	 * For MAC clocks the clock rate is
+	 * configured based on whether RGMII or RMII mode has been selected
+	 * through hardware strapping.
+	 */
+	case PCLK_MAC1:
+		ast2500_configure_mac(priv->scu, 1);
+		break;
+	case PCLK_MAC2:
+		ast2500_configure_mac(priv->scu, 2);
+		break;
+	case PLL_D2PLL:
+		ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
+	default:
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
 struct clk_ops ast2500_clk_ops = {
 	.get_rate = ast2500_clk_get_rate,
 	.set_rate = ast2500_clk_set_rate,
+	.enable = ast2500_clk_enable,
 };
 
 static int ast2500_clk_probe(struct udevice *dev)
diff --git a/include/dt-bindings/clock/ast2500-scu.h b/include/dt-bindings/clock/ast2500-scu.h
index ca58b12943..e2d7aaf9fe 100644
--- a/include/dt-bindings/clock/ast2500-scu.h
+++ b/include/dt-bindings/clock/ast2500-scu.h
@@ -27,3 +27,5 @@
 #define PCLK_UART3	503
 #define PCLK_UART4	504
 #define PCLK_UART5	505
+#define PCLK_MAC1	506
+#define PCLK_MAC2	507
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 14/15] aspeed: Refactor SCU to use consistent mask & shift
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Refactor SCU header to use consistent Mask & Shift values.
Now, consistently, to read value from SCU register, mask needs
to be applied before shift.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 12 ++++----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  5 ++--
 drivers/clk/aspeed/clk_ast2500.c               | 39 +++++++++++++-------------
 3 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fe877b5430..590aed2f6c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -8,8 +8,8 @@
 
 #define SCU_UNLOCK_VALUE		0x1688a8a8
 
-#define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_VGAMEM_MASK		(3 << SCU_HWSTRAP_VGAMEM_SHIFT)
 #define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
 #define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
@@ -18,17 +18,17 @@
 #define SCU_MPLL_DENUM_SHIFT		0
 #define SCU_MPLL_DENUM_MASK		0x1f
 #define SCU_MPLL_NUM_SHIFT		5
-#define SCU_MPLL_NUM_MASK		0xff
+#define SCU_MPLL_NUM_MASK		(0xff << SCU_MPLL_NUM_SHIFT)
 #define SCU_MPLL_POST_SHIFT		13
-#define SCU_MPLL_POST_MASK		0x3f
+#define SCU_MPLL_POST_MASK		(0x3f << SCU_MPLL_POST_SHIFT)
 #define SCU_PCLK_DIV_SHIFT		23
-#define SCU_PCLK_DIV_MASK		7
+#define SCU_PCLK_DIV_MASK		(7 << SCU_PCLK_DIV_SHIFT)
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
-#define SCU_HPLL_NUM_MASK		0xff
+#define SCU_HPLL_NUM_MASK		(0xff << SCU_HPLL_NUM_SHIFT)
 #define SCU_HPLL_POST_SHIFT		13
-#define SCU_HPLL_POST_MASK		0x3f
+#define SCU_HPLL_POST_MASK		(0x3f << SCU_HPLL_POST_SHIFT)
 
 #define SCU_MACCLK_SHIFT		16
 #define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index efcf452b17..6383f727f2 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -183,9 +183,8 @@ static int ast2500_sdrammc_ddr4_calibrate_vref(struct dram_info *info)
 static size_t ast2500_sdrammc_get_vga_mem_size(struct dram_info *info)
 {
 	size_t vga_mem_size_base = 8 * 1024 * 1024;
-	u32 vga_hwconf = (readl(&info->scu->hwstrap)
-			  >> SCU_HWSTRAP_VGAMEM_SHIFT)
-			& SCU_HWSTRAP_VGAMEM_MASK;
+	u32 vga_hwconf = (readl(&info->scu->hwstrap) & SCU_HWSTRAP_VGAMEM_MASK)
+	    >> SCU_HWSTRAP_VGAMEM_SHIFT;
 
 	return vga_mem_size_base << vga_hwconf;
 }
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 7b4b5c64ac..ccf47a1da1 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -52,11 +52,11 @@ struct ast2500_div_config {
  */
 static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
 {
-	const ulong num = (mpll_reg >> SCU_MPLL_NUM_SHIFT) & SCU_MPLL_NUM_MASK;
-	const ulong denum = (mpll_reg >> SCU_MPLL_DENUM_SHIFT)
-			& SCU_MPLL_DENUM_MASK;
-	const ulong post_div = (mpll_reg >> SCU_MPLL_POST_SHIFT)
-			& SCU_MPLL_POST_MASK;
+	const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT;
+	const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK)
+			>> SCU_MPLL_DENUM_SHIFT;
+	const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK)
+			>> SCU_MPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -67,11 +67,11 @@ static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
  */
 static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg)
 {
-	const ulong num = (hpll_reg >> SCU_HPLL_NUM_SHIFT) & SCU_HPLL_NUM_MASK;
-	const ulong denum = (hpll_reg >> SCU_HPLL_DENUM_SHIFT)
-			& SCU_HPLL_DENUM_MASK;
-	const ulong post_div = (hpll_reg >> SCU_HPLL_POST_SHIFT)
-			& SCU_HPLL_POST_MASK;
+	const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT;
+	const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK)
+			>> SCU_HPLL_DENUM_SHIFT;
+	const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK)
+			>> SCU_HPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -136,11 +136,11 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	case BCLK_PCLK:
 		{
 			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
-						  >> SCU_PCLK_DIV_SHIFT) &
-						 SCU_PCLK_DIV_MASK);
+						  & SCU_PCLK_DIV_MASK)
+						 >> SCU_PCLK_DIV_SHIFT);
 			rate = ast2500_get_hpll_rate(clkin,
-						     readl(&priv->scu->
-							   h_pll_param));
+						     readl(&priv->
+							   scu->h_pll_param));
 			rate = rate / apb_div;
 		}
 		break;
@@ -223,17 +223,16 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	ulong clkin = ast2500_get_clkin(scu);
 	u32 mpll_reg;
 	struct ast2500_div_config div_cfg = {
-		.num = SCU_MPLL_NUM_MASK,
-		.denum = SCU_MPLL_DENUM_MASK,
-		.post_div = SCU_MPLL_POST_MASK
+		.num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
+		.denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
+		.post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
 	};
 
 	ast2500_calc_clock_config(clkin, rate, &div_cfg);
 
 	mpll_reg = readl(&scu->m_pll_param);
-	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
-		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
-		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
+	mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
+		      | SCU_MPLL_DENUM_MASK);
 	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
 	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
 	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 14/15] aspeed: Refactor SCU to use consistent mask & shift
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Refactor SCU header to use consistent Mask & Shift values.
Now, consistently, to read value from SCU register, mask needs
to be applied before shift.

Signed-off-by: Maxim Sloyko <maxims@google.com>
---

Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 12 ++++----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  5 ++--
 drivers/clk/aspeed/clk_ast2500.c               | 39 +++++++++++++-------------
 3 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fe877b5430..590aed2f6c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -8,8 +8,8 @@
 
 #define SCU_UNLOCK_VALUE		0x1688a8a8
 
-#define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_VGAMEM_MASK		(3 << SCU_HWSTRAP_VGAMEM_SHIFT)
 #define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
 #define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
@@ -18,17 +18,17 @@
 #define SCU_MPLL_DENUM_SHIFT		0
 #define SCU_MPLL_DENUM_MASK		0x1f
 #define SCU_MPLL_NUM_SHIFT		5
-#define SCU_MPLL_NUM_MASK		0xff
+#define SCU_MPLL_NUM_MASK		(0xff << SCU_MPLL_NUM_SHIFT)
 #define SCU_MPLL_POST_SHIFT		13
-#define SCU_MPLL_POST_MASK		0x3f
+#define SCU_MPLL_POST_MASK		(0x3f << SCU_MPLL_POST_SHIFT)
 #define SCU_PCLK_DIV_SHIFT		23
-#define SCU_PCLK_DIV_MASK		7
+#define SCU_PCLK_DIV_MASK		(7 << SCU_PCLK_DIV_SHIFT)
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
-#define SCU_HPLL_NUM_MASK		0xff
+#define SCU_HPLL_NUM_MASK		(0xff << SCU_HPLL_NUM_SHIFT)
 #define SCU_HPLL_POST_SHIFT		13
-#define SCU_HPLL_POST_MASK		0x3f
+#define SCU_HPLL_POST_MASK		(0x3f << SCU_HPLL_POST_SHIFT)
 
 #define SCU_MACCLK_SHIFT		16
 #define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index efcf452b17..6383f727f2 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -183,9 +183,8 @@ static int ast2500_sdrammc_ddr4_calibrate_vref(struct dram_info *info)
 static size_t ast2500_sdrammc_get_vga_mem_size(struct dram_info *info)
 {
 	size_t vga_mem_size_base = 8 * 1024 * 1024;
-	u32 vga_hwconf = (readl(&info->scu->hwstrap)
-			  >> SCU_HWSTRAP_VGAMEM_SHIFT)
-			& SCU_HWSTRAP_VGAMEM_MASK;
+	u32 vga_hwconf = (readl(&info->scu->hwstrap) & SCU_HWSTRAP_VGAMEM_MASK)
+	    >> SCU_HWSTRAP_VGAMEM_SHIFT;
 
 	return vga_mem_size_base << vga_hwconf;
 }
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 7b4b5c64ac..ccf47a1da1 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -52,11 +52,11 @@ struct ast2500_div_config {
  */
 static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
 {
-	const ulong num = (mpll_reg >> SCU_MPLL_NUM_SHIFT) & SCU_MPLL_NUM_MASK;
-	const ulong denum = (mpll_reg >> SCU_MPLL_DENUM_SHIFT)
-			& SCU_MPLL_DENUM_MASK;
-	const ulong post_div = (mpll_reg >> SCU_MPLL_POST_SHIFT)
-			& SCU_MPLL_POST_MASK;
+	const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT;
+	const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK)
+			>> SCU_MPLL_DENUM_SHIFT;
+	const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK)
+			>> SCU_MPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -67,11 +67,11 @@ static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
  */
 static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg)
 {
-	const ulong num = (hpll_reg >> SCU_HPLL_NUM_SHIFT) & SCU_HPLL_NUM_MASK;
-	const ulong denum = (hpll_reg >> SCU_HPLL_DENUM_SHIFT)
-			& SCU_HPLL_DENUM_MASK;
-	const ulong post_div = (hpll_reg >> SCU_HPLL_POST_SHIFT)
-			& SCU_HPLL_POST_MASK;
+	const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT;
+	const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK)
+			>> SCU_HPLL_DENUM_SHIFT;
+	const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK)
+			>> SCU_HPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -136,11 +136,11 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	case BCLK_PCLK:
 		{
 			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
-						  >> SCU_PCLK_DIV_SHIFT) &
-						 SCU_PCLK_DIV_MASK);
+						  & SCU_PCLK_DIV_MASK)
+						 >> SCU_PCLK_DIV_SHIFT);
 			rate = ast2500_get_hpll_rate(clkin,
-						     readl(&priv->scu->
-							   h_pll_param));
+						     readl(&priv->
+							   scu->h_pll_param));
 			rate = rate / apb_div;
 		}
 		break;
@@ -223,17 +223,16 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	ulong clkin = ast2500_get_clkin(scu);
 	u32 mpll_reg;
 	struct ast2500_div_config div_cfg = {
-		.num = SCU_MPLL_NUM_MASK,
-		.denum = SCU_MPLL_DENUM_MASK,
-		.post_div = SCU_MPLL_POST_MASK
+		.num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
+		.denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
+		.post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
 	};
 
 	ast2500_calc_clock_config(clkin, rate, &div_cfg);
 
 	mpll_reg = readl(&scu->m_pll_param);
-	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
-		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
-		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
+	mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
+		      | SCU_MPLL_DENUM_MASK);
 	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
 	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
 	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH v1 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-04-17 19:00   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Remove unnecessary apb and ahb nodes and just override necessary
nodes/values.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1: None


---
 arch/arm/dts/ast2500-u-boot.dtsi | 41 ++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index f826646095..7f80bad7d0 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -34,32 +34,33 @@
 
 		apb {
 			u-boot,dm-pre-reloc;
+		};
 
-			timer: timer@1e782000 {
-				u-boot,dm-pre-reloc;
-			};
+	};
+};
 
-			uart1: serial@1e783000 {
-				clocks = <&scu PCLK_UART1>;
-			};
+&uart1 {
+	clocks = <&scu PCLK_UART1>;
+};
 
-			uart2: serial@1e78d000 {
-				clocks = <&scu PCLK_UART2>;
-			};
+&uart2 {
+	clocks = <&scu PCLK_UART2>;
+};
 
-			uart3: serial@1e78e000 {
-				clocks = <&scu PCLK_UART3>;
-			};
+&uart3 {
+	clocks = <&scu PCLK_UART3>;
+};
 
-			uart4: serial@1e78f000 {
-				clocks = <&scu PCLK_UART4>;
-			};
+&uart4 {
+	clocks = <&scu PCLK_UART4>;
+};
 
-			uart5: serial@1e784000 {
-				clocks = <&scu PCLK_UART5>;
-			};
-		};
-	};
+&uart5 {
+	clocks = <&scu PCLK_UART5>;
+};
+
+&timer {
+	u-boot,dm-pre-reloc;
 };
 
 &mac0 {
-- 
2.12.2.762.g0e3151a226-goog

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

* [U-Boot] [PATCH v1 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
@ 2017-04-17 19:00   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-17 19:00 UTC (permalink / raw)
  To: u-boot

Remove unnecessary apb and ahb nodes and just override necessary
nodes/values.

Signed-off-by: Maxim Sloyko <maxims@google.com>

---

Changes in v1: None


---
 arch/arm/dts/ast2500-u-boot.dtsi | 41 ++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index f826646095..7f80bad7d0 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -34,32 +34,33 @@
 
 		apb {
 			u-boot,dm-pre-reloc;
+		};
 
-			timer: timer at 1e782000 {
-				u-boot,dm-pre-reloc;
-			};
+	};
+};
 
-			uart1: serial at 1e783000 {
-				clocks = <&scu PCLK_UART1>;
-			};
+&uart1 {
+	clocks = <&scu PCLK_UART1>;
+};
 
-			uart2: serial at 1e78d000 {
-				clocks = <&scu PCLK_UART2>;
-			};
+&uart2 {
+	clocks = <&scu PCLK_UART2>;
+};
 
-			uart3: serial at 1e78e000 {
-				clocks = <&scu PCLK_UART3>;
-			};
+&uart3 {
+	clocks = <&scu PCLK_UART3>;
+};
 
-			uart4: serial at 1e78f000 {
-				clocks = <&scu PCLK_UART4>;
-			};
+&uart4 {
+	clocks = <&scu PCLK_UART4>;
+};
 
-			uart5: serial at 1e784000 {
-				clocks = <&scu PCLK_UART5>;
-			};
-		};
-	};
+&uart5 {
+	clocks = <&scu PCLK_UART5>;
+};
+
+&timer {
+	u-boot,dm-pre-reloc;
 };
 
 &mac0 {
-- 
2.12.2.762.g0e3151a226-goog

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

* Re: [PATCH v1 01/15] aspeed: Update ast2500 Device Tree
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Pull in the Device Tree for ast2500 from the mainline Linux kernel.
> The file is copied from
> https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Added link to the original version to commit message
>
> ---
>  arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 880 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 01/15] aspeed: Update ast2500 Device Tree
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Pull in the Device Tree for ast2500 from the mainline Linux kernel.
> The file is copied from
> https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Added link to the original version to commit message
>
> ---
>  arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 880 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 02/15] dm: Simple Watchdog uclass
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Stephen Warren

Hi Maxim,

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This is a simple uclass for Watchdog Timers. It has four operations:
> start, restart, reset, stop. Drivers must implement start, restart and
> stop operations, while implementing reset is optional: It's default
> implementation expires watchdog timer in one clock tick.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1:
> - Rename wdt_reset to wdt_expire_now
> - Rename wdt_restart to wdt_reset
> - Clarified function documentation in few cases
> - Add Sandbox WDT driver and unit tests
>
>
> ---
>  arch/sandbox/dts/test.dts        |   4 ++
>  arch/sandbox/include/asm/state.h |   9 ++++
>  configs/sandbox_defconfig        |   2 +
>  drivers/watchdog/Kconfig         |  21 ++++++++
>  drivers/watchdog/Makefile        |   2 +
>  drivers/watchdog/sandbox_wdt.c   |  76 +++++++++++++++++++++++++++
>  drivers/watchdog/wdt-uclass.c    |  72 ++++++++++++++++++++++++++
>  include/dm/uclass-id.h           |   1 +
>  include/wdt.h                    | 107 +++++++++++++++++++++++++++++++++++++++
>  test/dm/Makefile                 |   1 +
>  test/dm/wdt.c                    |  40 +++++++++++++++
>  11 files changed, 335 insertions(+)
>  create mode 100644 drivers/watchdog/sandbox_wdt.c
>  create mode 100644 drivers/watchdog/wdt-uclass.c
>  create mode 100644 include/wdt.h
>  create mode 100644 test/dm/wdt.c

Reviewed-by: Simon Glass <sjg@chromium.org>

nits below

[...]

> diff --git a/drivers/watchdog/sandbox_wdt.c b/drivers/watchdog/sandbox_wdt.c
> new file mode 100644
> index 0000000000..34d90bee7e
> --- /dev/null
> +++ b/drivers/watchdog/sandbox_wdt.c
> @@ -0,0 +1,76 @@
> +/*
> + * Copyright 2017 Google, Inc
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <asm/state.h>

Put this after wt.h

> +#include <wdt.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int sandbox_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       state->wdt.counter = timeout;
> +       state->wdt.running = true;
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_stop(struct udevice *dev)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       state->wdt.running = false;
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_reset(struct udevice *dev)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       state->wdt.reset_count++;
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_expire_now(struct udevice *dev, ulong flags)
> +{
> +       sandbox_wdt_start(dev, 1, flags);
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_probe(struct udevice *dev)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       memset(&state->wdt, 0, sizeof(state->wdt));

Driver model does this for you so this function is not needed.

> +
> +       return 0;
> +}
> +
> +static const struct wdt_ops sandbox_wdt_ops = {
> +       .start = sandbox_wdt_start,
> +       .reset = sandbox_wdt_reset,
> +       .stop = sandbox_wdt_stop,
> +       .expire_now = sandbox_wdt_expire_now,
> +};
> +
> +static const struct udevice_id sandbox_wdt_ids[] = {
> +       { .compatible = "sandbox,wdt" },
> +       {}
> +};
> +
> +U_BOOT_DRIVER(wdt_sandbox) = {
> +       .name = "wdt_sandbox",
> +       .id = UCLASS_WDT,
> +       .of_match = sandbox_wdt_ids,
> +       .ops = &sandbox_wdt_ops,
> +       .probe = sandbox_wdt_probe,
> +};

[...]

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

* [U-Boot] [PATCH v1 02/15] dm: Simple Watchdog uclass
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

Hi Maxim,

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This is a simple uclass for Watchdog Timers. It has four operations:
> start, restart, reset, stop. Drivers must implement start, restart and
> stop operations, while implementing reset is optional: It's default
> implementation expires watchdog timer in one clock tick.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1:
> - Rename wdt_reset to wdt_expire_now
> - Rename wdt_restart to wdt_reset
> - Clarified function documentation in few cases
> - Add Sandbox WDT driver and unit tests
>
>
> ---
>  arch/sandbox/dts/test.dts        |   4 ++
>  arch/sandbox/include/asm/state.h |   9 ++++
>  configs/sandbox_defconfig        |   2 +
>  drivers/watchdog/Kconfig         |  21 ++++++++
>  drivers/watchdog/Makefile        |   2 +
>  drivers/watchdog/sandbox_wdt.c   |  76 +++++++++++++++++++++++++++
>  drivers/watchdog/wdt-uclass.c    |  72 ++++++++++++++++++++++++++
>  include/dm/uclass-id.h           |   1 +
>  include/wdt.h                    | 107 +++++++++++++++++++++++++++++++++++++++
>  test/dm/Makefile                 |   1 +
>  test/dm/wdt.c                    |  40 +++++++++++++++
>  11 files changed, 335 insertions(+)
>  create mode 100644 drivers/watchdog/sandbox_wdt.c
>  create mode 100644 drivers/watchdog/wdt-uclass.c
>  create mode 100644 include/wdt.h
>  create mode 100644 test/dm/wdt.c

Reviewed-by: Simon Glass <sjg@chromium.org>

nits below

[...]

> diff --git a/drivers/watchdog/sandbox_wdt.c b/drivers/watchdog/sandbox_wdt.c
> new file mode 100644
> index 0000000000..34d90bee7e
> --- /dev/null
> +++ b/drivers/watchdog/sandbox_wdt.c
> @@ -0,0 +1,76 @@
> +/*
> + * Copyright 2017 Google, Inc
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <asm/state.h>

Put this after wt.h

> +#include <wdt.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int sandbox_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       state->wdt.counter = timeout;
> +       state->wdt.running = true;
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_stop(struct udevice *dev)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       state->wdt.running = false;
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_reset(struct udevice *dev)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       state->wdt.reset_count++;
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_expire_now(struct udevice *dev, ulong flags)
> +{
> +       sandbox_wdt_start(dev, 1, flags);
> +
> +       return 0;
> +}
> +
> +static int sandbox_wdt_probe(struct udevice *dev)
> +{
> +       struct sandbox_state *state = state_get_current();
> +
> +       memset(&state->wdt, 0, sizeof(state->wdt));

Driver model does this for you so this function is not needed.

> +
> +       return 0;
> +}
> +
> +static const struct wdt_ops sandbox_wdt_ops = {
> +       .start = sandbox_wdt_start,
> +       .reset = sandbox_wdt_reset,
> +       .stop = sandbox_wdt_stop,
> +       .expire_now = sandbox_wdt_expire_now,
> +};
> +
> +static const struct udevice_id sandbox_wdt_ids[] = {
> +       { .compatible = "sandbox,wdt" },
> +       {}
> +};
> +
> +U_BOOT_DRIVER(wdt_sandbox) = {
> +       .name = "wdt_sandbox",
> +       .id = UCLASS_WDT,
> +       .of_match = sandbox_wdt_ids,
> +       .ops = &sandbox_wdt_ops,
> +       .probe = sandbox_wdt_probe,
> +};

[...]

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

* Re: [PATCH v1 03/15] aspeed: Watchdog Timer Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This driver supports ast2500 and ast2400 SoCs.
> Only ast2500 supports reset_mask and thus the option of resettting
> individual peripherals using WDT.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Rename reset to expire_now
> - Rename restart to reset
>
>
> ---
>  arch/arm/include/asm/arch-aspeed/wdt.h |  53 ++++++++++++--
>  arch/arm/mach-aspeed/ast_wdt.c         |  40 ++++++++---
>  drivers/watchdog/Kconfig               |  11 +++
>  drivers/watchdog/Makefile              |   1 +
>  drivers/watchdog/ast_wdt.c             | 125 +++++++++++++++++++++++++++++++++
>  5 files changed, 217 insertions(+), 13 deletions(-)
>  create mode 100644 drivers/watchdog/ast_wdt.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 03/15] aspeed: Watchdog Timer Driver
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This driver supports ast2500 and ast2400 SoCs.
> Only ast2500 supports reset_mask and thus the option of resettting
> individual peripherals using WDT.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Rename reset to expire_now
> - Rename restart to reset
>
>
> ---
>  arch/arm/include/asm/arch-aspeed/wdt.h |  53 ++++++++++++--
>  arch/arm/mach-aspeed/ast_wdt.c         |  40 ++++++++---
>  drivers/watchdog/Kconfig               |  11 +++
>  drivers/watchdog/Makefile              |   1 +
>  drivers/watchdog/ast_wdt.c             | 125 +++++++++++++++++++++++++++++++++
>  5 files changed, 217 insertions(+), 13 deletions(-)
>  create mode 100644 drivers/watchdog/ast_wdt.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Make functions for locking and unlocking SCU part of SCU API.
> Many drivers need to modify settings in SCU and thus need to unlock it
> first. This change makes it possible.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 14 ++++++++++++++
>  arch/arm/mach-aspeed/ast2500/clk_ast2500.c     | 15 +++++++++++++++
>  drivers/clk/aspeed/clk_ast2500.c               | 18 ++----------------
>  3 files changed, 31 insertions(+), 16 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Make functions for locking and unlocking SCU part of SCU API.
> Many drivers need to modify settings in SCU and thus need to unlock it
> first. This change makes it possible.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 14 ++++++++++++++
>  arch/arm/mach-aspeed/ast2500/clk_ast2500.c     | 15 +++++++++++++++
>  drivers/clk/aspeed/clk_ast2500.c               | 18 ++----------------
>  3 files changed, 31 insertions(+), 16 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 05/15] aspeed: Reset Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko
  Cc: U-Boot Mailing List, OpenBMC Maillist, Masahiro Yamada,
	Tom Warren, Albert Aribaud, Stephen Warren

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
> perform resets and thus depends on it. The actual Watchdog device used
> needs to be configured in Device Tree using "aspeed,wdt" property, which
> must be WDT phandle, for example:
>
> rst: reset-controller {
>     compatible = "aspeed,ast2500-reset";
>     aspeed,wdt = <&wdt1>;
> }
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Remove unnecessary check for error in dev_get_priv
> - Fix comment
> - Rename wdt_reset call to wdt_expire_now
>
> ---
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  28 +++++++
>  drivers/reset/Kconfig                          |  10 +++
>  drivers/reset/Makefile                         |   1 +
>  drivers/reset/ast2500-reset.c                  | 106 +++++++++++++++++++++++++
>  4 files changed, 145 insertions(+)
>  create mode 100644 drivers/reset/ast2500-reset.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 05/15] aspeed: Reset Driver
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
> perform resets and thus depends on it. The actual Watchdog device used
> needs to be configured in Device Tree using "aspeed,wdt" property, which
> must be WDT phandle, for example:
>
> rst: reset-controller {
>     compatible = "aspeed,ast2500-reset";
>     aspeed,wdt = <&wdt1>;
> }
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Remove unnecessary check for error in dev_get_priv
> - Fix comment
> - Rename wdt_reset call to wdt_expire_now
>
> ---
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  28 +++++++
>  drivers/reset/Kconfig                          |  10 +++
>  drivers/reset/Makefile                         |   1 +
>  drivers/reset/ast2500-reset.c                  | 106 +++++++++++++++++++++++++
>  4 files changed, 145 insertions(+)
>  create mode 100644 drivers/reset/ast2500-reset.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 06/15] aspeed: Device Tree configuration for Reset Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
> for various reset signals
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/dts/ast2500-evb.dts              | 15 +++++++++++
>  arch/arm/dts/ast2500-u-boot.dtsi          | 10 +++++++
>  include/dt-bindings/reset/ast2500-reset.h | 45 +++++++++++++++++++++++++++++++
>  3 files changed, 70 insertions(+)
>  create mode 100644 include/dt-bindings/reset/ast2500-reset.h

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 06/15] aspeed: Device Tree configuration for Reset Driver
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
> for various reset signals
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/dts/ast2500-evb.dts              | 15 +++++++++++
>  arch/arm/dts/ast2500-u-boot.dtsi          | 10 +++++++
>  include/dt-bindings/reset/ast2500-reset.h | 45 +++++++++++++++++++++++++++++++
>  3 files changed, 70 insertions(+)
>  create mode 100644 include/dt-bindings/reset/ast2500-reset.h

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This change switches all existing users of ast2500 Watchdog to Driver
> Model based Watchdog driver.
>
> To perform system reset Sysreset Driver uses first Watchdog device found
> via uclass_first_device call. Since the system is going to be reset
> anyway it does not make much difference which watchdog is used.
>
> Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
> driver to do that.
>
> These were the only users of the old Watchdog API, so that API is
> removed.
>
> This all is done in one change to avoid having to maintain dual API for
> watchdog in between.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Rename wdt_reset call to wdt_expire_now
>
> ---
>  arch/arm/include/asm/arch-aspeed/wdt.h       | 39 ---------------------
>  arch/arm/mach-aspeed/Kconfig                 |  8 +----
>  arch/arm/mach-aspeed/ast2500/sdram_ast2500.c | 12 +++++--
>  arch/arm/mach-aspeed/ast_wdt.c               | 51 ----------------------------
>  configs/evb-ast2500_defconfig                |  2 ++
>  drivers/sysreset/sysreset_ast.c              | 24 ++++++-------
>  6 files changed, 24 insertions(+), 112 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This change switches all existing users of ast2500 Watchdog to Driver
> Model based Watchdog driver.
>
> To perform system reset Sysreset Driver uses first Watchdog device found
> via uclass_first_device call. Since the system is going to be reset
> anyway it does not make much difference which watchdog is used.
>
> Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
> driver to do that.
>
> These were the only users of the old Watchdog API, so that API is
> removed.
>
> This all is done in one change to avoid having to maintain dual API for
> watchdog in between.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Rename wdt_reset call to wdt_expire_now
>
> ---
>  arch/arm/include/asm/arch-aspeed/wdt.h       | 39 ---------------------
>  arch/arm/mach-aspeed/Kconfig                 |  8 +----
>  arch/arm/mach-aspeed/ast2500/sdram_ast2500.c | 12 +++++--
>  arch/arm/mach-aspeed/ast_wdt.c               | 51 ----------------------------
>  configs/evb-ast2500_defconfig                |  2 ++
>  drivers/sysreset/sysreset_ast.c              | 24 ++++++-------
>  6 files changed, 24 insertions(+), 112 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 08/15] aspeed: AST2500 Pinctrl Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko
  Cc: U-Boot Mailing List, OpenBMC Maillist, Konstantin Porotchkin,
	Thomas Abraham, Wills Wang, Kever Yang, Albert Aribaud,
	Beniamino Galvani, Heiko Stübner, Minkyu Kang,
	Daniel Schwierzeck, Wenyou Yang

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This driver uses Generic Pinctrl framework and is compatible with
> the Linux driver for ast2500: it uses the same device tree
> configuration.
>
> Not all pins are supported by the driver at the moment, so it actually
> compatible with ast2400. In general, however, there are differences that
> in the future would be easier to maintain separately.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++++++++++
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  19 ++++
>  drivers/pinctrl/Kconfig                        |   9 ++
>  drivers/pinctrl/Makefile                       |   1 +
>  drivers/pinctrl/aspeed/Makefile                |   1 +
>  drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 +++++++++++++++++++++++++
>  6 files changed, 209 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
>  create mode 100644 drivers/pinctrl/aspeed/Makefile
>  create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 08/15] aspeed: AST2500 Pinctrl Driver
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> This driver uses Generic Pinctrl framework and is compatible with
> the Linux driver for ast2500: it uses the same device tree
> configuration.
>
> Not all pins are supported by the driver at the moment, so it actually
> compatible with ast2400. In general, however, there are differences that
> in the future would be easier to maintain separately.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++++++++++
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  19 ++++
>  drivers/pinctrl/Kconfig                        |   9 ++
>  drivers/pinctrl/Makefile                       |   1 +
>  drivers/pinctrl/aspeed/Makefile                |   1 +
>  drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 +++++++++++++++++++++++++
>  6 files changed, 209 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
>  create mode 100644 drivers/pinctrl/aspeed/Makefile
>  create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Enable Pinctrl Driver in AST2500 Eval Board's defconfig
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  configs/evb-ast2500_defconfig | 1 +
>  1 file changed, 1 insertion(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Enable Pinctrl Driver in AST2500 Eval Board's defconfig
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  configs/evb-ast2500_defconfig | 1 +
>  1 file changed, 1 insertion(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:11     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add P-Bus Clock support to ast2500 clock driver.
> This is the clock used by I2C devices.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  3 ++-
>  drivers/clk/aspeed/clk_ast2500.c               | 11 +++++++++++
>  2 files changed, 13 insertions(+), 1 deletion(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

> diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
> index 1cdd3b9198..319d75e05c 100644
> --- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
> +++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
> @@ -21,7 +21,8 @@
>  #define SCU_MPLL_NUM_MASK              0xff
>  #define SCU_MPLL_POST_SHIFT            13
>  #define SCU_MPLL_POST_MASK             0x3f

I think it works better in general if the mask is defined as 0x3f <<
SCU_MPLL_POST_SHIFT. Something to think about as a possible clean-up.

> -
> +#define SCU_PCLK_DIV_SHIFT             23
> +#define SCU_PCLK_DIV_MASK              7
>  #define SCU_HPLL_DENUM_SHIFT           0
>  #define SCU_HPLL_DENUM_MASK            0x1f
>  #define SCU_HPLL_NUM_SHIFT             5
> diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
> index 504731271c..9e4c66ea85 100644
> --- a/drivers/clk/aspeed/clk_ast2500.c
> +++ b/drivers/clk/aspeed/clk_ast2500.c
> @@ -110,6 +110,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
>                 rate = ast2500_get_mpll_rate(clkin,
>                                              readl(&priv->scu->m_pll_param));
>                 break;
> +       case BCLK_PCLK:
> +               {
> +                       ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
> +                                                 >> SCU_PCLK_DIV_SHIFT) &
> +                                                SCU_PCLK_DIV_MASK);
> +                       rate = ast2500_get_hpll_rate(clkin,
> +                                                    readl(&priv->scu->
> +                                                          h_pll_param));
> +                       rate = rate / apb_div;
> +               }
> +               break;
>         case PCLK_UART1:
>                 rate = ast2500_get_uart_clk_rate(priv->scu, 1);
>                 break;
> --
> 2.12.2.762.g0e3151a226-goog
>

Regards,
Simon

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

* [U-Boot] [PATCH v1 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
@ 2017-04-19  0:11     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:11 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add P-Bus Clock support to ast2500 clock driver.
> This is the clock used by I2C devices.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  3 ++-
>  drivers/clk/aspeed/clk_ast2500.c               | 11 +++++++++++
>  2 files changed, 13 insertions(+), 1 deletion(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

> diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
> index 1cdd3b9198..319d75e05c 100644
> --- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
> +++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
> @@ -21,7 +21,8 @@
>  #define SCU_MPLL_NUM_MASK              0xff
>  #define SCU_MPLL_POST_SHIFT            13
>  #define SCU_MPLL_POST_MASK             0x3f

I think it works better in general if the mask is defined as 0x3f <<
SCU_MPLL_POST_SHIFT. Something to think about as a possible clean-up.

> -
> +#define SCU_PCLK_DIV_SHIFT             23
> +#define SCU_PCLK_DIV_MASK              7
>  #define SCU_HPLL_DENUM_SHIFT           0
>  #define SCU_HPLL_DENUM_MASK            0x1f
>  #define SCU_HPLL_NUM_SHIFT             5
> diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
> index 504731271c..9e4c66ea85 100644
> --- a/drivers/clk/aspeed/clk_ast2500.c
> +++ b/drivers/clk/aspeed/clk_ast2500.c
> @@ -110,6 +110,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
>                 rate = ast2500_get_mpll_rate(clkin,
>                                              readl(&priv->scu->m_pll_param));
>                 break;
> +       case BCLK_PCLK:
> +               {
> +                       ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
> +                                                 >> SCU_PCLK_DIV_SHIFT) &
> +                                                SCU_PCLK_DIV_MASK);
> +                       rate = ast2500_get_hpll_rate(clkin,
> +                                                    readl(&priv->scu->
> +                                                          h_pll_param));
> +                       rate = rate / apb_div;
> +               }
> +               break;
>         case PCLK_UART1:
>                 rate = ast2500_get_uart_clk_rate(priv->scu, 1);
>                 break;
> --
> 2.12.2.762.g0e3151a226-goog
>

Regards,
Simon

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

* Re: [PATCH v1 11/15] aspeed: Add I2C Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:12     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Heiko Schocher

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> The driver is very limited, it only supports master mode and
> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Style fixes
>
>
> ---
>  drivers/i2c/Kconfig   |   9 ++
>  drivers/i2c/Makefile  |   1 +
>  drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>  4 files changed, 499 insertions(+)
>  create mode 100644 drivers/i2c/ast_i2c.c
>  create mode 100644 drivers/i2c/ast_i2c.h

Reviewed-by: Simon Glass <sjg@chromium.org>

nit below

[..]
> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
> +       int ret;
> +
> +       priv->regs = dev_get_addr_ptr(dev);
> +       if (IS_ERR(priv->regs))
> +               return PTR_ERR(priv->regs);

Should be

 if (!priv->regs)

I think

> +
> +       ret = clk_get_by_index(dev, 0, &priv->clk);
> +       if (ret < 0) {
> +               debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
> +                     ret);
> +               return ret;

Regards,
Simon

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

* [U-Boot] [PATCH v1 11/15] aspeed: Add I2C Driver
@ 2017-04-19  0:12     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> The driver is very limited, it only supports master mode and
> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Style fixes
>
>
> ---
>  drivers/i2c/Kconfig   |   9 ++
>  drivers/i2c/Makefile  |   1 +
>  drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>  4 files changed, 499 insertions(+)
>  create mode 100644 drivers/i2c/ast_i2c.c
>  create mode 100644 drivers/i2c/ast_i2c.h

Reviewed-by: Simon Glass <sjg@chromium.org>

nit below

[..]
> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
> +       int ret;
> +
> +       priv->regs = dev_get_addr_ptr(dev);
> +       if (IS_ERR(priv->regs))
> +               return PTR_ERR(priv->regs);

Should be

 if (!priv->regs)

I think

> +
> +       ret = clk_get_by_index(dev, 0, &priv->clk);
> +       if (ret < 0) {
> +               debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
> +                     ret);
> +               return ret;

Regards,
Simon

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

* Re: [PATCH v1 12/15] aspeed: Enable I2C in EVB defconfig
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:12     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Enable I2C driver in ast2500 Eval Board defconfig.
> Also enable i2c command.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  configs/evb-ast2500_defconfig | 3 +++
>  1 file changed, 3 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 12/15] aspeed: Enable I2C in EVB defconfig
@ 2017-04-19  0:12     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Enable I2C driver in ast2500 Eval Board defconfig.
> Also enable i2c command.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  configs/evb-ast2500_defconfig | 3 +++
>  1 file changed, 3 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 13/15] aspeed: Add support for Clocks needed by MACs
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:12     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add support for clocks needed by MACs to ast2500 clock driver.
> The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
> PCLK_MAC2 for MAC1 and MAC2 respectively.
>
> The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
> SDK. It is not entirely clear from the datasheet how this clock is used
> by MACs, so not clear if the rate would ever need to be different. So,
> for now, hardcoding it is probably safer.
>
> The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
> hardware strapping.
>
> So, the network driver would only need to enable these clocks, no need
> to configure the rate.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/dts/ast2500-u-boot.dtsi               |   8 +
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  62 +++++-
>  drivers/clk/aspeed/clk_ast2500.c               | 265 ++++++++++++++++++++++---
>  include/dt-bindings/clock/ast2500-scu.h        |   2 +
>  4 files changed, 304 insertions(+), 33 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

Wow that 10ms delay is pretty unfortunate!

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

* [U-Boot] [PATCH v1 13/15] aspeed: Add support for Clocks needed by MACs
@ 2017-04-19  0:12     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Add support for clocks needed by MACs to ast2500 clock driver.
> The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
> PCLK_MAC2 for MAC1 and MAC2 respectively.
>
> The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
> SDK. It is not entirely clear from the datasheet how this clock is used
> by MACs, so not clear if the rate would ever need to be different. So,
> for now, hardcoding it is probably safer.
>
> The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
> hardware strapping.
>
> So, the network driver would only need to enable these clocks, no need
> to configure the rate.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/dts/ast2500-u-boot.dtsi               |   8 +
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  62 +++++-
>  drivers/clk/aspeed/clk_ast2500.c               | 265 ++++++++++++++++++++++---
>  include/dt-bindings/clock/ast2500-scu.h        |   2 +
>  4 files changed, 304 insertions(+), 33 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

Wow that 10ms delay is pretty unfortunate!

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

* Re: [PATCH v1 14/15] aspeed: Refactor SCU to use consistent mask & shift
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:12     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Refactor SCU header to use consistent Mask & Shift values.
> Now, consistently, to read value from SCU register, mask needs
> to be applied before shift.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 12 ++++----
>  arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  5 ++--
>  drivers/clk/aspeed/clk_ast2500.c               | 39 +++++++++++++-------------
>  3 files changed, 27 insertions(+), 29 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

OK, so ignore my earlier comment about shift/mask.

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

* [U-Boot] [PATCH v1 14/15] aspeed: Refactor SCU to use consistent mask & shift
@ 2017-04-19  0:12     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Refactor SCU header to use consistent Mask & Shift values.
> Now, consistently, to read value from SCU register, mask needs
> to be applied before shift.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> ---
>
> Changes in v1: None
>
>  arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 12 ++++----
>  arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  5 ++--
>  drivers/clk/aspeed/clk_ast2500.c               | 39 +++++++++++++-------------
>  3 files changed, 27 insertions(+), 29 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

OK, so ignore my earlier comment about shift/mask.

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

* Re: [PATCH v1 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19  0:12     ` Simon Glass
  -1 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: U-Boot Mailing List, OpenBMC Maillist, Albert Aribaud

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Remove unnecessary apb and ahb nodes and just override necessary
> nodes/values.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1: None
>
>
> ---
>  arch/arm/dts/ast2500-u-boot.dtsi | 41 ++++++++++++++++++++--------------------
>  1 file changed, 21 insertions(+), 20 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v1 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
@ 2017-04-19  0:12     ` Simon Glass
  0 siblings, 0 replies; 132+ messages in thread
From: Simon Glass @ 2017-04-19  0:12 UTC (permalink / raw)
  To: u-boot

On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> Remove unnecessary apb and ahb nodes and just override necessary
> nodes/values.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1: None
>
>
> ---
>  arch/arm/dts/ast2500-u-boot.dtsi | 41 ++++++++++++++++++++--------------------
>  1 file changed, 21 insertions(+), 20 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v1 11/15] aspeed: Add I2C Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-04-19 11:58     ` Heiko Schocher
  -1 siblings, 0 replies; 132+ messages in thread
From: Heiko Schocher @ 2017-04-19 11:58 UTC (permalink / raw)
  To: Maxim Sloyko, Simon Glass; +Cc: u-boot, openbmc

Hello Maxim,

Am 17.04.2017 um 21:00 schrieb Maxim Sloyko:
> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> The driver is very limited, it only supports master mode and
> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Style fixes
>
>
> ---
>   drivers/i2c/Kconfig   |   9 ++
>   drivers/i2c/Makefile  |   1 +
>   drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>   4 files changed, 499 insertions(+)
>   create mode 100644 drivers/i2c/ast_i2c.c
>   create mode 100644 drivers/i2c/ast_i2c.h

Is this "version 2" from the patch you posted in march?

Acked-by: Heiko Schocher <hs@denx.de>

bye,
Heiko
>
> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
> index 39f62daf5d..e661a308b0 100644
> --- a/drivers/i2c/Kconfig
> +++ b/drivers/i2c/Kconfig
> @@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>   	  enable status register. This config option can be enabled in such
>   	  cases.
>
> +config SYS_I2C_ASPEED
> +	bool "Aspeed I2C Controller"
> +	depends on DM_I2C && ARCH_ASPEED
> +	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
> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> index 7c86198863..229fd476db 100644
> --- a/drivers/i2c/Makefile
> +++ b/drivers/i2c/Makefile
> @@ -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_ASPEED) += ast_i2c.o
>   obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>   obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>   obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
> diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
> new file mode 100644
> index 0000000000..16dfb57066
> --- /dev/null
> +++ b/drivers/i2c/ast_i2c.c
> @@ -0,0 +1,357 @@
> +/*
> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
> + * Copyright 2016 IBM Corporation
> + * Copyright 2017 Google, Inc.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <fdtdec.h>
> +#include <i2c.h>
> +#include <asm/io.h>
> +#include <asm/arch/scu_ast2500.h>
> +
> +#include "ast_i2c.h"
> +
> +#define I2C_TIMEOUT_US 100000
> +#define I2C_SLEEP_STEP_US 20
> +
> +#define HIGHSPEED_TTIMEOUT		3
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/*
> + * Device private data
> + */
> +struct ast_i2c_priv {
> +	/* This device's clock */
> +	struct clk clk;
> +	/* 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)
> +			| (div << I2CD_BASE_DIV_SHIFT);
> +
> +	return data;
> +}
> +
> +static void ast_i2c_clear_interrupts(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	writel(~0, &priv->regs->isr);
> +}
> +
> +static void ast_i2c_init_bus(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	/* Reset device */
> +	writel(0, &priv->regs->fcr);
> +	/* Enable Master Mode. Assuming single-master */
> +	writel(I2CD_MASTER_EN
> +	       | I2CD_M_SDA_LOCK_EN
> +	       | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
> +	       &priv->regs->fcr);
> +	/* Enable Interrupts */
> +	writel(I2CD_INTR_TX_ACK
> +	       | I2CD_INTR_TX_NAK
> +	       | I2CD_INTR_RX_DONE
> +	       | I2CD_INTR_BUS_RECOVER_DONE
> +	       | I2CD_INTR_NORMAL_STOP
> +	       | I2CD_INTR_ABNORMAL, &priv->regs->icr);
> +}
> +
> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	priv->regs = dev_get_addr_ptr(dev);
> +	if (IS_ERR(priv->regs))
> +		return PTR_ERR(priv->regs);
> +
> +	ret = clk_get_by_index(dev, 0, &priv->clk);
> +	if (ret < 0) {
> +		debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
> +		      ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_probe(struct udevice *dev)
> +{
> +	struct ast2500_scu *scu;
> +
> +	debug("Enabling I2C%u\n", dev->seq);
> +
> +	/*
> +	 * Get all I2C devices out of Reset.
> +	 * Only needs to be done once, but doing it for every
> +	 * device does not hurt.
> +	 */
> +	scu = ast_get_scu();
> +	ast_scu_unlock(scu);
> +	clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
> +	ast_scu_lock(scu);
> +
> +	ast_i2c_init_bus(dev);
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int timeout = I2C_TIMEOUT_US;
> +
> +	while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
> +		udelay(I2C_SLEEP_STEP_US);
> +		timeout -= I2C_SLEEP_STEP_US;
> +	}
> +
> +	ast_i2c_clear_interrupts(dev);
> +	if (timeout <= 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_send_stop(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	writel(I2CD_M_STOP_CMD, &priv->regs->csr);
> +
> +	return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
> +}
> +
> +static int ast_i2c_wait_tx(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int timeout = I2C_TIMEOUT_US;
> +	u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
> +	u32 status = readl(&priv->regs->isr) & flag;
> +	int ret = 0;
> +
> +	while (!status && timeout > 0) {
> +		status = readl(&priv->regs->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(dev);
> +
> +	return ret;
> +}
> +
> +static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	/* Start and Send Device Address */
> +	writel(devaddr, &priv->regs->trbbr);
> +	writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
> +
> +	return ast_i2c_wait_tx(dev);
> +}
> +
> +static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8 *buffer,
> +			     size_t len, bool send_stop)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	u32 i2c_cmd = I2CD_M_RX_CMD;
> +	int ret;
> +
> +	ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
> +	if (ret < 0)
> +		return ret;
> +
> +	for (; len > 0; len--, buffer++) {
> +		if (len == 1)
> +			i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
> +		writel(i2c_cmd, &priv->regs->csr);
> +		ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
> +		if (ret < 0)
> +			return ret;
> +		*buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
> +				>> I2CD_RX_DATA_SHIFT;
> +	}
> +	ast_i2c_clear_interrupts(dev);
> +
> +	if (send_stop)
> +		return ast_i2c_send_stop(dev);
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
> +			      *buffer, size_t len, bool send_stop)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = ast_i2c_start_txn(dev, (chip_addr << 1));
> +	if (ret < 0)
> +		return ret;
> +
> +	for (; len > 0; len--, buffer++) {
> +		writel(*buffer, &priv->regs->trbbr);
> +		writel(I2CD_M_TX_CMD, &priv->regs->csr);
> +		ret = ast_i2c_wait_tx(dev);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	if (send_stop)
> +		return ast_i2c_send_stop(dev);
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_deblock(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	struct ast_i2c_regs *regs = priv->regs;
> +	u32 csr = readl(&regs->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(dev);
> +	} else if (scl_high) {
> +		/* Possibly stuck slave */
> +		debug("Bus stuck (%x), attempting recovery\n", csr);
> +		writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
> +		ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
> +	} else {
> +		/* Just try to reinit the device. */
> +		ast_i2c_init_bus(dev);
> +	}
> +
> +	return ret;
> +}
> +
> +static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
> +{
> +	int ret;
> +
> +	ret = ast_i2c_deblock(dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
> +	struct ast_i2c_regs *regs = priv->regs;
> +	ulong i2c_rate, divider;
> +
> +	debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
> +	if (!speed) {
> +		debug("No valid speed specified\n");
> +		return -EINVAL;
> +	}
> +
> +	i2c_rate = clk_get_rate(&priv->clk);
> +	divider = i2c_rate / speed;
> +
> +	priv->speed = speed;
> +	if (speed > I2C_HIGHSPEED_RATE) {
> +		debug("Enable High Speed\n");
> +		setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
> +			     | I2CD_M_SDA_DRIVE_1T_EN
> +			     | I2CD_SDA_DRIVE_1T_EN);
> +		writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
> +	} else {
> +		debug("Enabling Normal Speed\n");
> +		writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
> +	}
> +
> +	writel(get_clk_reg_val(divider), &regs->cactcr1);
> +	ast_i2c_clear_interrupts(dev);
> +
> +	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-bus" },
> +	{ .compatible = "aspeed,ast2500-i2c-bus" },
> +	{ },
> +};
> +
> +U_BOOT_DRIVER(ast_i2c) = {
> +	.name = "ast_i2c",
> +	.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_priv),
> +	.ops = &ast_i2c_ops,
> +};
> diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
> new file mode 100644
> index 0000000000..e5dec7a480
> --- /dev/null
> +++ b/drivers/i2c/ast_i2c.h
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
> + * Copyright 2016 IBM Corporation
> + * Copyright 2017 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_ASPEED_AST2500
> +	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)
> +
> +#define I2C_HIGHSPEED_RATE    400000
> +
> +#endif				/* __AST_I2C_H_ */
>

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

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

* [U-Boot] [PATCH v1 11/15] aspeed: Add I2C Driver
@ 2017-04-19 11:58     ` Heiko Schocher
  0 siblings, 0 replies; 132+ messages in thread
From: Heiko Schocher @ 2017-04-19 11:58 UTC (permalink / raw)
  To: u-boot

Hello Maxim,

Am 17.04.2017 um 21:00 schrieb Maxim Sloyko:
> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> The driver is very limited, it only supports master mode and
> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>
> Signed-off-by: Maxim Sloyko <maxims@google.com>
>
> ---
>
> Changes in v1:
> - Style fixes
>
>
> ---
>   drivers/i2c/Kconfig   |   9 ++
>   drivers/i2c/Makefile  |   1 +
>   drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>   4 files changed, 499 insertions(+)
>   create mode 100644 drivers/i2c/ast_i2c.c
>   create mode 100644 drivers/i2c/ast_i2c.h

Is this "version 2" from the patch you posted in march?

Acked-by: Heiko Schocher <hs@denx.de>

bye,
Heiko
>
> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
> index 39f62daf5d..e661a308b0 100644
> --- a/drivers/i2c/Kconfig
> +++ b/drivers/i2c/Kconfig
> @@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>   	  enable status register. This config option can be enabled in such
>   	  cases.
>
> +config SYS_I2C_ASPEED
> +	bool "Aspeed I2C Controller"
> +	depends on DM_I2C && ARCH_ASPEED
> +	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
> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> index 7c86198863..229fd476db 100644
> --- a/drivers/i2c/Makefile
> +++ b/drivers/i2c/Makefile
> @@ -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_ASPEED) += ast_i2c.o
>   obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>   obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>   obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
> diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
> new file mode 100644
> index 0000000000..16dfb57066
> --- /dev/null
> +++ b/drivers/i2c/ast_i2c.c
> @@ -0,0 +1,357 @@
> +/*
> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
> + * Copyright 2016 IBM Corporation
> + * Copyright 2017 Google, Inc.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <fdtdec.h>
> +#include <i2c.h>
> +#include <asm/io.h>
> +#include <asm/arch/scu_ast2500.h>
> +
> +#include "ast_i2c.h"
> +
> +#define I2C_TIMEOUT_US 100000
> +#define I2C_SLEEP_STEP_US 20
> +
> +#define HIGHSPEED_TTIMEOUT		3
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/*
> + * Device private data
> + */
> +struct ast_i2c_priv {
> +	/* This device's clock */
> +	struct clk clk;
> +	/* 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)
> +			| (div << I2CD_BASE_DIV_SHIFT);
> +
> +	return data;
> +}
> +
> +static void ast_i2c_clear_interrupts(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	writel(~0, &priv->regs->isr);
> +}
> +
> +static void ast_i2c_init_bus(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	/* Reset device */
> +	writel(0, &priv->regs->fcr);
> +	/* Enable Master Mode. Assuming single-master */
> +	writel(I2CD_MASTER_EN
> +	       | I2CD_M_SDA_LOCK_EN
> +	       | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
> +	       &priv->regs->fcr);
> +	/* Enable Interrupts */
> +	writel(I2CD_INTR_TX_ACK
> +	       | I2CD_INTR_TX_NAK
> +	       | I2CD_INTR_RX_DONE
> +	       | I2CD_INTR_BUS_RECOVER_DONE
> +	       | I2CD_INTR_NORMAL_STOP
> +	       | I2CD_INTR_ABNORMAL, &priv->regs->icr);
> +}
> +
> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	priv->regs = dev_get_addr_ptr(dev);
> +	if (IS_ERR(priv->regs))
> +		return PTR_ERR(priv->regs);
> +
> +	ret = clk_get_by_index(dev, 0, &priv->clk);
> +	if (ret < 0) {
> +		debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
> +		      ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_probe(struct udevice *dev)
> +{
> +	struct ast2500_scu *scu;
> +
> +	debug("Enabling I2C%u\n", dev->seq);
> +
> +	/*
> +	 * Get all I2C devices out of Reset.
> +	 * Only needs to be done once, but doing it for every
> +	 * device does not hurt.
> +	 */
> +	scu = ast_get_scu();
> +	ast_scu_unlock(scu);
> +	clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
> +	ast_scu_lock(scu);
> +
> +	ast_i2c_init_bus(dev);
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int timeout = I2C_TIMEOUT_US;
> +
> +	while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
> +		udelay(I2C_SLEEP_STEP_US);
> +		timeout -= I2C_SLEEP_STEP_US;
> +	}
> +
> +	ast_i2c_clear_interrupts(dev);
> +	if (timeout <= 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_send_stop(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	writel(I2CD_M_STOP_CMD, &priv->regs->csr);
> +
> +	return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
> +}
> +
> +static int ast_i2c_wait_tx(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int timeout = I2C_TIMEOUT_US;
> +	u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
> +	u32 status = readl(&priv->regs->isr) & flag;
> +	int ret = 0;
> +
> +	while (!status && timeout > 0) {
> +		status = readl(&priv->regs->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(dev);
> +
> +	return ret;
> +}
> +
> +static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +
> +	/* Start and Send Device Address */
> +	writel(devaddr, &priv->regs->trbbr);
> +	writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
> +
> +	return ast_i2c_wait_tx(dev);
> +}
> +
> +static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8 *buffer,
> +			     size_t len, bool send_stop)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	u32 i2c_cmd = I2CD_M_RX_CMD;
> +	int ret;
> +
> +	ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
> +	if (ret < 0)
> +		return ret;
> +
> +	for (; len > 0; len--, buffer++) {
> +		if (len == 1)
> +			i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
> +		writel(i2c_cmd, &priv->regs->csr);
> +		ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
> +		if (ret < 0)
> +			return ret;
> +		*buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
> +				>> I2CD_RX_DATA_SHIFT;
> +	}
> +	ast_i2c_clear_interrupts(dev);
> +
> +	if (send_stop)
> +		return ast_i2c_send_stop(dev);
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
> +			      *buffer, size_t len, bool send_stop)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = ast_i2c_start_txn(dev, (chip_addr << 1));
> +	if (ret < 0)
> +		return ret;
> +
> +	for (; len > 0; len--, buffer++) {
> +		writel(*buffer, &priv->regs->trbbr);
> +		writel(I2CD_M_TX_CMD, &priv->regs->csr);
> +		ret = ast_i2c_wait_tx(dev);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	if (send_stop)
> +		return ast_i2c_send_stop(dev);
> +
> +	return 0;
> +}
> +
> +static int ast_i2c_deblock(struct udevice *dev)
> +{
> +	struct ast_i2c_priv *priv = dev_get_priv(dev);
> +	struct ast_i2c_regs *regs = priv->regs;
> +	u32 csr = readl(&regs->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(dev);
> +	} else if (scl_high) {
> +		/* Possibly stuck slave */
> +		debug("Bus stuck (%x), attempting recovery\n", csr);
> +		writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
> +		ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
> +	} else {
> +		/* Just try to reinit the device. */
> +		ast_i2c_init_bus(dev);
> +	}
> +
> +	return ret;
> +}
> +
> +static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
> +{
> +	int ret;
> +
> +	ret = ast_i2c_deblock(dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
> +	struct ast_i2c_regs *regs = priv->regs;
> +	ulong i2c_rate, divider;
> +
> +	debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
> +	if (!speed) {
> +		debug("No valid speed specified\n");
> +		return -EINVAL;
> +	}
> +
> +	i2c_rate = clk_get_rate(&priv->clk);
> +	divider = i2c_rate / speed;
> +
> +	priv->speed = speed;
> +	if (speed > I2C_HIGHSPEED_RATE) {
> +		debug("Enable High Speed\n");
> +		setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
> +			     | I2CD_M_SDA_DRIVE_1T_EN
> +			     | I2CD_SDA_DRIVE_1T_EN);
> +		writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
> +	} else {
> +		debug("Enabling Normal Speed\n");
> +		writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
> +	}
> +
> +	writel(get_clk_reg_val(divider), &regs->cactcr1);
> +	ast_i2c_clear_interrupts(dev);
> +
> +	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-bus" },
> +	{ .compatible = "aspeed,ast2500-i2c-bus" },
> +	{ },
> +};
> +
> +U_BOOT_DRIVER(ast_i2c) = {
> +	.name = "ast_i2c",
> +	.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_priv),
> +	.ops = &ast_i2c_ops,
> +};
> diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
> new file mode 100644
> index 0000000000..e5dec7a480
> --- /dev/null
> +++ b/drivers/i2c/ast_i2c.h
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
> + * Copyright 2016 IBM Corporation
> + * Copyright 2017 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_ASPEED_AST2500
> +	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)
> +
> +#define I2C_HIGHSPEED_RATE    400000
> +
> +#endif				/* __AST_I2C_H_ */
>

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

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

* Re: [PATCH v1 11/15] aspeed: Add I2C Driver
  2017-04-19 11:58     ` [U-Boot] " Heiko Schocher
@ 2017-04-19 16:02       ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-19 16:02 UTC (permalink / raw)
  To: Heiko Schocher; +Cc: Simon Glass, U-Boot Mailing List, OpenBMC Maillist

On Wed, Apr 19, 2017 at 4:58 AM, Heiko Schocher <hs@denx.de> wrote:
> Hello Maxim,
>
> Am 17.04.2017 um 21:00 schrieb Maxim Sloyko:
>>
>> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
>> The driver is very limited, it only supports master mode and
>> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>>
>> Signed-off-by: Maxim Sloyko <maxims@google.com>
>>
>> ---
>>
>> Changes in v1:
>> - Style fixes
>>
>>
>> ---
>>   drivers/i2c/Kconfig   |   9 ++
>>   drivers/i2c/Makefile  |   1 +
>>   drivers/i2c/ast_i2c.c | 357
>> ++++++++++++++++++++++++++++++++++++++++++++++++++
>>   drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>>   4 files changed, 499 insertions(+)
>>   create mode 100644 drivers/i2c/ast_i2c.c
>>   create mode 100644 drivers/i2c/ast_i2c.h
>
>
> Is this "version 2" from the patch you posted in march?

Yes, sorry, I think I forgot to add proper "In-Reply-To" header.

>
> Acked-by: Heiko Schocher <hs@denx.de>
>
> bye,
> Heiko
>
>>
>> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
>> index 39f62daf5d..e661a308b0 100644
>> --- a/drivers/i2c/Kconfig
>> +++ b/drivers/i2c/Kconfig
>> @@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>>           enable status register. This config option can be enabled in
>> such
>>           cases.
>>
>> +config SYS_I2C_ASPEED
>> +       bool "Aspeed I2C Controller"
>> +       depends on DM_I2C && ARCH_ASPEED
>> +       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
>> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
>> index 7c86198863..229fd476db 100644
>> --- a/drivers/i2c/Makefile
>> +++ b/drivers/i2c/Makefile
>> @@ -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_ASPEED) += ast_i2c.o
>>   obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>>   obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>>   obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>> diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
>> new file mode 100644
>> index 0000000000..16dfb57066
>> --- /dev/null
>> +++ b/drivers/i2c/ast_i2c.c
>> @@ -0,0 +1,357 @@
>> +/*
>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>> + * Copyright 2016 IBM Corporation
>> + * Copyright 2017 Google, Inc.
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <errno.h>
>> +#include <fdtdec.h>
>> +#include <i2c.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/scu_ast2500.h>
>> +
>> +#include "ast_i2c.h"
>> +
>> +#define I2C_TIMEOUT_US 100000
>> +#define I2C_SLEEP_STEP_US 20
>> +
>> +#define HIGHSPEED_TTIMEOUT             3
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +/*
>> + * Device private data
>> + */
>> +struct ast_i2c_priv {
>> +       /* This device's clock */
>> +       struct clk clk;
>> +       /* 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)
>> +                       | (div << I2CD_BASE_DIV_SHIFT);
>> +
>> +       return data;
>> +}
>> +
>> +static void ast_i2c_clear_interrupts(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       writel(~0, &priv->regs->isr);
>> +}
>> +
>> +static void ast_i2c_init_bus(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       /* Reset device */
>> +       writel(0, &priv->regs->fcr);
>> +       /* Enable Master Mode. Assuming single-master */
>> +       writel(I2CD_MASTER_EN
>> +              | I2CD_M_SDA_LOCK_EN
>> +              | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
>> +              &priv->regs->fcr);
>> +       /* Enable Interrupts */
>> +       writel(I2CD_INTR_TX_ACK
>> +              | I2CD_INTR_TX_NAK
>> +              | I2CD_INTR_RX_DONE
>> +              | I2CD_INTR_BUS_RECOVER_DONE
>> +              | I2CD_INTR_NORMAL_STOP
>> +              | I2CD_INTR_ABNORMAL, &priv->regs->icr);
>> +}
>> +
>> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int ret;
>> +
>> +       priv->regs = dev_get_addr_ptr(dev);
>> +       if (IS_ERR(priv->regs))
>> +               return PTR_ERR(priv->regs);
>> +
>> +       ret = clk_get_by_index(dev, 0, &priv->clk);
>> +       if (ret < 0) {
>> +               debug("%s: Can't get clock for %s: %d\n", __func__,
>> dev->name,
>> +                     ret);
>> +               return ret;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_probe(struct udevice *dev)
>> +{
>> +       struct ast2500_scu *scu;
>> +
>> +       debug("Enabling I2C%u\n", dev->seq);
>> +
>> +       /*
>> +        * Get all I2C devices out of Reset.
>> +        * Only needs to be done once, but doing it for every
>> +        * device does not hurt.
>> +        */
>> +       scu = ast_get_scu();
>> +       ast_scu_unlock(scu);
>> +       clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
>> +       ast_scu_lock(scu);
>> +
>> +       ast_i2c_init_bus(dev);
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int timeout = I2C_TIMEOUT_US;
>> +
>> +       while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
>> +               udelay(I2C_SLEEP_STEP_US);
>> +               timeout -= I2C_SLEEP_STEP_US;
>> +       }
>> +
>> +       ast_i2c_clear_interrupts(dev);
>> +       if (timeout <= 0)
>> +               return -ETIMEDOUT;
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_send_stop(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       writel(I2CD_M_STOP_CMD, &priv->regs->csr);
>> +
>> +       return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
>> +}
>> +
>> +static int ast_i2c_wait_tx(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int timeout = I2C_TIMEOUT_US;
>> +       u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
>> +       u32 status = readl(&priv->regs->isr) & flag;
>> +       int ret = 0;
>> +
>> +       while (!status && timeout > 0) {
>> +               status = readl(&priv->regs->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(dev);
>> +
>> +       return ret;
>> +}
>> +
>> +static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       /* Start and Send Device Address */
>> +       writel(devaddr, &priv->regs->trbbr);
>> +       writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
>> +
>> +       return ast_i2c_wait_tx(dev);
>> +}
>> +
>> +static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8
>> *buffer,
>> +                            size_t len, bool send_stop)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       u32 i2c_cmd = I2CD_M_RX_CMD;
>> +       int ret;
>> +
>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       for (; len > 0; len--, buffer++) {
>> +               if (len == 1)
>> +                       i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
>> +               writel(i2c_cmd, &priv->regs->csr);
>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
>> +               if (ret < 0)
>> +                       return ret;
>> +               *buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
>> +                               >> I2CD_RX_DATA_SHIFT;
>> +       }
>> +       ast_i2c_clear_interrupts(dev);
>> +
>> +       if (send_stop)
>> +               return ast_i2c_send_stop(dev);
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
>> +                             *buffer, size_t len, bool send_stop)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int ret;
>> +
>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1));
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       for (; len > 0; len--, buffer++) {
>> +               writel(*buffer, &priv->regs->trbbr);
>> +               writel(I2CD_M_TX_CMD, &priv->regs->csr);
>> +               ret = ast_i2c_wait_tx(dev);
>> +               if (ret < 0)
>> +                       return ret;
>> +       }
>> +
>> +       if (send_stop)
>> +               return ast_i2c_send_stop(dev);
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_deblock(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       struct ast_i2c_regs *regs = priv->regs;
>> +       u32 csr = readl(&regs->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(dev);
>> +       } else if (scl_high) {
>> +               /* Possibly stuck slave */
>> +               debug("Bus stuck (%x), attempting recovery\n", csr);
>> +               writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
>> +       } else {
>> +               /* Just try to reinit the device. */
>> +               ast_i2c_init_bus(dev);
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int
>> nmsgs)
>> +{
>> +       int ret;
>> +
>> +       ret = ast_i2c_deblock(dev);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
>> +       struct ast_i2c_regs *regs = priv->regs;
>> +       ulong i2c_rate, divider;
>> +
>> +       debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
>> +       if (!speed) {
>> +               debug("No valid speed specified\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       i2c_rate = clk_get_rate(&priv->clk);
>> +       divider = i2c_rate / speed;
>> +
>> +       priv->speed = speed;
>> +       if (speed > I2C_HIGHSPEED_RATE) {
>> +               debug("Enable High Speed\n");
>> +               setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
>> +                            | I2CD_M_SDA_DRIVE_1T_EN
>> +                            | I2CD_SDA_DRIVE_1T_EN);
>> +               writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
>> +       } else {
>> +               debug("Enabling Normal Speed\n");
>> +               writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
>> +       }
>> +
>> +       writel(get_clk_reg_val(divider), &regs->cactcr1);
>> +       ast_i2c_clear_interrupts(dev);
>> +
>> +       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-bus" },
>> +       { .compatible = "aspeed,ast2500-i2c-bus" },
>> +       { },
>> +};
>> +
>> +U_BOOT_DRIVER(ast_i2c) = {
>> +       .name = "ast_i2c",
>> +       .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_priv),
>> +       .ops = &ast_i2c_ops,
>> +};
>> diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
>> new file mode 100644
>> index 0000000000..e5dec7a480
>> --- /dev/null
>> +++ b/drivers/i2c/ast_i2c.h
>> @@ -0,0 +1,132 @@
>> +/*
>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>> + * Copyright 2016 IBM Corporation
>> + * Copyright 2017 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_ASPEED_AST2500
>> +       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)
>> +
>> +#define I2C_HIGHSPEED_RATE    400000
>> +
>> +#endif                         /* __AST_I2C_H_ */
>>
>
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany



-- 
Maxim Sloyko

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

* [U-Boot] [PATCH v1 11/15] aspeed: Add I2C Driver
@ 2017-04-19 16:02       ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-04-19 16:02 UTC (permalink / raw)
  To: u-boot

On Wed, Apr 19, 2017 at 4:58 AM, Heiko Schocher <hs@denx.de> wrote:
> Hello Maxim,
>
> Am 17.04.2017 um 21:00 schrieb Maxim Sloyko:
>>
>> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
>> The driver is very limited, it only supports master mode and
>> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>>
>> Signed-off-by: Maxim Sloyko <maxims@google.com>
>>
>> ---
>>
>> Changes in v1:
>> - Style fixes
>>
>>
>> ---
>>   drivers/i2c/Kconfig   |   9 ++
>>   drivers/i2c/Makefile  |   1 +
>>   drivers/i2c/ast_i2c.c | 357
>> ++++++++++++++++++++++++++++++++++++++++++++++++++
>>   drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>>   4 files changed, 499 insertions(+)
>>   create mode 100644 drivers/i2c/ast_i2c.c
>>   create mode 100644 drivers/i2c/ast_i2c.h
>
>
> Is this "version 2" from the patch you posted in march?

Yes, sorry, I think I forgot to add proper "In-Reply-To" header.

>
> Acked-by: Heiko Schocher <hs@denx.de>
>
> bye,
> Heiko
>
>>
>> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
>> index 39f62daf5d..e661a308b0 100644
>> --- a/drivers/i2c/Kconfig
>> +++ b/drivers/i2c/Kconfig
>> @@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>>           enable status register. This config option can be enabled in
>> such
>>           cases.
>>
>> +config SYS_I2C_ASPEED
>> +       bool "Aspeed I2C Controller"
>> +       depends on DM_I2C && ARCH_ASPEED
>> +       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
>> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
>> index 7c86198863..229fd476db 100644
>> --- a/drivers/i2c/Makefile
>> +++ b/drivers/i2c/Makefile
>> @@ -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_ASPEED) += ast_i2c.o
>>   obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>>   obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>>   obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>> diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
>> new file mode 100644
>> index 0000000000..16dfb57066
>> --- /dev/null
>> +++ b/drivers/i2c/ast_i2c.c
>> @@ -0,0 +1,357 @@
>> +/*
>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>> + * Copyright 2016 IBM Corporation
>> + * Copyright 2017 Google, Inc.
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <errno.h>
>> +#include <fdtdec.h>
>> +#include <i2c.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/scu_ast2500.h>
>> +
>> +#include "ast_i2c.h"
>> +
>> +#define I2C_TIMEOUT_US 100000
>> +#define I2C_SLEEP_STEP_US 20
>> +
>> +#define HIGHSPEED_TTIMEOUT             3
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +/*
>> + * Device private data
>> + */
>> +struct ast_i2c_priv {
>> +       /* This device's clock */
>> +       struct clk clk;
>> +       /* 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)
>> +                       | (div << I2CD_BASE_DIV_SHIFT);
>> +
>> +       return data;
>> +}
>> +
>> +static void ast_i2c_clear_interrupts(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       writel(~0, &priv->regs->isr);
>> +}
>> +
>> +static void ast_i2c_init_bus(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       /* Reset device */
>> +       writel(0, &priv->regs->fcr);
>> +       /* Enable Master Mode. Assuming single-master */
>> +       writel(I2CD_MASTER_EN
>> +              | I2CD_M_SDA_LOCK_EN
>> +              | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
>> +              &priv->regs->fcr);
>> +       /* Enable Interrupts */
>> +       writel(I2CD_INTR_TX_ACK
>> +              | I2CD_INTR_TX_NAK
>> +              | I2CD_INTR_RX_DONE
>> +              | I2CD_INTR_BUS_RECOVER_DONE
>> +              | I2CD_INTR_NORMAL_STOP
>> +              | I2CD_INTR_ABNORMAL, &priv->regs->icr);
>> +}
>> +
>> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int ret;
>> +
>> +       priv->regs = dev_get_addr_ptr(dev);
>> +       if (IS_ERR(priv->regs))
>> +               return PTR_ERR(priv->regs);
>> +
>> +       ret = clk_get_by_index(dev, 0, &priv->clk);
>> +       if (ret < 0) {
>> +               debug("%s: Can't get clock for %s: %d\n", __func__,
>> dev->name,
>> +                     ret);
>> +               return ret;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_probe(struct udevice *dev)
>> +{
>> +       struct ast2500_scu *scu;
>> +
>> +       debug("Enabling I2C%u\n", dev->seq);
>> +
>> +       /*
>> +        * Get all I2C devices out of Reset.
>> +        * Only needs to be done once, but doing it for every
>> +        * device does not hurt.
>> +        */
>> +       scu = ast_get_scu();
>> +       ast_scu_unlock(scu);
>> +       clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
>> +       ast_scu_lock(scu);
>> +
>> +       ast_i2c_init_bus(dev);
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int timeout = I2C_TIMEOUT_US;
>> +
>> +       while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
>> +               udelay(I2C_SLEEP_STEP_US);
>> +               timeout -= I2C_SLEEP_STEP_US;
>> +       }
>> +
>> +       ast_i2c_clear_interrupts(dev);
>> +       if (timeout <= 0)
>> +               return -ETIMEDOUT;
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_send_stop(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       writel(I2CD_M_STOP_CMD, &priv->regs->csr);
>> +
>> +       return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
>> +}
>> +
>> +static int ast_i2c_wait_tx(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int timeout = I2C_TIMEOUT_US;
>> +       u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
>> +       u32 status = readl(&priv->regs->isr) & flag;
>> +       int ret = 0;
>> +
>> +       while (!status && timeout > 0) {
>> +               status = readl(&priv->regs->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(dev);
>> +
>> +       return ret;
>> +}
>> +
>> +static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +
>> +       /* Start and Send Device Address */
>> +       writel(devaddr, &priv->regs->trbbr);
>> +       writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
>> +
>> +       return ast_i2c_wait_tx(dev);
>> +}
>> +
>> +static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8
>> *buffer,
>> +                            size_t len, bool send_stop)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       u32 i2c_cmd = I2CD_M_RX_CMD;
>> +       int ret;
>> +
>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       for (; len > 0; len--, buffer++) {
>> +               if (len == 1)
>> +                       i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
>> +               writel(i2c_cmd, &priv->regs->csr);
>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
>> +               if (ret < 0)
>> +                       return ret;
>> +               *buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
>> +                               >> I2CD_RX_DATA_SHIFT;
>> +       }
>> +       ast_i2c_clear_interrupts(dev);
>> +
>> +       if (send_stop)
>> +               return ast_i2c_send_stop(dev);
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
>> +                             *buffer, size_t len, bool send_stop)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       int ret;
>> +
>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1));
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       for (; len > 0; len--, buffer++) {
>> +               writel(*buffer, &priv->regs->trbbr);
>> +               writel(I2CD_M_TX_CMD, &priv->regs->csr);
>> +               ret = ast_i2c_wait_tx(dev);
>> +               if (ret < 0)
>> +                       return ret;
>> +       }
>> +
>> +       if (send_stop)
>> +               return ast_i2c_send_stop(dev);
>> +
>> +       return 0;
>> +}
>> +
>> +static int ast_i2c_deblock(struct udevice *dev)
>> +{
>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>> +       struct ast_i2c_regs *regs = priv->regs;
>> +       u32 csr = readl(&regs->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(dev);
>> +       } else if (scl_high) {
>> +               /* Possibly stuck slave */
>> +               debug("Bus stuck (%x), attempting recovery\n", csr);
>> +               writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
>> +       } else {
>> +               /* Just try to reinit the device. */
>> +               ast_i2c_init_bus(dev);
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int
>> nmsgs)
>> +{
>> +       int ret;
>> +
>> +       ret = ast_i2c_deblock(dev);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
>> +       struct ast_i2c_regs *regs = priv->regs;
>> +       ulong i2c_rate, divider;
>> +
>> +       debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
>> +       if (!speed) {
>> +               debug("No valid speed specified\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       i2c_rate = clk_get_rate(&priv->clk);
>> +       divider = i2c_rate / speed;
>> +
>> +       priv->speed = speed;
>> +       if (speed > I2C_HIGHSPEED_RATE) {
>> +               debug("Enable High Speed\n");
>> +               setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
>> +                            | I2CD_M_SDA_DRIVE_1T_EN
>> +                            | I2CD_SDA_DRIVE_1T_EN);
>> +               writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
>> +       } else {
>> +               debug("Enabling Normal Speed\n");
>> +               writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
>> +       }
>> +
>> +       writel(get_clk_reg_val(divider), &regs->cactcr1);
>> +       ast_i2c_clear_interrupts(dev);
>> +
>> +       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-bus" },
>> +       { .compatible = "aspeed,ast2500-i2c-bus" },
>> +       { },
>> +};
>> +
>> +U_BOOT_DRIVER(ast_i2c) = {
>> +       .name = "ast_i2c",
>> +       .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_priv),
>> +       .ops = &ast_i2c_ops,
>> +};
>> diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
>> new file mode 100644
>> index 0000000000..e5dec7a480
>> --- /dev/null
>> +++ b/drivers/i2c/ast_i2c.h
>> @@ -0,0 +1,132 @@
>> +/*
>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>> + * Copyright 2016 IBM Corporation
>> + * Copyright 2017 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_ASPEED_AST2500
>> +       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)
>> +
>> +#define I2C_HIGHSPEED_RATE    400000
>> +
>> +#endif                         /* __AST_I2C_H_ */
>>
>
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany



-- 
Maxim Sloyko

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

* Re: [PATCH v1 11/15] aspeed: Add I2C Driver
  2017-04-19 16:02       ` [U-Boot] " Maxim Sloyko
@ 2017-04-20  4:03         ` Heiko Schocher
  -1 siblings, 0 replies; 132+ messages in thread
From: Heiko Schocher @ 2017-04-20  4:03 UTC (permalink / raw)
  To: Maxim Sloyko; +Cc: Simon Glass, U-Boot Mailing List, OpenBMC Maillist

Hello Mxaim,

Am 19.04.2017 um 18:02 schrieb Maxim Sloyko:
> On Wed, Apr 19, 2017 at 4:58 AM, Heiko Schocher <hs@denx.de> wrote:
>> Hello Maxim,
>>
>> Am 17.04.2017 um 21:00 schrieb Maxim Sloyko:
>>>
>>> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
>>> The driver is very limited, it only supports master mode and
>>> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>>>
>>> Signed-off-by: Maxim Sloyko <maxims@google.com>
>>>
>>> ---
>>>
>>> Changes in v1:
>>> - Style fixes
>>>
>>>
>>> ---
>>>    drivers/i2c/Kconfig   |   9 ++
>>>    drivers/i2c/Makefile  |   1 +
>>>    drivers/i2c/ast_i2c.c | 357
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++
>>>    drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>>>    4 files changed, 499 insertions(+)
>>>    create mode 100644 drivers/i2c/ast_i2c.c
>>>    create mode 100644 drivers/i2c/ast_i2c.h
>>
>>
>> Is this "version 2" from the patch you posted in march?
>
> Yes, sorry, I think I forgot to add proper "In-Reply-To" header.

No problem with your header, instead the v1 and the missing
Acked-by from me was misleading me ;-)

bye,
Heiko
>
>>
>> Acked-by: Heiko Schocher <hs@denx.de>
>>
>> bye,
>> Heiko
>>
>>>
>>> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
>>> index 39f62daf5d..e661a308b0 100644
>>> --- a/drivers/i2c/Kconfig
>>> +++ b/drivers/i2c/Kconfig
>>> @@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>>>            enable status register. This config option can be enabled in
>>> such
>>>            cases.
>>>
>>> +config SYS_I2C_ASPEED
>>> +       bool "Aspeed I2C Controller"
>>> +       depends on DM_I2C && ARCH_ASPEED
>>> +       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
>>> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
>>> index 7c86198863..229fd476db 100644
>>> --- a/drivers/i2c/Makefile
>>> +++ b/drivers/i2c/Makefile
>>> @@ -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_ASPEED) += ast_i2c.o
>>>    obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>>>    obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>>>    obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>>> diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
>>> new file mode 100644
>>> index 0000000000..16dfb57066
>>> --- /dev/null
>>> +++ b/drivers/i2c/ast_i2c.c
>>> @@ -0,0 +1,357 @@
>>> +/*
>>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>>> + * Copyright 2016 IBM Corporation
>>> + * Copyright 2017 Google, Inc.
>>> + *
>>> + * SPDX-License-Identifier:    GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <clk.h>
>>> +#include <dm.h>
>>> +#include <errno.h>
>>> +#include <fdtdec.h>
>>> +#include <i2c.h>
>>> +#include <asm/io.h>
>>> +#include <asm/arch/scu_ast2500.h>
>>> +
>>> +#include "ast_i2c.h"
>>> +
>>> +#define I2C_TIMEOUT_US 100000
>>> +#define I2C_SLEEP_STEP_US 20
>>> +
>>> +#define HIGHSPEED_TTIMEOUT             3
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +/*
>>> + * Device private data
>>> + */
>>> +struct ast_i2c_priv {
>>> +       /* This device's clock */
>>> +       struct clk clk;
>>> +       /* 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)
>>> +                       | (div << I2CD_BASE_DIV_SHIFT);
>>> +
>>> +       return data;
>>> +}
>>> +
>>> +static void ast_i2c_clear_interrupts(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       writel(~0, &priv->regs->isr);
>>> +}
>>> +
>>> +static void ast_i2c_init_bus(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       /* Reset device */
>>> +       writel(0, &priv->regs->fcr);
>>> +       /* Enable Master Mode. Assuming single-master */
>>> +       writel(I2CD_MASTER_EN
>>> +              | I2CD_M_SDA_LOCK_EN
>>> +              | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
>>> +              &priv->regs->fcr);
>>> +       /* Enable Interrupts */
>>> +       writel(I2CD_INTR_TX_ACK
>>> +              | I2CD_INTR_TX_NAK
>>> +              | I2CD_INTR_RX_DONE
>>> +              | I2CD_INTR_BUS_RECOVER_DONE
>>> +              | I2CD_INTR_NORMAL_STOP
>>> +              | I2CD_INTR_ABNORMAL, &priv->regs->icr);
>>> +}
>>> +
>>> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int ret;
>>> +
>>> +       priv->regs = dev_get_addr_ptr(dev);
>>> +       if (IS_ERR(priv->regs))
>>> +               return PTR_ERR(priv->regs);
>>> +
>>> +       ret = clk_get_by_index(dev, 0, &priv->clk);
>>> +       if (ret < 0) {
>>> +               debug("%s: Can't get clock for %s: %d\n", __func__,
>>> dev->name,
>>> +                     ret);
>>> +               return ret;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_probe(struct udevice *dev)
>>> +{
>>> +       struct ast2500_scu *scu;
>>> +
>>> +       debug("Enabling I2C%u\n", dev->seq);
>>> +
>>> +       /*
>>> +        * Get all I2C devices out of Reset.
>>> +        * Only needs to be done once, but doing it for every
>>> +        * device does not hurt.
>>> +        */
>>> +       scu = ast_get_scu();
>>> +       ast_scu_unlock(scu);
>>> +       clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
>>> +       ast_scu_lock(scu);
>>> +
>>> +       ast_i2c_init_bus(dev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int timeout = I2C_TIMEOUT_US;
>>> +
>>> +       while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
>>> +               udelay(I2C_SLEEP_STEP_US);
>>> +               timeout -= I2C_SLEEP_STEP_US;
>>> +       }
>>> +
>>> +       ast_i2c_clear_interrupts(dev);
>>> +       if (timeout <= 0)
>>> +               return -ETIMEDOUT;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_send_stop(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       writel(I2CD_M_STOP_CMD, &priv->regs->csr);
>>> +
>>> +       return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
>>> +}
>>> +
>>> +static int ast_i2c_wait_tx(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int timeout = I2C_TIMEOUT_US;
>>> +       u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
>>> +       u32 status = readl(&priv->regs->isr) & flag;
>>> +       int ret = 0;
>>> +
>>> +       while (!status && timeout > 0) {
>>> +               status = readl(&priv->regs->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(dev);
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       /* Start and Send Device Address */
>>> +       writel(devaddr, &priv->regs->trbbr);
>>> +       writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
>>> +
>>> +       return ast_i2c_wait_tx(dev);
>>> +}
>>> +
>>> +static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8
>>> *buffer,
>>> +                            size_t len, bool send_stop)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       u32 i2c_cmd = I2CD_M_RX_CMD;
>>> +       int ret;
>>> +
>>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
>>> +       if (ret < 0)
>>> +               return ret;
>>> +
>>> +       for (; len > 0; len--, buffer++) {
>>> +               if (len == 1)
>>> +                       i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
>>> +               writel(i2c_cmd, &priv->regs->csr);
>>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
>>> +               if (ret < 0)
>>> +                       return ret;
>>> +               *buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
>>> +                               >> I2CD_RX_DATA_SHIFT;
>>> +       }
>>> +       ast_i2c_clear_interrupts(dev);
>>> +
>>> +       if (send_stop)
>>> +               return ast_i2c_send_stop(dev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
>>> +                             *buffer, size_t len, bool send_stop)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int ret;
>>> +
>>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1));
>>> +       if (ret < 0)
>>> +               return ret;
>>> +
>>> +       for (; len > 0; len--, buffer++) {
>>> +               writel(*buffer, &priv->regs->trbbr);
>>> +               writel(I2CD_M_TX_CMD, &priv->regs->csr);
>>> +               ret = ast_i2c_wait_tx(dev);
>>> +               if (ret < 0)
>>> +                       return ret;
>>> +       }
>>> +
>>> +       if (send_stop)
>>> +               return ast_i2c_send_stop(dev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_deblock(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       struct ast_i2c_regs *regs = priv->regs;
>>> +       u32 csr = readl(&regs->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(dev);
>>> +       } else if (scl_high) {
>>> +               /* Possibly stuck slave */
>>> +               debug("Bus stuck (%x), attempting recovery\n", csr);
>>> +               writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
>>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
>>> +       } else {
>>> +               /* Just try to reinit the device. */
>>> +               ast_i2c_init_bus(dev);
>>> +       }
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int
>>> nmsgs)
>>> +{
>>> +       int ret;
>>> +
>>> +       ret = ast_i2c_deblock(dev);
>>> +       if (ret < 0)
>>> +               return ret;
>>> +
>>> +       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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
>>> +       struct ast_i2c_regs *regs = priv->regs;
>>> +       ulong i2c_rate, divider;
>>> +
>>> +       debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
>>> +       if (!speed) {
>>> +               debug("No valid speed specified\n");
>>> +               return -EINVAL;
>>> +       }
>>> +
>>> +       i2c_rate = clk_get_rate(&priv->clk);
>>> +       divider = i2c_rate / speed;
>>> +
>>> +       priv->speed = speed;
>>> +       if (speed > I2C_HIGHSPEED_RATE) {
>>> +               debug("Enable High Speed\n");
>>> +               setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
>>> +                            | I2CD_M_SDA_DRIVE_1T_EN
>>> +                            | I2CD_SDA_DRIVE_1T_EN);
>>> +               writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
>>> +       } else {
>>> +               debug("Enabling Normal Speed\n");
>>> +               writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
>>> +       }
>>> +
>>> +       writel(get_clk_reg_val(divider), &regs->cactcr1);
>>> +       ast_i2c_clear_interrupts(dev);
>>> +
>>> +       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-bus" },
>>> +       { .compatible = "aspeed,ast2500-i2c-bus" },
>>> +       { },
>>> +};
>>> +
>>> +U_BOOT_DRIVER(ast_i2c) = {
>>> +       .name = "ast_i2c",
>>> +       .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_priv),
>>> +       .ops = &ast_i2c_ops,
>>> +};
>>> diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
>>> new file mode 100644
>>> index 0000000000..e5dec7a480
>>> --- /dev/null
>>> +++ b/drivers/i2c/ast_i2c.h
>>> @@ -0,0 +1,132 @@
>>> +/*
>>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>>> + * Copyright 2016 IBM Corporation
>>> + * Copyright 2017 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_ASPEED_AST2500
>>> +       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)
>>> +
>>> +#define I2C_HIGHSPEED_RATE    400000
>>> +
>>> +#endif                         /* __AST_I2C_H_ */
>>>
>>
>> --
>> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>
>
>

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

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

* [U-Boot] [PATCH v1 11/15] aspeed: Add I2C Driver
@ 2017-04-20  4:03         ` Heiko Schocher
  0 siblings, 0 replies; 132+ messages in thread
From: Heiko Schocher @ 2017-04-20  4:03 UTC (permalink / raw)
  To: u-boot

Hello Mxaim,

Am 19.04.2017 um 18:02 schrieb Maxim Sloyko:
> On Wed, Apr 19, 2017 at 4:58 AM, Heiko Schocher <hs@denx.de> wrote:
>> Hello Maxim,
>>
>> Am 17.04.2017 um 21:00 schrieb Maxim Sloyko:
>>>
>>> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
>>> The driver is very limited, it only supports master mode and
>>> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
>>>
>>> Signed-off-by: Maxim Sloyko <maxims@google.com>
>>>
>>> ---
>>>
>>> Changes in v1:
>>> - Style fixes
>>>
>>>
>>> ---
>>>    drivers/i2c/Kconfig   |   9 ++
>>>    drivers/i2c/Makefile  |   1 +
>>>    drivers/i2c/ast_i2c.c | 357
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++
>>>    drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
>>>    4 files changed, 499 insertions(+)
>>>    create mode 100644 drivers/i2c/ast_i2c.c
>>>    create mode 100644 drivers/i2c/ast_i2c.h
>>
>>
>> Is this "version 2" from the patch you posted in march?
>
> Yes, sorry, I think I forgot to add proper "In-Reply-To" header.

No problem with your header, instead the v1 and the missing
Acked-by from me was misleading me ;-)

bye,
Heiko
>
>>
>> Acked-by: Heiko Schocher <hs@denx.de>
>>
>> bye,
>> Heiko
>>
>>>
>>> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
>>> index 39f62daf5d..e661a308b0 100644
>>> --- a/drivers/i2c/Kconfig
>>> +++ b/drivers/i2c/Kconfig
>>> @@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>>>            enable status register. This config option can be enabled in
>>> such
>>>            cases.
>>>
>>> +config SYS_I2C_ASPEED
>>> +       bool "Aspeed I2C Controller"
>>> +       depends on DM_I2C && ARCH_ASPEED
>>> +       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
>>> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
>>> index 7c86198863..229fd476db 100644
>>> --- a/drivers/i2c/Makefile
>>> +++ b/drivers/i2c/Makefile
>>> @@ -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_ASPEED) += ast_i2c.o
>>>    obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>>>    obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>>>    obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>>> diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
>>> new file mode 100644
>>> index 0000000000..16dfb57066
>>> --- /dev/null
>>> +++ b/drivers/i2c/ast_i2c.c
>>> @@ -0,0 +1,357 @@
>>> +/*
>>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>>> + * Copyright 2016 IBM Corporation
>>> + * Copyright 2017 Google, Inc.
>>> + *
>>> + * SPDX-License-Identifier:    GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <clk.h>
>>> +#include <dm.h>
>>> +#include <errno.h>
>>> +#include <fdtdec.h>
>>> +#include <i2c.h>
>>> +#include <asm/io.h>
>>> +#include <asm/arch/scu_ast2500.h>
>>> +
>>> +#include "ast_i2c.h"
>>> +
>>> +#define I2C_TIMEOUT_US 100000
>>> +#define I2C_SLEEP_STEP_US 20
>>> +
>>> +#define HIGHSPEED_TTIMEOUT             3
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +/*
>>> + * Device private data
>>> + */
>>> +struct ast_i2c_priv {
>>> +       /* This device's clock */
>>> +       struct clk clk;
>>> +       /* 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)
>>> +                       | (div << I2CD_BASE_DIV_SHIFT);
>>> +
>>> +       return data;
>>> +}
>>> +
>>> +static void ast_i2c_clear_interrupts(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       writel(~0, &priv->regs->isr);
>>> +}
>>> +
>>> +static void ast_i2c_init_bus(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       /* Reset device */
>>> +       writel(0, &priv->regs->fcr);
>>> +       /* Enable Master Mode. Assuming single-master */
>>> +       writel(I2CD_MASTER_EN
>>> +              | I2CD_M_SDA_LOCK_EN
>>> +              | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
>>> +              &priv->regs->fcr);
>>> +       /* Enable Interrupts */
>>> +       writel(I2CD_INTR_TX_ACK
>>> +              | I2CD_INTR_TX_NAK
>>> +              | I2CD_INTR_RX_DONE
>>> +              | I2CD_INTR_BUS_RECOVER_DONE
>>> +              | I2CD_INTR_NORMAL_STOP
>>> +              | I2CD_INTR_ABNORMAL, &priv->regs->icr);
>>> +}
>>> +
>>> +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int ret;
>>> +
>>> +       priv->regs = dev_get_addr_ptr(dev);
>>> +       if (IS_ERR(priv->regs))
>>> +               return PTR_ERR(priv->regs);
>>> +
>>> +       ret = clk_get_by_index(dev, 0, &priv->clk);
>>> +       if (ret < 0) {
>>> +               debug("%s: Can't get clock for %s: %d\n", __func__,
>>> dev->name,
>>> +                     ret);
>>> +               return ret;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_probe(struct udevice *dev)
>>> +{
>>> +       struct ast2500_scu *scu;
>>> +
>>> +       debug("Enabling I2C%u\n", dev->seq);
>>> +
>>> +       /*
>>> +        * Get all I2C devices out of Reset.
>>> +        * Only needs to be done once, but doing it for every
>>> +        * device does not hurt.
>>> +        */
>>> +       scu = ast_get_scu();
>>> +       ast_scu_unlock(scu);
>>> +       clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
>>> +       ast_scu_lock(scu);
>>> +
>>> +       ast_i2c_init_bus(dev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int timeout = I2C_TIMEOUT_US;
>>> +
>>> +       while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
>>> +               udelay(I2C_SLEEP_STEP_US);
>>> +               timeout -= I2C_SLEEP_STEP_US;
>>> +       }
>>> +
>>> +       ast_i2c_clear_interrupts(dev);
>>> +       if (timeout <= 0)
>>> +               return -ETIMEDOUT;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_send_stop(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       writel(I2CD_M_STOP_CMD, &priv->regs->csr);
>>> +
>>> +       return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
>>> +}
>>> +
>>> +static int ast_i2c_wait_tx(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int timeout = I2C_TIMEOUT_US;
>>> +       u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
>>> +       u32 status = readl(&priv->regs->isr) & flag;
>>> +       int ret = 0;
>>> +
>>> +       while (!status && timeout > 0) {
>>> +               status = readl(&priv->regs->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(dev);
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +
>>> +       /* Start and Send Device Address */
>>> +       writel(devaddr, &priv->regs->trbbr);
>>> +       writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
>>> +
>>> +       return ast_i2c_wait_tx(dev);
>>> +}
>>> +
>>> +static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8
>>> *buffer,
>>> +                            size_t len, bool send_stop)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       u32 i2c_cmd = I2CD_M_RX_CMD;
>>> +       int ret;
>>> +
>>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
>>> +       if (ret < 0)
>>> +               return ret;
>>> +
>>> +       for (; len > 0; len--, buffer++) {
>>> +               if (len == 1)
>>> +                       i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
>>> +               writel(i2c_cmd, &priv->regs->csr);
>>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
>>> +               if (ret < 0)
>>> +                       return ret;
>>> +               *buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
>>> +                               >> I2CD_RX_DATA_SHIFT;
>>> +       }
>>> +       ast_i2c_clear_interrupts(dev);
>>> +
>>> +       if (send_stop)
>>> +               return ast_i2c_send_stop(dev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
>>> +                             *buffer, size_t len, bool send_stop)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       int ret;
>>> +
>>> +       ret = ast_i2c_start_txn(dev, (chip_addr << 1));
>>> +       if (ret < 0)
>>> +               return ret;
>>> +
>>> +       for (; len > 0; len--, buffer++) {
>>> +               writel(*buffer, &priv->regs->trbbr);
>>> +               writel(I2CD_M_TX_CMD, &priv->regs->csr);
>>> +               ret = ast_i2c_wait_tx(dev);
>>> +               if (ret < 0)
>>> +                       return ret;
>>> +       }
>>> +
>>> +       if (send_stop)
>>> +               return ast_i2c_send_stop(dev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int ast_i2c_deblock(struct udevice *dev)
>>> +{
>>> +       struct ast_i2c_priv *priv = dev_get_priv(dev);
>>> +       struct ast_i2c_regs *regs = priv->regs;
>>> +       u32 csr = readl(&regs->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(dev);
>>> +       } else if (scl_high) {
>>> +               /* Possibly stuck slave */
>>> +               debug("Bus stuck (%x), attempting recovery\n", csr);
>>> +               writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
>>> +               ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
>>> +       } else {
>>> +               /* Just try to reinit the device. */
>>> +               ast_i2c_init_bus(dev);
>>> +       }
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int
>>> nmsgs)
>>> +{
>>> +       int ret;
>>> +
>>> +       ret = ast_i2c_deblock(dev);
>>> +       if (ret < 0)
>>> +               return ret;
>>> +
>>> +       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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
>>> +       struct ast_i2c_regs *regs = priv->regs;
>>> +       ulong i2c_rate, divider;
>>> +
>>> +       debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
>>> +       if (!speed) {
>>> +               debug("No valid speed specified\n");
>>> +               return -EINVAL;
>>> +       }
>>> +
>>> +       i2c_rate = clk_get_rate(&priv->clk);
>>> +       divider = i2c_rate / speed;
>>> +
>>> +       priv->speed = speed;
>>> +       if (speed > I2C_HIGHSPEED_RATE) {
>>> +               debug("Enable High Speed\n");
>>> +               setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
>>> +                            | I2CD_M_SDA_DRIVE_1T_EN
>>> +                            | I2CD_SDA_DRIVE_1T_EN);
>>> +               writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
>>> +       } else {
>>> +               debug("Enabling Normal Speed\n");
>>> +               writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
>>> +       }
>>> +
>>> +       writel(get_clk_reg_val(divider), &regs->cactcr1);
>>> +       ast_i2c_clear_interrupts(dev);
>>> +
>>> +       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-bus" },
>>> +       { .compatible = "aspeed,ast2500-i2c-bus" },
>>> +       { },
>>> +};
>>> +
>>> +U_BOOT_DRIVER(ast_i2c) = {
>>> +       .name = "ast_i2c",
>>> +       .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_priv),
>>> +       .ops = &ast_i2c_ops,
>>> +};
>>> diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
>>> new file mode 100644
>>> index 0000000000..e5dec7a480
>>> --- /dev/null
>>> +++ b/drivers/i2c/ast_i2c.h
>>> @@ -0,0 +1,132 @@
>>> +/*
>>> + * Copyright (C) 2012-2020  ASPEED Technology Inc.
>>> + * Copyright 2016 IBM Corporation
>>> + * Copyright 2017 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_ASPEED_AST2500
>>> +       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)
>>> +
>>> +#define I2C_HIGHSPEED_RATE    400000
>>> +
>>> +#endif                         /* __AST_I2C_H_ */
>>>
>>
>> --
>> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>
>
>

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

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

* Re: [PATCH v1 11/15] aspeed: Add I2C Driver
  2017-04-19  0:12     ` [U-Boot] " Simon Glass
@ 2017-05-05 19:18       ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 19:18 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List, OpenBMC Maillist, Heiko Schocher

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

On Tue, Apr 18, 2017 at 5:12 PM, Simon Glass <sjg@chromium.org> wrote:

> On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> > Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> > The driver is very limited, it only supports master mode and
> > synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
> >
> > Signed-off-by: Maxim Sloyko <maxims@google.com>
> >
> > ---
> >
> > Changes in v1:
> > - Style fixes
> >
> >
> > ---
> >  drivers/i2c/Kconfig   |   9 ++
> >  drivers/i2c/Makefile  |   1 +
> >  drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++
> ++++++++++++++++++++
> >  drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
> >  4 files changed, 499 insertions(+)
> >  create mode 100644 drivers/i2c/ast_i2c.c
> >  create mode 100644 drivers/i2c/ast_i2c.h
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> nit below
>
> [..]
> > +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
> > +{
> > +       struct ast_i2c_priv *priv = dev_get_priv(dev);
> > +       int ret;
> > +
> > +       priv->regs = dev_get_addr_ptr(dev);
> > +       if (IS_ERR(priv->regs))
> > +               return PTR_ERR(priv->regs);
>
> Should be
>
>  if (!priv->regs)
>
> I think
>

Looks like dev_get_addr_ptr returns FDT_ADDR_T_NONE (cast to void*) in case
of error. FDT_ADDR_T_NONE is -1, so simple !priv->regs check would be
incorrect, as far as I understand.


>
> > +
> > +       ret = clk_get_by_index(dev, 0, &priv->clk);
> > +       if (ret < 0) {
> > +               debug("%s: Can't get clock for %s: %d\n", __func__,
> dev->name,
> > +                     ret);
> > +               return ret;
>
> Regards,
> Simon
>



-- 
*M*axim *S*loyko

[-- Attachment #2: Type: text/html, Size: 2834 bytes --]

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

* [U-Boot] [PATCH v1 11/15] aspeed: Add I2C Driver
@ 2017-05-05 19:18       ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 19:18 UTC (permalink / raw)
  To: u-boot

On Tue, Apr 18, 2017 at 5:12 PM, Simon Glass <sjg@chromium.org> wrote:

> On 17 April 2017 at 13:00, Maxim Sloyko <maxims@google.com> wrote:
> > Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> > The driver is very limited, it only supports master mode and
> > synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
> >
> > Signed-off-by: Maxim Sloyko <maxims@google.com>
> >
> > ---
> >
> > Changes in v1:
> > - Style fixes
> >
> >
> > ---
> >  drivers/i2c/Kconfig   |   9 ++
> >  drivers/i2c/Makefile  |   1 +
> >  drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++
> ++++++++++++++++++++
> >  drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
> >  4 files changed, 499 insertions(+)
> >  create mode 100644 drivers/i2c/ast_i2c.c
> >  create mode 100644 drivers/i2c/ast_i2c.h
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> nit below
>
> [..]
> > +static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
> > +{
> > +       struct ast_i2c_priv *priv = dev_get_priv(dev);
> > +       int ret;
> > +
> > +       priv->regs = dev_get_addr_ptr(dev);
> > +       if (IS_ERR(priv->regs))
> > +               return PTR_ERR(priv->regs);
>
> Should be
>
>  if (!priv->regs)
>
> I think
>

Looks like dev_get_addr_ptr returns FDT_ADDR_T_NONE (cast to void*) in case
of error. FDT_ADDR_T_NONE is -1, so simple !priv->regs check would be
incorrect, as far as I understand.


>
> > +
> > +       ret = clk_get_by_index(dev, 0, &priv->clk);
> > +       if (ret < 0) {
> > +               debug("%s: Can't get clock for %s: %d\n", __func__,
> dev->name,
> > +                     ret);
> > +               return ret;
>
> Regards,
> Simon
>



-- 
*M*axim *S*loyko

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

* [PATCH v2 00/15] Expand Aspeed AST2500 Support
  2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01   ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass
  Cc: openbmc, Maxim Sloyko, Heiko Schocher, Konstantin Porotchkin,
	Masahiro Yamada, Tom Warren, Thomas Abraham, Wills Wang,
	Kever Yang, Albert Aribaud, Beniamino Galvani, Stefan Roese,
	Heiko Stübner, Minkyu Kang, Daniel Schwierzeck, Wenyou Yang,
	Stephen Warren

This series expands support for Aspeed AST2500 SoC, commonly used as
Board Management Controller in many servers.

The main goal of this series is I2C driver, the rest are
either cleanups or supporting patches. Most notable among them is
addition of Watchdog uclass, so that watchdog drivers can now use Driver
Model.

One notable thing that is *missing* from this series is Device Tree
configuration for I2C driver. The Linux Kernel I2C driver is still under
review and it may affect the details of how devices need to be
configured in the Device Tree. So, I decided to wait until it will show
up in Linux Kernel DT and then pull it into U-Boot.

I removed Network driver from this series. I will work on it separately
and will make it compatible with existing Faraday devices, but that is a
work better done outside of this already long series.

Also, sorry for taking long time to respond, I had to take care of some
more pressing, non-U-Boot-related issues.
I can assure you that I'm still committed to continue to work on Aspeed
in U-Boot.

Changes in v2:
- Remove "probe" function from sandbox wdt driver
- Fix include order

Changes in v1:
- Added link to the original version to commit message
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests
- Rename reset to expire_now
- Rename restart to reset
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now
- Rename wdt_reset call to wdt_expire_now
- Style fixes

Maxim Sloyko (15):
  aspeed: Update ast2500 Device Tree
  dm: Simple Watchdog uclass
  aspeed: Watchdog Timer Driver
  aspeed: Make SCU lock/unlock functions part of SCU API
  aspeed: Reset Driver
  aspeed: Device Tree configuration for Reset Driver
  aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  aspeed: AST2500 Pinctrl Driver
  aspeed: Enable Pinctrl Driver in AST2500 EVB
  aspeed: Add P-Bus clock in ast2500 clock driver
  aspeed: Add I2C Driver
  aspeed: Enable I2C in EVB defconfig
  aspeed: Add support for Clocks needed by MACs
  aspeed: Refactor SCU to use consistent mask & shift
  aspeed: Cleanup ast2500-u-boot.dtsi Device Tree

 arch/arm/dts/ast2500-evb.dts                   |  15 +
 arch/arm/dts/ast2500-u-boot.dtsi               |  59 +-
 arch/arm/dts/ast2500.dtsi                      | 881 ++++++++++++++++++++++++-
 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 132 +++-
 arch/arm/include/asm/arch-aspeed/wdt.h         |  38 +-
 arch/arm/mach-aspeed/Kconfig                   |   8 +-
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     |  15 +
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  17 +-
 arch/arm/mach-aspeed/ast_wdt.c                 |  47 +-
 arch/sandbox/dts/test.dts                      |   4 +
 arch/sandbox/include/asm/state.h               |   9 +
 configs/evb-ast2500_defconfig                  |   6 +
 configs/sandbox_defconfig                      |   2 +
 drivers/clk/aspeed/clk_ast2500.c               | 321 +++++++--
 drivers/i2c/Kconfig                            |   9 +
 drivers/i2c/Makefile                           |   1 +
 drivers/i2c/ast_i2c.c                          | 357 ++++++++++
 drivers/i2c/ast_i2c.h                          | 132 ++++
 drivers/pinctrl/Kconfig                        |   9 +
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 ++++
 drivers/reset/Kconfig                          |  10 +
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++
 drivers/sysreset/sysreset_ast.c                |  24 +-
 drivers/watchdog/Kconfig                       |  32 +
 drivers/watchdog/Makefile                      |   3 +
 drivers/watchdog/ast_wdt.c                     | 125 ++++
 drivers/watchdog/sandbox_wdt.c                 |  66 ++
 drivers/watchdog/wdt-uclass.c                  |  72 ++
 include/dm/uclass-id.h                         |   1 +
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 include/dt-bindings/reset/ast2500-reset.h      |  45 ++
 include/wdt.h                                  | 107 +++
 test/dm/Makefile                               |   1 +
 test/dm/wdt.c                                  |  40 ++
 38 files changed, 2711 insertions(+), 167 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c
 create mode 100644 drivers/reset/ast2500-reset.c
 create mode 100644 drivers/watchdog/ast_wdt.c
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 00/15] Expand Aspeed AST2500 Support
@ 2017-05-05 22:01   ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

This series expands support for Aspeed AST2500 SoC, commonly used as
Board Management Controller in many servers.

The main goal of this series is I2C driver, the rest are
either cleanups or supporting patches. Most notable among them is
addition of Watchdog uclass, so that watchdog drivers can now use Driver
Model.

One notable thing that is *missing* from this series is Device Tree
configuration for I2C driver. The Linux Kernel I2C driver is still under
review and it may affect the details of how devices need to be
configured in the Device Tree. So, I decided to wait until it will show
up in Linux Kernel DT and then pull it into U-Boot.

I removed Network driver from this series. I will work on it separately
and will make it compatible with existing Faraday devices, but that is a
work better done outside of this already long series.

Also, sorry for taking long time to respond, I had to take care of some
more pressing, non-U-Boot-related issues.
I can assure you that I'm still committed to continue to work on Aspeed
in U-Boot.

Changes in v2:
- Remove "probe" function from sandbox wdt driver
- Fix include order

Changes in v1:
- Added link to the original version to commit message
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests
- Rename reset to expire_now
- Rename restart to reset
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now
- Rename wdt_reset call to wdt_expire_now
- Style fixes

Maxim Sloyko (15):
  aspeed: Update ast2500 Device Tree
  dm: Simple Watchdog uclass
  aspeed: Watchdog Timer Driver
  aspeed: Make SCU lock/unlock functions part of SCU API
  aspeed: Reset Driver
  aspeed: Device Tree configuration for Reset Driver
  aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  aspeed: AST2500 Pinctrl Driver
  aspeed: Enable Pinctrl Driver in AST2500 EVB
  aspeed: Add P-Bus clock in ast2500 clock driver
  aspeed: Add I2C Driver
  aspeed: Enable I2C in EVB defconfig
  aspeed: Add support for Clocks needed by MACs
  aspeed: Refactor SCU to use consistent mask & shift
  aspeed: Cleanup ast2500-u-boot.dtsi Device Tree

 arch/arm/dts/ast2500-evb.dts                   |  15 +
 arch/arm/dts/ast2500-u-boot.dtsi               |  59 +-
 arch/arm/dts/ast2500.dtsi                      | 881 ++++++++++++++++++++++++-
 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 132 +++-
 arch/arm/include/asm/arch-aspeed/wdt.h         |  38 +-
 arch/arm/mach-aspeed/Kconfig                   |   8 +-
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     |  15 +
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  17 +-
 arch/arm/mach-aspeed/ast_wdt.c                 |  47 +-
 arch/sandbox/dts/test.dts                      |   4 +
 arch/sandbox/include/asm/state.h               |   9 +
 configs/evb-ast2500_defconfig                  |   6 +
 configs/sandbox_defconfig                      |   2 +
 drivers/clk/aspeed/clk_ast2500.c               | 321 +++++++--
 drivers/i2c/Kconfig                            |   9 +
 drivers/i2c/Makefile                           |   1 +
 drivers/i2c/ast_i2c.c                          | 357 ++++++++++
 drivers/i2c/ast_i2c.h                          | 132 ++++
 drivers/pinctrl/Kconfig                        |   9 +
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 ++++
 drivers/reset/Kconfig                          |  10 +
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++
 drivers/sysreset/sysreset_ast.c                |  24 +-
 drivers/watchdog/Kconfig                       |  32 +
 drivers/watchdog/Makefile                      |   3 +
 drivers/watchdog/ast_wdt.c                     | 125 ++++
 drivers/watchdog/sandbox_wdt.c                 |  66 ++
 drivers/watchdog/wdt-uclass.c                  |  72 ++
 include/dm/uclass-id.h                         |   1 +
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 include/dt-bindings/reset/ast2500-reset.h      |  45 ++
 include/wdt.h                                  | 107 +++
 test/dm/Makefile                               |   1 +
 test/dm/wdt.c                                  |  40 ++
 38 files changed, 2711 insertions(+), 167 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c
 create mode 100644 drivers/reset/ast2500-reset.c
 create mode 100644 drivers/watchdog/ast_wdt.c
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 01/15] aspeed: Update ast2500 Device Tree
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Pull in the Device Tree for ast2500 from the mainline Linux kernel.
The file is copied from
https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Added link to the original version to commit message

---
 arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 880 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/ast2500.dtsi b/arch/arm/dts/ast2500.dtsi
index 97fac69d11..7e0ad3a41a 100644
--- a/arch/arm/dts/ast2500.dtsi
+++ b/arch/arm/dts/ast2500.dtsi
@@ -1,6 +1,6 @@
 /*
  * This device tree is copied from
- * https://raw.githubusercontent.com/torvalds/linux/02440622/arch/arm/boot/dts/
+ * https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
  */
 #include "skeleton.dtsi"
 
@@ -36,6 +36,22 @@
 			reg = <0x1e6c0080 0x80>;
 		};
 
+		mac0: ethernet@1e660000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e660000 0x180>;
+			interrupts = <2>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
+		mac1: ethernet@1e680000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e680000 0x180>;
+			interrupts = <3>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
 		apb {
 			compatible = "simple-bus";
 			#address-cells = <1>;
@@ -48,6 +64,822 @@
 				reg = <0x1e6e2070 0x04>;
 			};
 
+			syscon: syscon@1e6e2000 {
+				compatible = "aspeed,g5-scu", "syscon", "simple-mfd";
+				reg = <0x1e6e2000 0x1a8>;
+
+				pinctrl: pinctrl {
+					compatible = "aspeed,g5-pinctrl";
+					aspeed,external-nodes = <&gfx &lhc>;
+
+					pinctrl_acpi_default: acpi_default {
+						function = "ACPI";
+						groups = "ACPI";
+					};
+
+					pinctrl_adc0_default: adc0_default {
+						function = "ADC0";
+						groups = "ADC0";
+					};
+
+					pinctrl_adc1_default: adc1_default {
+						function = "ADC1";
+						groups = "ADC1";
+					};
+
+					pinctrl_adc10_default: adc10_default {
+						function = "ADC10";
+						groups = "ADC10";
+					};
+
+					pinctrl_adc11_default: adc11_default {
+						function = "ADC11";
+						groups = "ADC11";
+					};
+
+					pinctrl_adc12_default: adc12_default {
+						function = "ADC12";
+						groups = "ADC12";
+					};
+
+					pinctrl_adc13_default: adc13_default {
+						function = "ADC13";
+						groups = "ADC13";
+					};
+
+					pinctrl_adc14_default: adc14_default {
+						function = "ADC14";
+						groups = "ADC14";
+					};
+
+					pinctrl_adc15_default: adc15_default {
+						function = "ADC15";
+						groups = "ADC15";
+					};
+
+					pinctrl_adc2_default: adc2_default {
+						function = "ADC2";
+						groups = "ADC2";
+					};
+
+					pinctrl_adc3_default: adc3_default {
+						function = "ADC3";
+						groups = "ADC3";
+					};
+
+					pinctrl_adc4_default: adc4_default {
+						function = "ADC4";
+						groups = "ADC4";
+					};
+
+					pinctrl_adc5_default: adc5_default {
+						function = "ADC5";
+						groups = "ADC5";
+					};
+
+					pinctrl_adc6_default: adc6_default {
+						function = "ADC6";
+						groups = "ADC6";
+					};
+
+					pinctrl_adc7_default: adc7_default {
+						function = "ADC7";
+						groups = "ADC7";
+					};
+
+					pinctrl_adc8_default: adc8_default {
+						function = "ADC8";
+						groups = "ADC8";
+					};
+
+					pinctrl_adc9_default: adc9_default {
+						function = "ADC9";
+						groups = "ADC9";
+					};
+
+					pinctrl_bmcint_default: bmcint_default {
+						function = "BMCINT";
+						groups = "BMCINT";
+					};
+
+					pinctrl_ddcclk_default: ddcclk_default {
+						function = "DDCCLK";
+						groups = "DDCCLK";
+					};
+
+					pinctrl_ddcdat_default: ddcdat_default {
+						function = "DDCDAT";
+						groups = "DDCDAT";
+					};
+
+					pinctrl_espi_default: espi_default {
+						function = "ESPI";
+						groups = "ESPI";
+					};
+
+					pinctrl_fwspics1_default: fwspics1_default {
+						function = "FWSPICS1";
+						groups = "FWSPICS1";
+					};
+
+					pinctrl_fwspics2_default: fwspics2_default {
+						function = "FWSPICS2";
+						groups = "FWSPICS2";
+					};
+
+					pinctrl_gpid0_default: gpid0_default {
+						function = "GPID0";
+						groups = "GPID0";
+					};
+
+					pinctrl_gpid2_default: gpid2_default {
+						function = "GPID2";
+						groups = "GPID2";
+					};
+
+					pinctrl_gpid4_default: gpid4_default {
+						function = "GPID4";
+						groups = "GPID4";
+					};
+
+					pinctrl_gpid6_default: gpid6_default {
+						function = "GPID6";
+						groups = "GPID6";
+					};
+
+					pinctrl_gpie0_default: gpie0_default {
+						function = "GPIE0";
+						groups = "GPIE0";
+					};
+
+					pinctrl_gpie2_default: gpie2_default {
+						function = "GPIE2";
+						groups = "GPIE2";
+					};
+
+					pinctrl_gpie4_default: gpie4_default {
+						function = "GPIE4";
+						groups = "GPIE4";
+					};
+
+					pinctrl_gpie6_default: gpie6_default {
+						function = "GPIE6";
+						groups = "GPIE6";
+					};
+
+					pinctrl_i2c10_default: i2c10_default {
+						function = "I2C10";
+						groups = "I2C10";
+					};
+
+					pinctrl_i2c11_default: i2c11_default {
+						function = "I2C11";
+						groups = "I2C11";
+					};
+
+					pinctrl_i2c12_default: i2c12_default {
+						function = "I2C12";
+						groups = "I2C12";
+					};
+
+					pinctrl_i2c13_default: i2c13_default {
+						function = "I2C13";
+						groups = "I2C13";
+					};
+
+					pinctrl_i2c14_default: i2c14_default {
+						function = "I2C14";
+						groups = "I2C14";
+					};
+
+					pinctrl_i2c3_default: i2c3_default {
+						function = "I2C3";
+						groups = "I2C3";
+					};
+
+					pinctrl_i2c4_default: i2c4_default {
+						function = "I2C4";
+						groups = "I2C4";
+					};
+
+					pinctrl_i2c5_default: i2c5_default {
+						function = "I2C5";
+						groups = "I2C5";
+					};
+
+					pinctrl_i2c6_default: i2c6_default {
+						function = "I2C6";
+						groups = "I2C6";
+					};
+
+					pinctrl_i2c7_default: i2c7_default {
+						function = "I2C7";
+						groups = "I2C7";
+					};
+
+					pinctrl_i2c8_default: i2c8_default {
+						function = "I2C8";
+						groups = "I2C8";
+					};
+
+					pinctrl_i2c9_default: i2c9_default {
+						function = "I2C9";
+						groups = "I2C9";
+					};
+
+					pinctrl_lad0_default: lad0_default {
+						function = "LAD0";
+						groups = "LAD0";
+					};
+
+					pinctrl_lad1_default: lad1_default {
+						function = "LAD1";
+						groups = "LAD1";
+					};
+
+					pinctrl_lad2_default: lad2_default {
+						function = "LAD2";
+						groups = "LAD2";
+					};
+
+					pinctrl_lad3_default: lad3_default {
+						function = "LAD3";
+						groups = "LAD3";
+					};
+
+					pinctrl_lclk_default: lclk_default {
+						function = "LCLK";
+						groups = "LCLK";
+					};
+
+					pinctrl_lframe_default: lframe_default {
+						function = "LFRAME";
+						groups = "LFRAME";
+					};
+
+					pinctrl_lpchc_default: lpchc_default {
+						function = "LPCHC";
+						groups = "LPCHC";
+					};
+
+					pinctrl_lpcpd_default: lpcpd_default {
+						function = "LPCPD";
+						groups = "LPCPD";
+					};
+
+					pinctrl_lpcplus_default: lpcplus_default {
+						function = "LPCPLUS";
+						groups = "LPCPLUS";
+					};
+
+					pinctrl_lpcpme_default: lpcpme_default {
+						function = "LPCPME";
+						groups = "LPCPME";
+					};
+
+					pinctrl_lpcrst_default: lpcrst_default {
+						function = "LPCRST";
+						groups = "LPCRST";
+					};
+
+					pinctrl_lpcsmi_default: lpcsmi_default {
+						function = "LPCSMI";
+						groups = "LPCSMI";
+					};
+
+					pinctrl_lsirq_default: lsirq_default {
+						function = "LSIRQ";
+						groups = "LSIRQ";
+					};
+
+					pinctrl_mac1link_default: mac1link_default {
+						function = "MAC1LINK";
+						groups = "MAC1LINK";
+					};
+
+					pinctrl_mac2link_default: mac2link_default {
+						function = "MAC2LINK";
+						groups = "MAC2LINK";
+					};
+
+					pinctrl_mdio1_default: mdio1_default {
+						function = "MDIO1";
+						groups = "MDIO1";
+					};
+
+					pinctrl_mdio2_default: mdio2_default {
+						function = "MDIO2";
+						groups = "MDIO2";
+					};
+
+					pinctrl_ncts1_default: ncts1_default {
+						function = "NCTS1";
+						groups = "NCTS1";
+					};
+
+					pinctrl_ncts2_default: ncts2_default {
+						function = "NCTS2";
+						groups = "NCTS2";
+					};
+
+					pinctrl_ncts3_default: ncts3_default {
+						function = "NCTS3";
+						groups = "NCTS3";
+					};
+
+					pinctrl_ncts4_default: ncts4_default {
+						function = "NCTS4";
+						groups = "NCTS4";
+					};
+
+					pinctrl_ndcd1_default: ndcd1_default {
+						function = "NDCD1";
+						groups = "NDCD1";
+					};
+
+					pinctrl_ndcd2_default: ndcd2_default {
+						function = "NDCD2";
+						groups = "NDCD2";
+					};
+
+					pinctrl_ndcd3_default: ndcd3_default {
+						function = "NDCD3";
+						groups = "NDCD3";
+					};
+
+					pinctrl_ndcd4_default: ndcd4_default {
+						function = "NDCD4";
+						groups = "NDCD4";
+					};
+
+					pinctrl_ndsr1_default: ndsr1_default {
+						function = "NDSR1";
+						groups = "NDSR1";
+					};
+
+					pinctrl_ndsr2_default: ndsr2_default {
+						function = "NDSR2";
+						groups = "NDSR2";
+					};
+
+					pinctrl_ndsr3_default: ndsr3_default {
+						function = "NDSR3";
+						groups = "NDSR3";
+					};
+
+					pinctrl_ndsr4_default: ndsr4_default {
+						function = "NDSR4";
+						groups = "NDSR4";
+					};
+
+					pinctrl_ndtr1_default: ndtr1_default {
+						function = "NDTR1";
+						groups = "NDTR1";
+					};
+
+					pinctrl_ndtr2_default: ndtr2_default {
+						function = "NDTR2";
+						groups = "NDTR2";
+					};
+
+					pinctrl_ndtr3_default: ndtr3_default {
+						function = "NDTR3";
+						groups = "NDTR3";
+					};
+
+					pinctrl_ndtr4_default: ndtr4_default {
+						function = "NDTR4";
+						groups = "NDTR4";
+					};
+
+					pinctrl_nri1_default: nri1_default {
+						function = "NRI1";
+						groups = "NRI1";
+					};
+
+					pinctrl_nri2_default: nri2_default {
+						function = "NRI2";
+						groups = "NRI2";
+					};
+
+					pinctrl_nri3_default: nri3_default {
+						function = "NRI3";
+						groups = "NRI3";
+					};
+
+					pinctrl_nri4_default: nri4_default {
+						function = "NRI4";
+						groups = "NRI4";
+					};
+
+					pinctrl_nrts1_default: nrts1_default {
+						function = "NRTS1";
+						groups = "NRTS1";
+					};
+
+					pinctrl_nrts2_default: nrts2_default {
+						function = "NRTS2";
+						groups = "NRTS2";
+					};
+
+					pinctrl_nrts3_default: nrts3_default {
+						function = "NRTS3";
+						groups = "NRTS3";
+					};
+
+					pinctrl_nrts4_default: nrts4_default {
+						function = "NRTS4";
+						groups = "NRTS4";
+					};
+
+					pinctrl_oscclk_default: oscclk_default {
+						function = "OSCCLK";
+						groups = "OSCCLK";
+					};
+
+					pinctrl_pewake_default: pewake_default {
+						function = "PEWAKE";
+						groups = "PEWAKE";
+					};
+
+					pinctrl_pnor_default: pnor_default {
+						function = "PNOR";
+						groups = "PNOR";
+					};
+
+					pinctrl_pwm0_default: pwm0_default {
+						function = "PWM0";
+						groups = "PWM0";
+					};
+
+					pinctrl_pwm1_default: pwm1_default {
+						function = "PWM1";
+						groups = "PWM1";
+					};
+
+					pinctrl_pwm2_default: pwm2_default {
+						function = "PWM2";
+						groups = "PWM2";
+					};
+
+					pinctrl_pwm3_default: pwm3_default {
+						function = "PWM3";
+						groups = "PWM3";
+					};
+
+					pinctrl_pwm4_default: pwm4_default {
+						function = "PWM4";
+						groups = "PWM4";
+					};
+
+					pinctrl_pwm5_default: pwm5_default {
+						function = "PWM5";
+						groups = "PWM5";
+					};
+
+					pinctrl_pwm6_default: pwm6_default {
+						function = "PWM6";
+						groups = "PWM6";
+					};
+
+					pinctrl_pwm7_default: pwm7_default {
+						function = "PWM7";
+						groups = "PWM7";
+					};
+
+					pinctrl_rgmii1_default: rgmii1_default {
+						function = "RGMII1";
+						groups = "RGMII1";
+					};
+
+					pinctrl_rgmii2_default: rgmii2_default {
+						function = "RGMII2";
+						groups = "RGMII2";
+					};
+
+					pinctrl_rmii1_default: rmii1_default {
+						function = "RMII1";
+						groups = "RMII1";
+					};
+
+					pinctrl_rmii2_default: rmii2_default {
+						function = "RMII2";
+						groups = "RMII2";
+					};
+
+					pinctrl_rxd1_default: rxd1_default {
+						function = "RXD1";
+						groups = "RXD1";
+					};
+
+					pinctrl_rxd2_default: rxd2_default {
+						function = "RXD2";
+						groups = "RXD2";
+					};
+
+					pinctrl_rxd3_default: rxd3_default {
+						function = "RXD3";
+						groups = "RXD3";
+					};
+
+					pinctrl_rxd4_default: rxd4_default {
+						function = "RXD4";
+						groups = "RXD4";
+					};
+
+					pinctrl_salt1_default: salt1_default {
+						function = "SALT1";
+						groups = "SALT1";
+					};
+
+					pinctrl_salt10_default: salt10_default {
+						function = "SALT10";
+						groups = "SALT10";
+					};
+
+					pinctrl_salt11_default: salt11_default {
+						function = "SALT11";
+						groups = "SALT11";
+					};
+
+					pinctrl_salt12_default: salt12_default {
+						function = "SALT12";
+						groups = "SALT12";
+					};
+
+					pinctrl_salt13_default: salt13_default {
+						function = "SALT13";
+						groups = "SALT13";
+					};
+
+					pinctrl_salt14_default: salt14_default {
+						function = "SALT14";
+						groups = "SALT14";
+					};
+
+					pinctrl_salt2_default: salt2_default {
+						function = "SALT2";
+						groups = "SALT2";
+					};
+
+					pinctrl_salt3_default: salt3_default {
+						function = "SALT3";
+						groups = "SALT3";
+					};
+
+					pinctrl_salt4_default: salt4_default {
+						function = "SALT4";
+						groups = "SALT4";
+					};
+
+					pinctrl_salt5_default: salt5_default {
+						function = "SALT5";
+						groups = "SALT5";
+					};
+
+					pinctrl_salt6_default: salt6_default {
+						function = "SALT6";
+						groups = "SALT6";
+					};
+
+					pinctrl_salt7_default: salt7_default {
+						function = "SALT7";
+						groups = "SALT7";
+					};
+
+					pinctrl_salt8_default: salt8_default {
+						function = "SALT8";
+						groups = "SALT8";
+					};
+
+					pinctrl_salt9_default: salt9_default {
+						function = "SALT9";
+						groups = "SALT9";
+					};
+
+					pinctrl_scl1_default: scl1_default {
+						function = "SCL1";
+						groups = "SCL1";
+					};
+
+					pinctrl_scl2_default: scl2_default {
+						function = "SCL2";
+						groups = "SCL2";
+					};
+
+					pinctrl_sd1_default: sd1_default {
+						function = "SD1";
+						groups = "SD1";
+					};
+
+					pinctrl_sd2_default: sd2_default {
+						function = "SD2";
+						groups = "SD2";
+					};
+
+					pinctrl_sda1_default: sda1_default {
+						function = "SDA1";
+						groups = "SDA1";
+					};
+
+					pinctrl_sda2_default: sda2_default {
+						function = "SDA2";
+						groups = "SDA2";
+					};
+
+					pinctrl_sgps1_default: sgps1_default {
+						function = "SGPS1";
+						groups = "SGPS1";
+					};
+
+					pinctrl_sgps2_default: sgps2_default {
+						function = "SGPS2";
+						groups = "SGPS2";
+					};
+
+					pinctrl_sioonctrl_default: sioonctrl_default {
+						function = "SIOONCTRL";
+						groups = "SIOONCTRL";
+					};
+
+					pinctrl_siopbi_default: siopbi_default {
+						function = "SIOPBI";
+						groups = "SIOPBI";
+					};
+
+					pinctrl_siopbo_default: siopbo_default {
+						function = "SIOPBO";
+						groups = "SIOPBO";
+					};
+
+					pinctrl_siopwreq_default: siopwreq_default {
+						function = "SIOPWREQ";
+						groups = "SIOPWREQ";
+					};
+
+					pinctrl_siopwrgd_default: siopwrgd_default {
+						function = "SIOPWRGD";
+						groups = "SIOPWRGD";
+					};
+
+					pinctrl_sios3_default: sios3_default {
+						function = "SIOS3";
+						groups = "SIOS3";
+					};
+
+					pinctrl_sios5_default: sios5_default {
+						function = "SIOS5";
+						groups = "SIOS5";
+					};
+
+					pinctrl_siosci_default: siosci_default {
+						function = "SIOSCI";
+						groups = "SIOSCI";
+					};
+
+					pinctrl_spi1_default: spi1_default {
+						function = "SPI1";
+						groups = "SPI1";
+					};
+
+					pinctrl_spi1cs1_default: spi1cs1_default {
+						function = "SPI1CS1";
+						groups = "SPI1CS1";
+					};
+
+					pinctrl_spi1debug_default: spi1debug_default {
+						function = "SPI1DEBUG";
+						groups = "SPI1DEBUG";
+					};
+
+					pinctrl_spi1passthru_default: spi1passthru_default {
+						function = "SPI1PASSTHRU";
+						groups = "SPI1PASSTHRU";
+					};
+
+					pinctrl_spi2ck_default: spi2ck_default {
+						function = "SPI2CK";
+						groups = "SPI2CK";
+					};
+
+					pinctrl_spi2cs0_default: spi2cs0_default {
+						function = "SPI2CS0";
+						groups = "SPI2CS0";
+					};
+
+					pinctrl_spi2cs1_default: spi2cs1_default {
+						function = "SPI2CS1";
+						groups = "SPI2CS1";
+					};
+
+					pinctrl_spi2miso_default: spi2miso_default {
+						function = "SPI2MISO";
+						groups = "SPI2MISO";
+					};
+
+					pinctrl_spi2mosi_default: spi2mosi_default {
+						function = "SPI2MOSI";
+						groups = "SPI2MOSI";
+					};
+
+					pinctrl_timer3_default: timer3_default {
+						function = "TIMER3";
+						groups = "TIMER3";
+					};
+
+					pinctrl_timer4_default: timer4_default {
+						function = "TIMER4";
+						groups = "TIMER4";
+					};
+
+					pinctrl_timer5_default: timer5_default {
+						function = "TIMER5";
+						groups = "TIMER5";
+					};
+
+					pinctrl_timer6_default: timer6_default {
+						function = "TIMER6";
+						groups = "TIMER6";
+					};
+
+					pinctrl_timer7_default: timer7_default {
+						function = "TIMER7";
+						groups = "TIMER7";
+					};
+
+					pinctrl_timer8_default: timer8_default {
+						function = "TIMER8";
+						groups = "TIMER8";
+					};
+
+					pinctrl_txd1_default: txd1_default {
+						function = "TXD1";
+						groups = "TXD1";
+					};
+
+					pinctrl_txd2_default: txd2_default {
+						function = "TXD2";
+						groups = "TXD2";
+					};
+
+					pinctrl_txd3_default: txd3_default {
+						function = "TXD3";
+						groups = "TXD3";
+					};
+
+					pinctrl_txd4_default: txd4_default {
+						function = "TXD4";
+						groups = "TXD4";
+					};
+
+					pinctrl_uart6_default: uart6_default {
+						function = "UART6";
+						groups = "UART6";
+					};
+
+					pinctrl_usbcki_default: usbcki_default {
+						function = "USBCKI";
+						groups = "USBCKI";
+					};
+
+					pinctrl_vgabiosrom_default: vgabiosrom_default {
+						function = "VGABIOSROM";
+						groups = "VGABIOSROM";
+					};
+
+					pinctrl_vgahs_default: vgahs_default {
+						function = "VGAHS";
+						groups = "VGAHS";
+					};
+
+					pinctrl_vgavs_default: vgavs_default {
+						function = "VGAVS";
+						groups = "VGAVS";
+					};
+
+					pinctrl_vpi24_default: vpi24_default {
+						function = "VPI24";
+						groups = "VPI24";
+					};
+
+					pinctrl_vpo_default: vpo_default {
+						function = "VPO";
+						groups = "VPO";
+					};
+
+					pinctrl_wdtrst1_default: wdtrst1_default {
+						function = "WDTRST1";
+						groups = "WDTRST1";
+					};
+
+					pinctrl_wdtrst2_default: wdtrst2_default {
+						function = "WDTRST2";
+						groups = "WDTRST2";
+					};
+
+				};
+			};
+
 			clk_hpll: clk_hpll@1e6e2024 {
 				#clock-cells = <0>;
 				compatible = "aspeed,g5-hpll-clock";
@@ -75,11 +907,27 @@
 				reg = <0x1e6e202c 0x4>;
 			};
 
+			gfx: display@1e6e6000 {
+				compatible = "aspeed,ast2500-gfx", "syscon";
+				reg = <0x1e6e6000 0x1000>;
+				reg-io-width = <4>;
+			};
+
 			sram@1e720000 {
 				compatible = "mmio-sram";
 				reg = <0x1e720000 0x9000>;	// 36K
 			};
 
+			gpio: gpio@1e780000 {
+				#gpio-cells = <2>;
+				gpio-controller;
+				compatible = "aspeed,ast2500-gpio";
+				reg = <0x1e780000 0x1000>;
+				interrupts = <20>;
+				gpio-ranges = <&pinctrl 0 0 220>;
+				interrupt-controller;
+			};
+
 			timer: timer@1e782000 {
 				compatible = "aspeed,ast2400-timer";
 				reg = <0x1e782000 0x90>;
@@ -90,6 +938,7 @@
 				clocks = <&clk_apb>;
 			};
 
+
 			wdt1: wdt@1e785000 {
 				compatible = "aspeed,wdt";
 				reg = <0x1e785000 0x1c>;
@@ -119,6 +968,36 @@
 				status = "disabled";
 			};
 
+			lpc: lpc@1e789000 {
+				compatible = "aspeed,ast2500-lpc", "simple-mfd";
+				reg = <0x1e789000 0x1000>;
+
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x1e789000 0x1000>;
+
+				lpc_bmc: lpc-bmc@0 {
+					compatible = "aspeed,ast2500-lpc-bmc";
+					reg = <0x0 0x80>;
+				};
+
+				lpc_host: lpc-host@80 {
+					compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
+					reg = <0x80 0x1e0>;
+
+					#address-cells = <1>;
+					#size-cells = <1>;
+					ranges = <0 0x80 0x1e0>;
+
+					reg-io-width = <4>;
+
+					lhc: lhc@20 {
+						compatible = "aspeed,ast2500-lhc";
+						reg = <0x20 0x24 0x48 0x8>;
+					};
+				};
+			};
+
 			uart2: serial@1e78d000 {
 				compatible = "ns16550a";
 				reg = <0x1e78d000 0x1000>;
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 01/15] aspeed: Update ast2500 Device Tree
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Pull in the Device Tree for ast2500 from the mainline Linux kernel.
The file is copied from
https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Added link to the original version to commit message

---
 arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 880 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/ast2500.dtsi b/arch/arm/dts/ast2500.dtsi
index 97fac69d11..7e0ad3a41a 100644
--- a/arch/arm/dts/ast2500.dtsi
+++ b/arch/arm/dts/ast2500.dtsi
@@ -1,6 +1,6 @@
 /*
  * This device tree is copied from
- * https://raw.githubusercontent.com/torvalds/linux/02440622/arch/arm/boot/dts/
+ * https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
  */
 #include "skeleton.dtsi"
 
@@ -36,6 +36,22 @@
 			reg = <0x1e6c0080 0x80>;
 		};
 
+		mac0: ethernet at 1e660000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e660000 0x180>;
+			interrupts = <2>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
+		mac1: ethernet at 1e680000 {
+			compatible = "faraday,ftgmac100";
+			reg = <0x1e680000 0x180>;
+			interrupts = <3>;
+			no-hw-checksum;
+			status = "disabled";
+		};
+
 		apb {
 			compatible = "simple-bus";
 			#address-cells = <1>;
@@ -48,6 +64,822 @@
 				reg = <0x1e6e2070 0x04>;
 			};
 
+			syscon: syscon at 1e6e2000 {
+				compatible = "aspeed,g5-scu", "syscon", "simple-mfd";
+				reg = <0x1e6e2000 0x1a8>;
+
+				pinctrl: pinctrl {
+					compatible = "aspeed,g5-pinctrl";
+					aspeed,external-nodes = <&gfx &lhc>;
+
+					pinctrl_acpi_default: acpi_default {
+						function = "ACPI";
+						groups = "ACPI";
+					};
+
+					pinctrl_adc0_default: adc0_default {
+						function = "ADC0";
+						groups = "ADC0";
+					};
+
+					pinctrl_adc1_default: adc1_default {
+						function = "ADC1";
+						groups = "ADC1";
+					};
+
+					pinctrl_adc10_default: adc10_default {
+						function = "ADC10";
+						groups = "ADC10";
+					};
+
+					pinctrl_adc11_default: adc11_default {
+						function = "ADC11";
+						groups = "ADC11";
+					};
+
+					pinctrl_adc12_default: adc12_default {
+						function = "ADC12";
+						groups = "ADC12";
+					};
+
+					pinctrl_adc13_default: adc13_default {
+						function = "ADC13";
+						groups = "ADC13";
+					};
+
+					pinctrl_adc14_default: adc14_default {
+						function = "ADC14";
+						groups = "ADC14";
+					};
+
+					pinctrl_adc15_default: adc15_default {
+						function = "ADC15";
+						groups = "ADC15";
+					};
+
+					pinctrl_adc2_default: adc2_default {
+						function = "ADC2";
+						groups = "ADC2";
+					};
+
+					pinctrl_adc3_default: adc3_default {
+						function = "ADC3";
+						groups = "ADC3";
+					};
+
+					pinctrl_adc4_default: adc4_default {
+						function = "ADC4";
+						groups = "ADC4";
+					};
+
+					pinctrl_adc5_default: adc5_default {
+						function = "ADC5";
+						groups = "ADC5";
+					};
+
+					pinctrl_adc6_default: adc6_default {
+						function = "ADC6";
+						groups = "ADC6";
+					};
+
+					pinctrl_adc7_default: adc7_default {
+						function = "ADC7";
+						groups = "ADC7";
+					};
+
+					pinctrl_adc8_default: adc8_default {
+						function = "ADC8";
+						groups = "ADC8";
+					};
+
+					pinctrl_adc9_default: adc9_default {
+						function = "ADC9";
+						groups = "ADC9";
+					};
+
+					pinctrl_bmcint_default: bmcint_default {
+						function = "BMCINT";
+						groups = "BMCINT";
+					};
+
+					pinctrl_ddcclk_default: ddcclk_default {
+						function = "DDCCLK";
+						groups = "DDCCLK";
+					};
+
+					pinctrl_ddcdat_default: ddcdat_default {
+						function = "DDCDAT";
+						groups = "DDCDAT";
+					};
+
+					pinctrl_espi_default: espi_default {
+						function = "ESPI";
+						groups = "ESPI";
+					};
+
+					pinctrl_fwspics1_default: fwspics1_default {
+						function = "FWSPICS1";
+						groups = "FWSPICS1";
+					};
+
+					pinctrl_fwspics2_default: fwspics2_default {
+						function = "FWSPICS2";
+						groups = "FWSPICS2";
+					};
+
+					pinctrl_gpid0_default: gpid0_default {
+						function = "GPID0";
+						groups = "GPID0";
+					};
+
+					pinctrl_gpid2_default: gpid2_default {
+						function = "GPID2";
+						groups = "GPID2";
+					};
+
+					pinctrl_gpid4_default: gpid4_default {
+						function = "GPID4";
+						groups = "GPID4";
+					};
+
+					pinctrl_gpid6_default: gpid6_default {
+						function = "GPID6";
+						groups = "GPID6";
+					};
+
+					pinctrl_gpie0_default: gpie0_default {
+						function = "GPIE0";
+						groups = "GPIE0";
+					};
+
+					pinctrl_gpie2_default: gpie2_default {
+						function = "GPIE2";
+						groups = "GPIE2";
+					};
+
+					pinctrl_gpie4_default: gpie4_default {
+						function = "GPIE4";
+						groups = "GPIE4";
+					};
+
+					pinctrl_gpie6_default: gpie6_default {
+						function = "GPIE6";
+						groups = "GPIE6";
+					};
+
+					pinctrl_i2c10_default: i2c10_default {
+						function = "I2C10";
+						groups = "I2C10";
+					};
+
+					pinctrl_i2c11_default: i2c11_default {
+						function = "I2C11";
+						groups = "I2C11";
+					};
+
+					pinctrl_i2c12_default: i2c12_default {
+						function = "I2C12";
+						groups = "I2C12";
+					};
+
+					pinctrl_i2c13_default: i2c13_default {
+						function = "I2C13";
+						groups = "I2C13";
+					};
+
+					pinctrl_i2c14_default: i2c14_default {
+						function = "I2C14";
+						groups = "I2C14";
+					};
+
+					pinctrl_i2c3_default: i2c3_default {
+						function = "I2C3";
+						groups = "I2C3";
+					};
+
+					pinctrl_i2c4_default: i2c4_default {
+						function = "I2C4";
+						groups = "I2C4";
+					};
+
+					pinctrl_i2c5_default: i2c5_default {
+						function = "I2C5";
+						groups = "I2C5";
+					};
+
+					pinctrl_i2c6_default: i2c6_default {
+						function = "I2C6";
+						groups = "I2C6";
+					};
+
+					pinctrl_i2c7_default: i2c7_default {
+						function = "I2C7";
+						groups = "I2C7";
+					};
+
+					pinctrl_i2c8_default: i2c8_default {
+						function = "I2C8";
+						groups = "I2C8";
+					};
+
+					pinctrl_i2c9_default: i2c9_default {
+						function = "I2C9";
+						groups = "I2C9";
+					};
+
+					pinctrl_lad0_default: lad0_default {
+						function = "LAD0";
+						groups = "LAD0";
+					};
+
+					pinctrl_lad1_default: lad1_default {
+						function = "LAD1";
+						groups = "LAD1";
+					};
+
+					pinctrl_lad2_default: lad2_default {
+						function = "LAD2";
+						groups = "LAD2";
+					};
+
+					pinctrl_lad3_default: lad3_default {
+						function = "LAD3";
+						groups = "LAD3";
+					};
+
+					pinctrl_lclk_default: lclk_default {
+						function = "LCLK";
+						groups = "LCLK";
+					};
+
+					pinctrl_lframe_default: lframe_default {
+						function = "LFRAME";
+						groups = "LFRAME";
+					};
+
+					pinctrl_lpchc_default: lpchc_default {
+						function = "LPCHC";
+						groups = "LPCHC";
+					};
+
+					pinctrl_lpcpd_default: lpcpd_default {
+						function = "LPCPD";
+						groups = "LPCPD";
+					};
+
+					pinctrl_lpcplus_default: lpcplus_default {
+						function = "LPCPLUS";
+						groups = "LPCPLUS";
+					};
+
+					pinctrl_lpcpme_default: lpcpme_default {
+						function = "LPCPME";
+						groups = "LPCPME";
+					};
+
+					pinctrl_lpcrst_default: lpcrst_default {
+						function = "LPCRST";
+						groups = "LPCRST";
+					};
+
+					pinctrl_lpcsmi_default: lpcsmi_default {
+						function = "LPCSMI";
+						groups = "LPCSMI";
+					};
+
+					pinctrl_lsirq_default: lsirq_default {
+						function = "LSIRQ";
+						groups = "LSIRQ";
+					};
+
+					pinctrl_mac1link_default: mac1link_default {
+						function = "MAC1LINK";
+						groups = "MAC1LINK";
+					};
+
+					pinctrl_mac2link_default: mac2link_default {
+						function = "MAC2LINK";
+						groups = "MAC2LINK";
+					};
+
+					pinctrl_mdio1_default: mdio1_default {
+						function = "MDIO1";
+						groups = "MDIO1";
+					};
+
+					pinctrl_mdio2_default: mdio2_default {
+						function = "MDIO2";
+						groups = "MDIO2";
+					};
+
+					pinctrl_ncts1_default: ncts1_default {
+						function = "NCTS1";
+						groups = "NCTS1";
+					};
+
+					pinctrl_ncts2_default: ncts2_default {
+						function = "NCTS2";
+						groups = "NCTS2";
+					};
+
+					pinctrl_ncts3_default: ncts3_default {
+						function = "NCTS3";
+						groups = "NCTS3";
+					};
+
+					pinctrl_ncts4_default: ncts4_default {
+						function = "NCTS4";
+						groups = "NCTS4";
+					};
+
+					pinctrl_ndcd1_default: ndcd1_default {
+						function = "NDCD1";
+						groups = "NDCD1";
+					};
+
+					pinctrl_ndcd2_default: ndcd2_default {
+						function = "NDCD2";
+						groups = "NDCD2";
+					};
+
+					pinctrl_ndcd3_default: ndcd3_default {
+						function = "NDCD3";
+						groups = "NDCD3";
+					};
+
+					pinctrl_ndcd4_default: ndcd4_default {
+						function = "NDCD4";
+						groups = "NDCD4";
+					};
+
+					pinctrl_ndsr1_default: ndsr1_default {
+						function = "NDSR1";
+						groups = "NDSR1";
+					};
+
+					pinctrl_ndsr2_default: ndsr2_default {
+						function = "NDSR2";
+						groups = "NDSR2";
+					};
+
+					pinctrl_ndsr3_default: ndsr3_default {
+						function = "NDSR3";
+						groups = "NDSR3";
+					};
+
+					pinctrl_ndsr4_default: ndsr4_default {
+						function = "NDSR4";
+						groups = "NDSR4";
+					};
+
+					pinctrl_ndtr1_default: ndtr1_default {
+						function = "NDTR1";
+						groups = "NDTR1";
+					};
+
+					pinctrl_ndtr2_default: ndtr2_default {
+						function = "NDTR2";
+						groups = "NDTR2";
+					};
+
+					pinctrl_ndtr3_default: ndtr3_default {
+						function = "NDTR3";
+						groups = "NDTR3";
+					};
+
+					pinctrl_ndtr4_default: ndtr4_default {
+						function = "NDTR4";
+						groups = "NDTR4";
+					};
+
+					pinctrl_nri1_default: nri1_default {
+						function = "NRI1";
+						groups = "NRI1";
+					};
+
+					pinctrl_nri2_default: nri2_default {
+						function = "NRI2";
+						groups = "NRI2";
+					};
+
+					pinctrl_nri3_default: nri3_default {
+						function = "NRI3";
+						groups = "NRI3";
+					};
+
+					pinctrl_nri4_default: nri4_default {
+						function = "NRI4";
+						groups = "NRI4";
+					};
+
+					pinctrl_nrts1_default: nrts1_default {
+						function = "NRTS1";
+						groups = "NRTS1";
+					};
+
+					pinctrl_nrts2_default: nrts2_default {
+						function = "NRTS2";
+						groups = "NRTS2";
+					};
+
+					pinctrl_nrts3_default: nrts3_default {
+						function = "NRTS3";
+						groups = "NRTS3";
+					};
+
+					pinctrl_nrts4_default: nrts4_default {
+						function = "NRTS4";
+						groups = "NRTS4";
+					};
+
+					pinctrl_oscclk_default: oscclk_default {
+						function = "OSCCLK";
+						groups = "OSCCLK";
+					};
+
+					pinctrl_pewake_default: pewake_default {
+						function = "PEWAKE";
+						groups = "PEWAKE";
+					};
+
+					pinctrl_pnor_default: pnor_default {
+						function = "PNOR";
+						groups = "PNOR";
+					};
+
+					pinctrl_pwm0_default: pwm0_default {
+						function = "PWM0";
+						groups = "PWM0";
+					};
+
+					pinctrl_pwm1_default: pwm1_default {
+						function = "PWM1";
+						groups = "PWM1";
+					};
+
+					pinctrl_pwm2_default: pwm2_default {
+						function = "PWM2";
+						groups = "PWM2";
+					};
+
+					pinctrl_pwm3_default: pwm3_default {
+						function = "PWM3";
+						groups = "PWM3";
+					};
+
+					pinctrl_pwm4_default: pwm4_default {
+						function = "PWM4";
+						groups = "PWM4";
+					};
+
+					pinctrl_pwm5_default: pwm5_default {
+						function = "PWM5";
+						groups = "PWM5";
+					};
+
+					pinctrl_pwm6_default: pwm6_default {
+						function = "PWM6";
+						groups = "PWM6";
+					};
+
+					pinctrl_pwm7_default: pwm7_default {
+						function = "PWM7";
+						groups = "PWM7";
+					};
+
+					pinctrl_rgmii1_default: rgmii1_default {
+						function = "RGMII1";
+						groups = "RGMII1";
+					};
+
+					pinctrl_rgmii2_default: rgmii2_default {
+						function = "RGMII2";
+						groups = "RGMII2";
+					};
+
+					pinctrl_rmii1_default: rmii1_default {
+						function = "RMII1";
+						groups = "RMII1";
+					};
+
+					pinctrl_rmii2_default: rmii2_default {
+						function = "RMII2";
+						groups = "RMII2";
+					};
+
+					pinctrl_rxd1_default: rxd1_default {
+						function = "RXD1";
+						groups = "RXD1";
+					};
+
+					pinctrl_rxd2_default: rxd2_default {
+						function = "RXD2";
+						groups = "RXD2";
+					};
+
+					pinctrl_rxd3_default: rxd3_default {
+						function = "RXD3";
+						groups = "RXD3";
+					};
+
+					pinctrl_rxd4_default: rxd4_default {
+						function = "RXD4";
+						groups = "RXD4";
+					};
+
+					pinctrl_salt1_default: salt1_default {
+						function = "SALT1";
+						groups = "SALT1";
+					};
+
+					pinctrl_salt10_default: salt10_default {
+						function = "SALT10";
+						groups = "SALT10";
+					};
+
+					pinctrl_salt11_default: salt11_default {
+						function = "SALT11";
+						groups = "SALT11";
+					};
+
+					pinctrl_salt12_default: salt12_default {
+						function = "SALT12";
+						groups = "SALT12";
+					};
+
+					pinctrl_salt13_default: salt13_default {
+						function = "SALT13";
+						groups = "SALT13";
+					};
+
+					pinctrl_salt14_default: salt14_default {
+						function = "SALT14";
+						groups = "SALT14";
+					};
+
+					pinctrl_salt2_default: salt2_default {
+						function = "SALT2";
+						groups = "SALT2";
+					};
+
+					pinctrl_salt3_default: salt3_default {
+						function = "SALT3";
+						groups = "SALT3";
+					};
+
+					pinctrl_salt4_default: salt4_default {
+						function = "SALT4";
+						groups = "SALT4";
+					};
+
+					pinctrl_salt5_default: salt5_default {
+						function = "SALT5";
+						groups = "SALT5";
+					};
+
+					pinctrl_salt6_default: salt6_default {
+						function = "SALT6";
+						groups = "SALT6";
+					};
+
+					pinctrl_salt7_default: salt7_default {
+						function = "SALT7";
+						groups = "SALT7";
+					};
+
+					pinctrl_salt8_default: salt8_default {
+						function = "SALT8";
+						groups = "SALT8";
+					};
+
+					pinctrl_salt9_default: salt9_default {
+						function = "SALT9";
+						groups = "SALT9";
+					};
+
+					pinctrl_scl1_default: scl1_default {
+						function = "SCL1";
+						groups = "SCL1";
+					};
+
+					pinctrl_scl2_default: scl2_default {
+						function = "SCL2";
+						groups = "SCL2";
+					};
+
+					pinctrl_sd1_default: sd1_default {
+						function = "SD1";
+						groups = "SD1";
+					};
+
+					pinctrl_sd2_default: sd2_default {
+						function = "SD2";
+						groups = "SD2";
+					};
+
+					pinctrl_sda1_default: sda1_default {
+						function = "SDA1";
+						groups = "SDA1";
+					};
+
+					pinctrl_sda2_default: sda2_default {
+						function = "SDA2";
+						groups = "SDA2";
+					};
+
+					pinctrl_sgps1_default: sgps1_default {
+						function = "SGPS1";
+						groups = "SGPS1";
+					};
+
+					pinctrl_sgps2_default: sgps2_default {
+						function = "SGPS2";
+						groups = "SGPS2";
+					};
+
+					pinctrl_sioonctrl_default: sioonctrl_default {
+						function = "SIOONCTRL";
+						groups = "SIOONCTRL";
+					};
+
+					pinctrl_siopbi_default: siopbi_default {
+						function = "SIOPBI";
+						groups = "SIOPBI";
+					};
+
+					pinctrl_siopbo_default: siopbo_default {
+						function = "SIOPBO";
+						groups = "SIOPBO";
+					};
+
+					pinctrl_siopwreq_default: siopwreq_default {
+						function = "SIOPWREQ";
+						groups = "SIOPWREQ";
+					};
+
+					pinctrl_siopwrgd_default: siopwrgd_default {
+						function = "SIOPWRGD";
+						groups = "SIOPWRGD";
+					};
+
+					pinctrl_sios3_default: sios3_default {
+						function = "SIOS3";
+						groups = "SIOS3";
+					};
+
+					pinctrl_sios5_default: sios5_default {
+						function = "SIOS5";
+						groups = "SIOS5";
+					};
+
+					pinctrl_siosci_default: siosci_default {
+						function = "SIOSCI";
+						groups = "SIOSCI";
+					};
+
+					pinctrl_spi1_default: spi1_default {
+						function = "SPI1";
+						groups = "SPI1";
+					};
+
+					pinctrl_spi1cs1_default: spi1cs1_default {
+						function = "SPI1CS1";
+						groups = "SPI1CS1";
+					};
+
+					pinctrl_spi1debug_default: spi1debug_default {
+						function = "SPI1DEBUG";
+						groups = "SPI1DEBUG";
+					};
+
+					pinctrl_spi1passthru_default: spi1passthru_default {
+						function = "SPI1PASSTHRU";
+						groups = "SPI1PASSTHRU";
+					};
+
+					pinctrl_spi2ck_default: spi2ck_default {
+						function = "SPI2CK";
+						groups = "SPI2CK";
+					};
+
+					pinctrl_spi2cs0_default: spi2cs0_default {
+						function = "SPI2CS0";
+						groups = "SPI2CS0";
+					};
+
+					pinctrl_spi2cs1_default: spi2cs1_default {
+						function = "SPI2CS1";
+						groups = "SPI2CS1";
+					};
+
+					pinctrl_spi2miso_default: spi2miso_default {
+						function = "SPI2MISO";
+						groups = "SPI2MISO";
+					};
+
+					pinctrl_spi2mosi_default: spi2mosi_default {
+						function = "SPI2MOSI";
+						groups = "SPI2MOSI";
+					};
+
+					pinctrl_timer3_default: timer3_default {
+						function = "TIMER3";
+						groups = "TIMER3";
+					};
+
+					pinctrl_timer4_default: timer4_default {
+						function = "TIMER4";
+						groups = "TIMER4";
+					};
+
+					pinctrl_timer5_default: timer5_default {
+						function = "TIMER5";
+						groups = "TIMER5";
+					};
+
+					pinctrl_timer6_default: timer6_default {
+						function = "TIMER6";
+						groups = "TIMER6";
+					};
+
+					pinctrl_timer7_default: timer7_default {
+						function = "TIMER7";
+						groups = "TIMER7";
+					};
+
+					pinctrl_timer8_default: timer8_default {
+						function = "TIMER8";
+						groups = "TIMER8";
+					};
+
+					pinctrl_txd1_default: txd1_default {
+						function = "TXD1";
+						groups = "TXD1";
+					};
+
+					pinctrl_txd2_default: txd2_default {
+						function = "TXD2";
+						groups = "TXD2";
+					};
+
+					pinctrl_txd3_default: txd3_default {
+						function = "TXD3";
+						groups = "TXD3";
+					};
+
+					pinctrl_txd4_default: txd4_default {
+						function = "TXD4";
+						groups = "TXD4";
+					};
+
+					pinctrl_uart6_default: uart6_default {
+						function = "UART6";
+						groups = "UART6";
+					};
+
+					pinctrl_usbcki_default: usbcki_default {
+						function = "USBCKI";
+						groups = "USBCKI";
+					};
+
+					pinctrl_vgabiosrom_default: vgabiosrom_default {
+						function = "VGABIOSROM";
+						groups = "VGABIOSROM";
+					};
+
+					pinctrl_vgahs_default: vgahs_default {
+						function = "VGAHS";
+						groups = "VGAHS";
+					};
+
+					pinctrl_vgavs_default: vgavs_default {
+						function = "VGAVS";
+						groups = "VGAVS";
+					};
+
+					pinctrl_vpi24_default: vpi24_default {
+						function = "VPI24";
+						groups = "VPI24";
+					};
+
+					pinctrl_vpo_default: vpo_default {
+						function = "VPO";
+						groups = "VPO";
+					};
+
+					pinctrl_wdtrst1_default: wdtrst1_default {
+						function = "WDTRST1";
+						groups = "WDTRST1";
+					};
+
+					pinctrl_wdtrst2_default: wdtrst2_default {
+						function = "WDTRST2";
+						groups = "WDTRST2";
+					};
+
+				};
+			};
+
 			clk_hpll: clk_hpll at 1e6e2024 {
 				#clock-cells = <0>;
 				compatible = "aspeed,g5-hpll-clock";
@@ -75,11 +907,27 @@
 				reg = <0x1e6e202c 0x4>;
 			};
 
+			gfx: display at 1e6e6000 {
+				compatible = "aspeed,ast2500-gfx", "syscon";
+				reg = <0x1e6e6000 0x1000>;
+				reg-io-width = <4>;
+			};
+
 			sram at 1e720000 {
 				compatible = "mmio-sram";
 				reg = <0x1e720000 0x9000>;	// 36K
 			};
 
+			gpio: gpio at 1e780000 {
+				#gpio-cells = <2>;
+				gpio-controller;
+				compatible = "aspeed,ast2500-gpio";
+				reg = <0x1e780000 0x1000>;
+				interrupts = <20>;
+				gpio-ranges = <&pinctrl 0 0 220>;
+				interrupt-controller;
+			};
+
 			timer: timer at 1e782000 {
 				compatible = "aspeed,ast2400-timer";
 				reg = <0x1e782000 0x90>;
@@ -90,6 +938,7 @@
 				clocks = <&clk_apb>;
 			};
 
+
 			wdt1: wdt at 1e785000 {
 				compatible = "aspeed,wdt";
 				reg = <0x1e785000 0x1c>;
@@ -119,6 +968,36 @@
 				status = "disabled";
 			};
 
+			lpc: lpc at 1e789000 {
+				compatible = "aspeed,ast2500-lpc", "simple-mfd";
+				reg = <0x1e789000 0x1000>;
+
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x1e789000 0x1000>;
+
+				lpc_bmc: lpc-bmc at 0 {
+					compatible = "aspeed,ast2500-lpc-bmc";
+					reg = <0x0 0x80>;
+				};
+
+				lpc_host: lpc-host at 80 {
+					compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
+					reg = <0x80 0x1e0>;
+
+					#address-cells = <1>;
+					#size-cells = <1>;
+					ranges = <0 0x80 0x1e0>;
+
+					reg-io-width = <4>;
+
+					lhc: lhc at 20 {
+						compatible = "aspeed,ast2500-lhc";
+						reg = <0x20 0x24 0x48 0x8>;
+					};
+				};
+			};
+
 			uart2: serial at 1e78d000 {
 				compatible = "ns16550a";
 				reg = <0x1e78d000 0x1000>;
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 02/15] dm: Simple Watchdog uclass
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Stephen Warren

This is a simple uclass for Watchdog Timers. It has four operations:
start, restart, reset, stop. Drivers must implement start, restart and
stop operations, while implementing reset is optional: It's default
implementation expires watchdog timer in one clock tick.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2:
- Remove "probe" function from sandbox wdt driver
- Fix include order

Changes in v1:
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests


---
 arch/sandbox/dts/test.dts        |   4 ++
 arch/sandbox/include/asm/state.h |   9 ++++
 configs/sandbox_defconfig        |   2 +
 drivers/watchdog/Kconfig         |  21 ++++++++
 drivers/watchdog/Makefile        |   2 +
 drivers/watchdog/sandbox_wdt.c   |  66 ++++++++++++++++++++++++
 drivers/watchdog/wdt-uclass.c    |  72 ++++++++++++++++++++++++++
 include/dm/uclass-id.h           |   1 +
 include/wdt.h                    | 107 +++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile                 |   1 +
 test/dm/wdt.c                    |  40 +++++++++++++++
 11 files changed, 325 insertions(+)
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fff175d1b7..e04ecc64cc 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -418,6 +418,10 @@
 			};
 		};
 	};
+
+	wdt0: wdt@0 {
+		compatible = "sandbox,wdt";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 149f28d873..987cc7b49d 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -39,6 +39,12 @@ struct sandbox_spi_info {
 	struct udevice *emul;
 };
 
+struct sandbox_wdt_info {
+	unsigned long long counter;
+	uint reset_count;
+	bool running;
+};
+
 /* The complete state of the test system */
 struct sandbox_state {
 	const char *cmd;		/* Command to execute */
@@ -69,6 +75,9 @@ struct sandbox_state {
 	/* Pointer to information for each SPI bus/cs */
 	struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
 					[CONFIG_SANDBOX_SPI_MAX_CS];
+
+	/* Information about Watchdog */
+	struct sandbox_wdt_info wdt;
 };
 
 /* Minimum space we guarantee in the state FDT when calling read/write*/
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 01f6f5d5c6..a5f63e027f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -171,3 +171,5 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_WDT=y
+CONFIG_WDT_SANDBOX=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e69de29bb2..7a725f1e6d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -0,0 +1,21 @@
+menu "Watchdog Timer Support"
+
+config WDT
+	bool "Enable driver model for watchdog timer drivers"
+	depends on DM
+	help
+	  Enable driver model for watchdog timer. At the moment the API
+	  is very simple and only supports four operations:
+	  start, restart, stop and reset (expire immediately).
+	  What exactly happens when the timer expires is up to a particular
+	  device/driver.
+
+config WDT_SANDBOX
+	bool "Enable Watchdog Timer support for Sandbox"
+	depends on SANDBOX && WDT
+	help
+		Enable Watchdog Timer support in Sandbox. This is a dummy device that
+		can be probed and supports all of the methods of WDT, but does not
+		really do anything.
+
+endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a007ae8234..f523d34d57 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -15,3 +15,5 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
 obj-$(CONFIG_BFIN_WATCHDOG)  += bfin_wdt.o
 obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
+obj-$(CONFIG_WDT) += wdt-uclass.o
+obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
diff --git a/drivers/watchdog/sandbox_wdt.c b/drivers/watchdog/sandbox_wdt.c
new file mode 100644
index 0000000000..02b57f3986
--- /dev/null
+++ b/drivers/watchdog/sandbox_wdt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.counter = timeout;
+	state->wdt.running = true;
+
+	return 0;
+}
+
+static int sandbox_wdt_stop(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.running = false;
+
+	return 0;
+}
+
+static int sandbox_wdt_reset(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.reset_count++;
+
+	return 0;
+}
+
+static int sandbox_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	sandbox_wdt_start(dev, 1, flags);
+
+	return 0;
+}
+
+static const struct wdt_ops sandbox_wdt_ops = {
+	.start = sandbox_wdt_start,
+	.reset = sandbox_wdt_reset,
+	.stop = sandbox_wdt_stop,
+	.expire_now = sandbox_wdt_expire_now,
+};
+
+static const struct udevice_id sandbox_wdt_ids[] = {
+	{ .compatible = "sandbox,wdt" },
+	{}
+};
+
+U_BOOT_DRIVER(wdt_sandbox) = {
+	.name = "wdt_sandbox",
+	.id = UCLASS_WDT,
+	.of_match = sandbox_wdt_ids,
+	.ops = &sandbox_wdt_ops,
+};
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
new file mode 100644
index 0000000000..ab8a64c354
--- /dev/null
+++ b/drivers/watchdog/wdt-uclass.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->start)
+		return -ENOSYS;
+
+	return ops->start(dev, timeout, flags);
+}
+
+int wdt_stop(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->stop)
+		return -ENOSYS;
+
+	return ops->stop(dev);
+}
+
+int wdt_reset(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->reset)
+		return -ENOSYS;
+
+	return ops->reset(dev);
+}
+
+int wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	int ret = 0;
+	const struct wdt_ops *ops;
+
+	debug("WDT Resettting: %lu\n", flags);
+	ops = device_get_ops(dev);
+	if (ops->expire_now) {
+		return ops->expire_now(dev, flags);
+	} else {
+		if (!ops->start)
+			return -ENOSYS;
+
+		ret = ops->start(dev, 1, flags);
+		if (ret < 0)
+			return ret;
+
+		hang();
+	}
+
+	return ret;
+}
+
+UCLASS_DRIVER(wdt) = {
+	.id		= UCLASS_WDT,
+	.name		= "wdt",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8c92d0b030..b73a7fd436 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -83,6 +83,7 @@ enum uclass_id {
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
+	UCLASS_WDT,		/* Watchdot Timer driver */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/wdt.h b/include/wdt.h
new file mode 100644
index 0000000000..0b5f05851a
--- /dev/null
+++ b/include/wdt.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _WDT_H_
+#define _WDT_H_
+
+/*
+ * Implement a simple watchdog uclass. Watchdog is basically a timer that
+ * is used to detect or recover from malfunction. During normal operation
+ * the watchdog would be regularly reset to prevent it from timing out.
+ * If, due to a hardware fault or program error, the computer fails to reset
+ * the watchdog, the timer will elapse and generate a timeout signal.
+ * The timeout signal is used to initiate corrective action or actions,
+ * which typically include placing the system in a safe, known state.
+ */
+
+/*
+ * Start the timer
+ *
+ * @dev: WDT Device
+ * @timeout: Number of ticks before timer expires
+ * @flags: Driver specific flags. This might be used to specify
+ * which action needs to be executed when the timer expires
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags);
+
+/*
+ * Stop the timer, thus disabling the Watchdog. Use wdt_start to start it again.
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_stop(struct udevice *dev);
+
+/*
+ * Reset the timer, typically restoring the counter to
+ * the value configured by start()
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_reset(struct udevice *dev);
+
+/*
+ * Expire the timer, thus executing its action immediately.
+ * This is typically used to reset the board or peripherals.
+ *
+ * @dev: WDT Device
+ * @flags: Driver specific flags
+ * @return 0 if OK -ve on error. If wdt action is system reset,
+ * this function may never return.
+ */
+int wdt_expire_now(struct udevice *dev, ulong flags);
+
+/*
+ * struct wdt_ops - Driver model wdt operations
+ *
+ * The uclass interface is implemented by all wdt devices which use
+ * driver model.
+ */
+struct wdt_ops {
+	/*
+	 * Start the timer
+	 *
+	 * @dev: WDT Device
+	 * @timeout: Number of ticks before the timer expires
+	 * @flags: Driver specific flags. This might be used to specify
+	 * which action needs to be executed when the timer expires
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*start)(struct udevice *dev, u64 timeout, ulong flags);
+	/*
+	 * Stop the timer
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*stop)(struct udevice *dev);
+	/*
+	 * Reset the timer, typically restoring the counter to
+	 * the value configured by start()
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*reset)(struct udevice *dev);
+	/*
+	 * Expire the timer, thus executing the action immediately (optional)
+	 *
+	 * If this function is not provided, a default implementation
+	 * will be used, which sets the counter to 1
+	 * and waits forever. This is good enough for system level
+	 * reset, where the function is not expected to return, but might not be
+	 * good enough for other use cases.
+	 *
+	 * @dev: WDT Device
+	 * @flags: Driver specific flags
+	 * @return 0 if OK -ve on error. May not return.
+	 */
+	int (*expire_now)(struct udevice *dev, ulong flags);
+};
+
+#endif  /* _WDT_H_ */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1885e17c38..78d14c27e6 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -41,4 +41,5 @@ obj-$(CONFIG_TIMER) += timer.o
 obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 obj-$(CONFIG_SPMI) += spmi.o
+obj-$(CONFIG_WDT) += wdt.o
 endif
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
new file mode 100644
index 0000000000..2ecfceaaff
--- /dev/null
+++ b/test/dm/wdt.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Test that watchdog driver functions are called */
+static int dm_test_wdt_base(struct unit_test_state *uts)
+{
+	struct sandbox_state *state = state_get_current();
+	struct udevice *dev;
+	const u64 timeout = 42;
+
+	ut_assertok(uclass_get_device(UCLASS_WDT, 0, &dev));
+	ut_asserteq(0, state->wdt.counter);
+	ut_asserteq(false, state->wdt.running);
+
+	ut_assertok(wdt_start(dev, timeout, 0));
+	ut_asserteq(timeout, state->wdt.counter);
+	ut_asserteq(true, state->wdt.running);
+
+	uint reset_count = state->wdt.reset_count;
+	ut_assertok(wdt_reset(dev));
+	ut_asserteq(reset_count + 1, state->wdt.reset_count);
+	ut_asserteq(true, state->wdt.running);
+
+	ut_assertok(wdt_stop(dev));
+	ut_asserteq(false, state->wdt.running);
+
+	return 0;
+}
+DM_TEST(dm_test_wdt_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 02/15] dm: Simple Watchdog uclass
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

This is a simple uclass for Watchdog Timers. It has four operations:
start, restart, reset, stop. Drivers must implement start, restart and
stop operations, while implementing reset is optional: It's default
implementation expires watchdog timer in one clock tick.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2:
- Remove "probe" function from sandbox wdt driver
- Fix include order

Changes in v1:
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests


---
 arch/sandbox/dts/test.dts        |   4 ++
 arch/sandbox/include/asm/state.h |   9 ++++
 configs/sandbox_defconfig        |   2 +
 drivers/watchdog/Kconfig         |  21 ++++++++
 drivers/watchdog/Makefile        |   2 +
 drivers/watchdog/sandbox_wdt.c   |  66 ++++++++++++++++++++++++
 drivers/watchdog/wdt-uclass.c    |  72 ++++++++++++++++++++++++++
 include/dm/uclass-id.h           |   1 +
 include/wdt.h                    | 107 +++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile                 |   1 +
 test/dm/wdt.c                    |  40 +++++++++++++++
 11 files changed, 325 insertions(+)
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fff175d1b7..e04ecc64cc 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -418,6 +418,10 @@
 			};
 		};
 	};
+
+	wdt0: wdt at 0 {
+		compatible = "sandbox,wdt";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 149f28d873..987cc7b49d 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -39,6 +39,12 @@ struct sandbox_spi_info {
 	struct udevice *emul;
 };
 
+struct sandbox_wdt_info {
+	unsigned long long counter;
+	uint reset_count;
+	bool running;
+};
+
 /* The complete state of the test system */
 struct sandbox_state {
 	const char *cmd;		/* Command to execute */
@@ -69,6 +75,9 @@ struct sandbox_state {
 	/* Pointer to information for each SPI bus/cs */
 	struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
 					[CONFIG_SANDBOX_SPI_MAX_CS];
+
+	/* Information about Watchdog */
+	struct sandbox_wdt_info wdt;
 };
 
 /* Minimum space we guarantee in the state FDT when calling read/write*/
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 01f6f5d5c6..a5f63e027f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -171,3 +171,5 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_WDT=y
+CONFIG_WDT_SANDBOX=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e69de29bb2..7a725f1e6d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -0,0 +1,21 @@
+menu "Watchdog Timer Support"
+
+config WDT
+	bool "Enable driver model for watchdog timer drivers"
+	depends on DM
+	help
+	  Enable driver model for watchdog timer. At the moment the API
+	  is very simple and only supports four operations:
+	  start, restart, stop and reset (expire immediately).
+	  What exactly happens when the timer expires is up to a particular
+	  device/driver.
+
+config WDT_SANDBOX
+	bool "Enable Watchdog Timer support for Sandbox"
+	depends on SANDBOX && WDT
+	help
+		Enable Watchdog Timer support in Sandbox. This is a dummy device that
+		can be probed and supports all of the methods of WDT, but does not
+		really do anything.
+
+endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a007ae8234..f523d34d57 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -15,3 +15,5 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
 obj-$(CONFIG_BFIN_WATCHDOG)  += bfin_wdt.o
 obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
+obj-$(CONFIG_WDT) += wdt-uclass.o
+obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
diff --git a/drivers/watchdog/sandbox_wdt.c b/drivers/watchdog/sandbox_wdt.c
new file mode 100644
index 0000000000..02b57f3986
--- /dev/null
+++ b/drivers/watchdog/sandbox_wdt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.counter = timeout;
+	state->wdt.running = true;
+
+	return 0;
+}
+
+static int sandbox_wdt_stop(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.running = false;
+
+	return 0;
+}
+
+static int sandbox_wdt_reset(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.reset_count++;
+
+	return 0;
+}
+
+static int sandbox_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	sandbox_wdt_start(dev, 1, flags);
+
+	return 0;
+}
+
+static const struct wdt_ops sandbox_wdt_ops = {
+	.start = sandbox_wdt_start,
+	.reset = sandbox_wdt_reset,
+	.stop = sandbox_wdt_stop,
+	.expire_now = sandbox_wdt_expire_now,
+};
+
+static const struct udevice_id sandbox_wdt_ids[] = {
+	{ .compatible = "sandbox,wdt" },
+	{}
+};
+
+U_BOOT_DRIVER(wdt_sandbox) = {
+	.name = "wdt_sandbox",
+	.id = UCLASS_WDT,
+	.of_match = sandbox_wdt_ids,
+	.ops = &sandbox_wdt_ops,
+};
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
new file mode 100644
index 0000000000..ab8a64c354
--- /dev/null
+++ b/drivers/watchdog/wdt-uclass.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->start)
+		return -ENOSYS;
+
+	return ops->start(dev, timeout, flags);
+}
+
+int wdt_stop(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->stop)
+		return -ENOSYS;
+
+	return ops->stop(dev);
+}
+
+int wdt_reset(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->reset)
+		return -ENOSYS;
+
+	return ops->reset(dev);
+}
+
+int wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	int ret = 0;
+	const struct wdt_ops *ops;
+
+	debug("WDT Resettting: %lu\n", flags);
+	ops = device_get_ops(dev);
+	if (ops->expire_now) {
+		return ops->expire_now(dev, flags);
+	} else {
+		if (!ops->start)
+			return -ENOSYS;
+
+		ret = ops->start(dev, 1, flags);
+		if (ret < 0)
+			return ret;
+
+		hang();
+	}
+
+	return ret;
+}
+
+UCLASS_DRIVER(wdt) = {
+	.id		= UCLASS_WDT,
+	.name		= "wdt",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8c92d0b030..b73a7fd436 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -83,6 +83,7 @@ enum uclass_id {
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
+	UCLASS_WDT,		/* Watchdot Timer driver */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/wdt.h b/include/wdt.h
new file mode 100644
index 0000000000..0b5f05851a
--- /dev/null
+++ b/include/wdt.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _WDT_H_
+#define _WDT_H_
+
+/*
+ * Implement a simple watchdog uclass. Watchdog is basically a timer that
+ * is used to detect or recover from malfunction. During normal operation
+ * the watchdog would be regularly reset to prevent it from timing out.
+ * If, due to a hardware fault or program error, the computer fails to reset
+ * the watchdog, the timer will elapse and generate a timeout signal.
+ * The timeout signal is used to initiate corrective action or actions,
+ * which typically include placing the system in a safe, known state.
+ */
+
+/*
+ * Start the timer
+ *
+ * @dev: WDT Device
+ * @timeout: Number of ticks before timer expires
+ * @flags: Driver specific flags. This might be used to specify
+ * which action needs to be executed when the timer expires
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags);
+
+/*
+ * Stop the timer, thus disabling the Watchdog. Use wdt_start to start it again.
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_stop(struct udevice *dev);
+
+/*
+ * Reset the timer, typically restoring the counter to
+ * the value configured by start()
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_reset(struct udevice *dev);
+
+/*
+ * Expire the timer, thus executing its action immediately.
+ * This is typically used to reset the board or peripherals.
+ *
+ * @dev: WDT Device
+ * @flags: Driver specific flags
+ * @return 0 if OK -ve on error. If wdt action is system reset,
+ * this function may never return.
+ */
+int wdt_expire_now(struct udevice *dev, ulong flags);
+
+/*
+ * struct wdt_ops - Driver model wdt operations
+ *
+ * The uclass interface is implemented by all wdt devices which use
+ * driver model.
+ */
+struct wdt_ops {
+	/*
+	 * Start the timer
+	 *
+	 * @dev: WDT Device
+	 * @timeout: Number of ticks before the timer expires
+	 * @flags: Driver specific flags. This might be used to specify
+	 * which action needs to be executed when the timer expires
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*start)(struct udevice *dev, u64 timeout, ulong flags);
+	/*
+	 * Stop the timer
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*stop)(struct udevice *dev);
+	/*
+	 * Reset the timer, typically restoring the counter to
+	 * the value configured by start()
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*reset)(struct udevice *dev);
+	/*
+	 * Expire the timer, thus executing the action immediately (optional)
+	 *
+	 * If this function is not provided, a default implementation
+	 * will be used, which sets the counter to 1
+	 * and waits forever. This is good enough for system level
+	 * reset, where the function is not expected to return, but might not be
+	 * good enough for other use cases.
+	 *
+	 * @dev: WDT Device
+	 * @flags: Driver specific flags
+	 * @return 0 if OK -ve on error. May not return.
+	 */
+	int (*expire_now)(struct udevice *dev, ulong flags);
+};
+
+#endif  /* _WDT_H_ */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1885e17c38..78d14c27e6 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -41,4 +41,5 @@ obj-$(CONFIG_TIMER) += timer.o
 obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 obj-$(CONFIG_SPMI) += spmi.o
+obj-$(CONFIG_WDT) += wdt.o
 endif
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
new file mode 100644
index 0000000000..2ecfceaaff
--- /dev/null
+++ b/test/dm/wdt.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Test that watchdog driver functions are called */
+static int dm_test_wdt_base(struct unit_test_state *uts)
+{
+	struct sandbox_state *state = state_get_current();
+	struct udevice *dev;
+	const u64 timeout = 42;
+
+	ut_assertok(uclass_get_device(UCLASS_WDT, 0, &dev));
+	ut_asserteq(0, state->wdt.counter);
+	ut_asserteq(false, state->wdt.running);
+
+	ut_assertok(wdt_start(dev, timeout, 0));
+	ut_asserteq(timeout, state->wdt.counter);
+	ut_asserteq(true, state->wdt.running);
+
+	uint reset_count = state->wdt.reset_count;
+	ut_assertok(wdt_reset(dev));
+	ut_asserteq(reset_count + 1, state->wdt.reset_count);
+	ut_asserteq(true, state->wdt.running);
+
+	ut_assertok(wdt_stop(dev));
+	ut_asserteq(false, state->wdt.running);
+
+	return 0;
+}
+DM_TEST(dm_test_wdt_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 03/15] aspeed: Watchdog Timer Driver
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

This driver supports ast2500 and ast2400 SoCs.
Only ast2500 supports reset_mask and thus the option of resettting
individual peripherals using WDT.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Rename reset to expire_now
- Rename restart to reset


---
 arch/arm/include/asm/arch-aspeed/wdt.h |  53 ++++++++++++--
 arch/arm/mach-aspeed/ast_wdt.c         |  40 ++++++++---
 drivers/watchdog/Kconfig               |  11 +++
 drivers/watchdog/Makefile              |   1 +
 drivers/watchdog/ast_wdt.c             | 125 +++++++++++++++++++++++++++++++++
 5 files changed, 217 insertions(+), 13 deletions(-)
 create mode 100644 drivers/watchdog/ast_wdt.c

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index b292a0e67b..981fa05a56 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -67,15 +67,60 @@ struct ast_wdt {
 	u32 timeout_status;
 	u32 clr_timeout_status;
 	u32 reset_width;
-#ifdef CONFIG_ASPEED_AST2500
+	/* On pre-ast2500 SoCs this register is reserved. */
 	u32 reset_mask;
-#else
-	u32 reserved0;
-#endif
 };
 
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mode value from it.
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mode value
+ */
+u32 ast_reset_mode_from_flags(ulong flags);
+
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mask value from it. Reset Mask is only supported on ast2500
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mask value
+ */
+u32 ast_reset_mask_from_flags(ulong flags);
+
+/**
+ * Given Reset Mask and Reset Mode values, converts them to flags,
+ * suitable for passing into wdt_start or wdt_reset uclass functions.
+ *
+ * On ast2500 Reset Mask is 25 bits wide and Reset Mode is 2 bits wide, so they
+ * can both be packed into single 32 bits wide value.
+ *
+ * @reset_mode: Reset Mode
+ * @reset_mask: Reset Mask
+ */
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
+
+#ifndef CONFIG_WDT
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to stop
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_stop(struct ast_wdt *wdt);
+
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to start
+ * @timeout	watchdog timeout in number of clock ticks
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_start(struct ast_wdt *wdt, u32 timeout);
+#endif  /* CONFIG_WDT */
 
 /**
  * Reset peripherals specified by mask
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 22481ab7ea..895fba3366 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -9,6 +9,27 @@
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
+u32 ast_reset_mode_from_flags(ulong flags)
+{
+	return flags & WDT_CTRL_RESET_MASK;
+}
+
+u32 ast_reset_mask_from_flags(ulong flags)
+{
+	return flags >> 2;
+}
+
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
+{
+	ulong ret = reset_mode & WDT_CTRL_RESET_MASK;
+
+	if (ret == WDT_CTRL_RESET_SOC)
+		ret |= (reset_mask << 2);
+
+	return ret;
+}
+
+#ifndef CONFIG_WDT
 void wdt_stop(struct ast_wdt *wdt)
 {
 	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
@@ -26,15 +47,7 @@ void wdt_start(struct ast_wdt *wdt, u32 timeout)
 	setbits_le32(&wdt->ctrl,
 		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
 }
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
+#endif  /* CONFIG_WDT */
 
 int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 {
@@ -57,3 +70,12 @@ int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 	return -EINVAL;
 #endif
 }
+
+struct ast_wdt *ast_get_wdt(u8 wdt_number)
+{
+	if (wdt_number > CONFIG_WDT_NUM - 1)
+		return ERR_PTR(-EINVAL);
+
+	return (struct ast_wdt *)(WDT_BASE +
+				  sizeof(struct ast_wdt) * wdt_number);
+}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7a725f1e6d..fab8dc9034 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -18,4 +18,15 @@ config WDT_SANDBOX
 		can be probed and supports all of the methods of WDT, but does not
 		really do anything.
 
+config WDT_ASPEED
+	bool "Aspeed ast2400/ast2500 watchdog timer support"
+	depends on WDT
+	default y if ARCH_ASPEED
+	help
+	  Select this to enable watchdog timer for Aspeed ast2500/ast2400 devices.
+	  The watchdog timer is stopped when initialized. It performs reset, either
+	  full SoC reset or CPU or just some peripherals, based on the flags.
+	  It currently does not support Boot Flash Addressing Mode Detection or
+	  Second Boot.
+
 endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f523d34d57..a30dd661b1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
 obj-$(CONFIG_WDT) += wdt-uclass.o
 obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
+obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
new file mode 100644
index 0000000000..b2bd912ad5
--- /dev/null
+++ b/drivers/watchdog/ast_wdt.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/wdt.h>
+
+#define WDT_AST2500	2500
+#define WDT_AST2400	2400
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast_wdt_priv {
+	struct ast_wdt *regs;
+};
+
+static int ast_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	ulong driver_data = dev_get_driver_data(dev);
+	u32 reset_mode = ast_reset_mode_from_flags(flags);
+
+	clrsetbits_le32(&priv->regs->ctrl,
+			WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT,
+			reset_mode << WDT_CTRL_RESET_MODE_SHIFT);
+
+	if (driver_data >= WDT_AST2500 && reset_mode == WDT_CTRL_RESET_SOC)
+		writel(ast_reset_mask_from_flags(flags),
+		       &priv->regs->reset_mask);
+
+	writel((u32) timeout, &priv->regs->counter_reload_val);
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+	/*
+	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
+	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
+	 * read-only
+	 */
+	setbits_le32(&priv->regs->ctrl,
+		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
+
+	return 0;
+}
+
+static int ast_wdt_stop(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN);
+
+	return 0;
+}
+
+static int ast_wdt_reset(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+
+	return 0;
+}
+
+static int ast_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_wdt_start(dev, 1, flags);
+	if (ret)
+		return ret;
+
+	while (readl(&priv->regs->ctrl) & WDT_CTRL_EN)
+		;
+
+	return ast_wdt_stop(dev);
+}
+
+static int ast_wdt_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	return 0;
+}
+
+static const struct wdt_ops ast_wdt_ops = {
+	.start = ast_wdt_start,
+	.reset = ast_wdt_reset,
+	.stop = ast_wdt_stop,
+	.expire_now = ast_wdt_expire_now,
+};
+
+static const struct udevice_id ast_wdt_ids[] = {
+	{ .compatible = "aspeed,wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2500-wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2400-wdt", .data = WDT_AST2400 },
+	{}
+};
+
+static int ast_wdt_probe(struct udevice *dev)
+{
+	debug("%s() wdt%u\n", __func__, dev->seq);
+	ast_wdt_stop(dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(ast_wdt) = {
+	.name = "ast_wdt",
+	.id = UCLASS_WDT,
+	.of_match = ast_wdt_ids,
+	.probe = ast_wdt_probe,
+	.priv_auto_alloc_size = sizeof(struct ast_wdt_priv),
+	.ofdata_to_platdata = ast_wdt_ofdata_to_platdata,
+	.ops = &ast_wdt_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 03/15] aspeed: Watchdog Timer Driver
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

This driver supports ast2500 and ast2400 SoCs.
Only ast2500 supports reset_mask and thus the option of resettting
individual peripherals using WDT.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Rename reset to expire_now
- Rename restart to reset


---
 arch/arm/include/asm/arch-aspeed/wdt.h |  53 ++++++++++++--
 arch/arm/mach-aspeed/ast_wdt.c         |  40 ++++++++---
 drivers/watchdog/Kconfig               |  11 +++
 drivers/watchdog/Makefile              |   1 +
 drivers/watchdog/ast_wdt.c             | 125 +++++++++++++++++++++++++++++++++
 5 files changed, 217 insertions(+), 13 deletions(-)
 create mode 100644 drivers/watchdog/ast_wdt.c

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index b292a0e67b..981fa05a56 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -67,15 +67,60 @@ struct ast_wdt {
 	u32 timeout_status;
 	u32 clr_timeout_status;
 	u32 reset_width;
-#ifdef CONFIG_ASPEED_AST2500
+	/* On pre-ast2500 SoCs this register is reserved. */
 	u32 reset_mask;
-#else
-	u32 reserved0;
-#endif
 };
 
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mode value from it.
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mode value
+ */
+u32 ast_reset_mode_from_flags(ulong flags);
+
+/**
+ * Given flags parameter passed to wdt_reset or wdt_start uclass functions,
+ * gets Reset Mask value from it. Reset Mask is only supported on ast2500
+ *
+ * @flags: flags parameter passed into wdt_reset or wdt_start
+ * @return Reset Mask value
+ */
+u32 ast_reset_mask_from_flags(ulong flags);
+
+/**
+ * Given Reset Mask and Reset Mode values, converts them to flags,
+ * suitable for passing into wdt_start or wdt_reset uclass functions.
+ *
+ * On ast2500 Reset Mask is 25 bits wide and Reset Mode is 2 bits wide, so they
+ * can both be packed into single 32 bits wide value.
+ *
+ * @reset_mode: Reset Mode
+ * @reset_mask: Reset Mask
+ */
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
+
+#ifndef CONFIG_WDT
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to stop
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_stop(struct ast_wdt *wdt);
+
+/**
+ * Stop WDT
+ *
+ * @wdt: watchdog to start
+ * @timeout	watchdog timeout in number of clock ticks
+ *
+ * When using driver model this function has different signature
+ */
 void wdt_start(struct ast_wdt *wdt, u32 timeout);
+#endif  /* CONFIG_WDT */
 
 /**
  * Reset peripherals specified by mask
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 22481ab7ea..895fba3366 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -9,6 +9,27 @@
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
+u32 ast_reset_mode_from_flags(ulong flags)
+{
+	return flags & WDT_CTRL_RESET_MASK;
+}
+
+u32 ast_reset_mask_from_flags(ulong flags)
+{
+	return flags >> 2;
+}
+
+ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
+{
+	ulong ret = reset_mode & WDT_CTRL_RESET_MASK;
+
+	if (ret == WDT_CTRL_RESET_SOC)
+		ret |= (reset_mask << 2);
+
+	return ret;
+}
+
+#ifndef CONFIG_WDT
 void wdt_stop(struct ast_wdt *wdt)
 {
 	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
@@ -26,15 +47,7 @@ void wdt_start(struct ast_wdt *wdt, u32 timeout)
 	setbits_le32(&wdt->ctrl,
 		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
 }
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
+#endif  /* CONFIG_WDT */
 
 int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 {
@@ -57,3 +70,12 @@ int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
 	return -EINVAL;
 #endif
 }
+
+struct ast_wdt *ast_get_wdt(u8 wdt_number)
+{
+	if (wdt_number > CONFIG_WDT_NUM - 1)
+		return ERR_PTR(-EINVAL);
+
+	return (struct ast_wdt *)(WDT_BASE +
+				  sizeof(struct ast_wdt) * wdt_number);
+}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7a725f1e6d..fab8dc9034 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -18,4 +18,15 @@ config WDT_SANDBOX
 		can be probed and supports all of the methods of WDT, but does not
 		really do anything.
 
+config WDT_ASPEED
+	bool "Aspeed ast2400/ast2500 watchdog timer support"
+	depends on WDT
+	default y if ARCH_ASPEED
+	help
+	  Select this to enable watchdog timer for Aspeed ast2500/ast2400 devices.
+	  The watchdog timer is stopped when initialized. It performs reset, either
+	  full SoC reset or CPU or just some peripherals, based on the flags.
+	  It currently does not support Boot Flash Addressing Mode Detection or
+	  Second Boot.
+
 endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f523d34d57..a30dd661b1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
 obj-$(CONFIG_WDT) += wdt-uclass.o
 obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
+obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
new file mode 100644
index 0000000000..b2bd912ad5
--- /dev/null
+++ b/drivers/watchdog/ast_wdt.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/wdt.h>
+
+#define WDT_AST2500	2500
+#define WDT_AST2400	2400
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast_wdt_priv {
+	struct ast_wdt *regs;
+};
+
+static int ast_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	ulong driver_data = dev_get_driver_data(dev);
+	u32 reset_mode = ast_reset_mode_from_flags(flags);
+
+	clrsetbits_le32(&priv->regs->ctrl,
+			WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT,
+			reset_mode << WDT_CTRL_RESET_MODE_SHIFT);
+
+	if (driver_data >= WDT_AST2500 && reset_mode == WDT_CTRL_RESET_SOC)
+		writel(ast_reset_mask_from_flags(flags),
+		       &priv->regs->reset_mask);
+
+	writel((u32) timeout, &priv->regs->counter_reload_val);
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+	/*
+	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
+	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
+	 * read-only
+	 */
+	setbits_le32(&priv->regs->ctrl,
+		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
+
+	return 0;
+}
+
+static int ast_wdt_stop(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN);
+
+	return 0;
+}
+
+static int ast_wdt_reset(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
+
+	return 0;
+}
+
+static int ast_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_wdt_start(dev, 1, flags);
+	if (ret)
+		return ret;
+
+	while (readl(&priv->regs->ctrl) & WDT_CTRL_EN)
+		;
+
+	return ast_wdt_stop(dev);
+}
+
+static int ast_wdt_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	return 0;
+}
+
+static const struct wdt_ops ast_wdt_ops = {
+	.start = ast_wdt_start,
+	.reset = ast_wdt_reset,
+	.stop = ast_wdt_stop,
+	.expire_now = ast_wdt_expire_now,
+};
+
+static const struct udevice_id ast_wdt_ids[] = {
+	{ .compatible = "aspeed,wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2500-wdt", .data = WDT_AST2500 },
+	{ .compatible = "aspeed,ast2400-wdt", .data = WDT_AST2400 },
+	{}
+};
+
+static int ast_wdt_probe(struct udevice *dev)
+{
+	debug("%s() wdt%u\n", __func__, dev->seq);
+	ast_wdt_stop(dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(ast_wdt) = {
+	.name = "ast_wdt",
+	.id = UCLASS_WDT,
+	.of_match = ast_wdt_ids,
+	.probe = ast_wdt_probe,
+	.priv_auto_alloc_size = sizeof(struct ast_wdt_priv),
+	.ofdata_to_platdata = ast_wdt_ofdata_to_platdata,
+	.ops = &ast_wdt_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Make functions for locking and unlocking SCU part of SCU API.
Many drivers need to modify settings in SCU and thus need to unlock it
first. This change makes it possible.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 14 ++++++++++++++
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     | 15 +++++++++++++++
 drivers/clk/aspeed/clk_ast2500.c               | 18 ++----------------
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fc0c01ae33..0fa3ecb9b9 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -120,6 +120,20 @@ int ast_get_clk(struct udevice **devp);
  */
 void *ast_get_scu(void);
 
+/**
+ * ast_scu_unlock() - unlock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_unlock(struct ast2500_scu *scu);
+
+/**
+ * ast_scu_lock() - lock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_lock(struct ast2500_scu *scu);
+
 #endif  /* __ASSEMBLY__ */
 
 #endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
index 079909fa64..30cfac1af0 100644
--- a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 
 int ast_get_clk(struct udevice **devp)
@@ -28,3 +29,17 @@ void *ast_get_scu(void)
 
 	return priv->scu;
 }
+
+void ast_scu_unlock(struct ast2500_scu *scu)
+{
+	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (!readl(&scu->protection_key))
+		;
+}
+
+void ast_scu_lock(struct ast2500_scu *scu)
+{
+	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (readl(&scu->protection_key))
+		;
+}
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 26a5e58221..504731271c 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -132,20 +132,6 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static void ast2500_scu_unlock(struct ast2500_scu *scu)
-{
-	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (!readl(&scu->protection_key))
-		;
-}
-
-static void ast2500_scu_lock(struct ast2500_scu *scu)
-{
-	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (readl(&scu->protection_key))
-		;
-}
-
 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 {
 	ulong clkin = ast2500_get_clkin(scu);
@@ -197,9 +183,9 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	    | (best_num << SCU_MPLL_NUM_SHIFT)
 	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
 
-	ast2500_scu_unlock(scu);
+	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
-	ast2500_scu_lock(scu);
+	ast_scu_lock(scu);
 
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Make functions for locking and unlocking SCU part of SCU API.
Many drivers need to modify settings in SCU and thus need to unlock it
first. This change makes it possible.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 14 ++++++++++++++
 arch/arm/mach-aspeed/ast2500/clk_ast2500.c     | 15 +++++++++++++++
 drivers/clk/aspeed/clk_ast2500.c               | 18 ++----------------
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fc0c01ae33..0fa3ecb9b9 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -120,6 +120,20 @@ int ast_get_clk(struct udevice **devp);
  */
 void *ast_get_scu(void);
 
+/**
+ * ast_scu_unlock() - unlock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_unlock(struct ast2500_scu *scu);
+
+/**
+ * ast_scu_lock() - lock protected registers
+ *
+ * @scu, pointer to ast2500_scu
+ */
+void ast_scu_lock(struct ast2500_scu *scu);
+
 #endif  /* __ASSEMBLY__ */
 
 #endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
index 079909fa64..30cfac1af0 100644
--- a/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/clk_ast2500.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 
 int ast_get_clk(struct udevice **devp)
@@ -28,3 +29,17 @@ void *ast_get_scu(void)
 
 	return priv->scu;
 }
+
+void ast_scu_unlock(struct ast2500_scu *scu)
+{
+	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (!readl(&scu->protection_key))
+		;
+}
+
+void ast_scu_lock(struct ast2500_scu *scu)
+{
+	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
+	while (readl(&scu->protection_key))
+		;
+}
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 26a5e58221..504731271c 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -132,20 +132,6 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static void ast2500_scu_unlock(struct ast2500_scu *scu)
-{
-	writel(SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (!readl(&scu->protection_key))
-		;
-}
-
-static void ast2500_scu_lock(struct ast2500_scu *scu)
-{
-	writel(~SCU_UNLOCK_VALUE, &scu->protection_key);
-	while (readl(&scu->protection_key))
-		;
-}
-
 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 {
 	ulong clkin = ast2500_get_clkin(scu);
@@ -197,9 +183,9 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	    | (best_num << SCU_MPLL_NUM_SHIFT)
 	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
 
-	ast2500_scu_unlock(scu);
+	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
-	ast2500_scu_lock(scu);
+	ast_scu_lock(scu);
 
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 05/15] aspeed: Reset Driver
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass
  Cc: openbmc, Maxim Sloyko, Masahiro Yamada, Tom Warren,
	Albert Aribaud, Stephen Warren

Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
perform resets and thus depends on it. The actual Watchdog device used
needs to be configured in Device Tree using "aspeed,wdt" property, which
must be WDT phandle, for example:

rst: reset-controller {
    compatible = "aspeed,ast2500-reset";
    aspeed,wdt = <&wdt1>;
}

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  28 +++++++
 drivers/reset/Kconfig                          |  10 +++
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++++++++++++++++++++++++
 4 files changed, 145 insertions(+)
 create mode 100644 drivers/reset/ast2500-reset.c

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 0fa3ecb9b9..e2556f920d 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -31,6 +31,34 @@
 
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
 
+/*
+ * SYSRESET is actually more like a Power register,
+ * except that corresponding bit set to 1 means that
+ * the peripheral is off.
+ */
+#define SCU_SYSRESET_XDMA		(1 << 25)
+#define SCU_SYSRESET_MCTP		(1 << 24)
+#define SCU_SYSRESET_ADC		(1 << 23)
+#define SCU_SYSRESET_JTAG		(1 << 22)
+#define SCU_SYSRESET_MIC		(1 << 18)
+#define SCU_SYSRESET_SDIO		(1 << 16)
+#define SCU_SYSRESET_USB11HOST		(1 << 15)
+#define SCU_SYSRESET_USBHUB		(1 << 14)
+#define SCU_SYSRESET_CRT		(1 << 13)
+#define SCU_SYSRESET_MAC2		(1 << 12)
+#define SCU_SYSRESET_MAC1		(1 << 11)
+#define SCU_SYSRESET_PECI		(1 << 10)
+#define SCU_SYSRESET_PWM		(1 << 9)
+#define SCU_SYSRESET_PCI_VGA		(1 << 8)
+#define SCU_SYSRESET_2D			(1 << 7)
+#define SCU_SYSRESET_VIDEO		(1 << 6)
+#define SCU_SYSRESET_LPC		(1 << 5)
+#define SCU_SYSRESET_HAC		(1 << 4)
+#define SCU_SYSRESET_USBHID		(1 << 3)
+#define SCU_SYSRESET_I2C		(1 << 2)
+#define SCU_SYSRESET_AHB		(1 << 1)
+#define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c42b0bcf0e..eb54189d4b 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -43,4 +43,14 @@ config RESET_UNIPHIER
 	  Say Y if you want to control reset signals provided by System Control
 	  block, Media I/O block, Peripheral Block.
 
+config AST2500_RESET
+	bool "Reset controller driver for AST2500 SoCs"
+	depends on DM_RESET && WDT_ASPEED
+	default y if ASPEED_AST2500
+	help
+	  Support for reset controller on AST2500 SoC. This controller uses
+	  watchdog to reset different peripherals and thus only supports
+	  resets that are supported by watchdog. The main limitation though
+	  is that some reset signals, like I2C or MISC reset multiple devices.
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 5c4305cc1d..16ad7eed5b 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
 obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
 obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
diff --git a/drivers/reset/ast2500-reset.c b/drivers/reset/ast2500-reset.c
new file mode 100644
index 0000000000..b2c89e1f1e
--- /dev/null
+++ b/drivers/reset/ast2500-reset.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <reset.h>
+#include <reset-uclass.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+#include <asm/arch/wdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast2500_reset_priv {
+	/* WDT used to perform resets. */
+	struct udevice *wdt;
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt",
+					   &priv->wdt);
+	if (ret) {
+		debug("%s: can't find WDT for reset controller", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast2500_reset_assert(struct reset_ctl *reset_ctl)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	u32 reset_mode, reset_mask;
+	bool reset_sdram;
+	int ret;
+
+	/*
+	 * To reset SDRAM, a specifal flag in SYSRESET register
+	 * needs to be enabled first
+	 */
+	reset_mode = ast_reset_mode_from_flags(reset_ctl->id);
+	reset_mask = ast_reset_mask_from_flags(reset_ctl->id);
+	reset_sdram = reset_mode == WDT_CTRL_RESET_SOC &&
+		(reset_mask & WDT_RESET_SDRAM);
+
+	if (reset_sdram) {
+		ast_scu_unlock(priv->scu);
+		setbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+		clrbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ast_scu_lock(priv->scu);
+	} else {
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+	}
+
+	return ret;
+}
+
+static int ast2500_reset_request(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int ast2500_reset_probe(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+static const struct udevice_id ast2500_reset_ids[] = {
+	{ .compatible = "aspeed,ast2500-reset" },
+	{ }
+};
+
+struct reset_ops ast2500_reset_ops = {
+	.rst_assert = ast2500_reset_assert,
+	.request = ast2500_reset_request,
+};
+
+U_BOOT_DRIVER(ast2500_reset) = {
+	.name		= "ast2500_reset",
+	.id		= UCLASS_RESET,
+	.of_match = ast2500_reset_ids,
+	.probe = ast2500_reset_probe,
+	.ops = &ast2500_reset_ops,
+	.ofdata_to_platdata = ast2500_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct ast2500_reset_priv),
+};
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 05/15] aspeed: Reset Driver
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
perform resets and thus depends on it. The actual Watchdog device used
needs to be configured in Device Tree using "aspeed,wdt" property, which
must be WDT phandle, for example:

rst: reset-controller {
    compatible = "aspeed,ast2500-reset";
    aspeed,wdt = <&wdt1>;
}

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Remove unnecessary check for error in dev_get_priv
- Fix comment
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  28 +++++++
 drivers/reset/Kconfig                          |  10 +++
 drivers/reset/Makefile                         |   1 +
 drivers/reset/ast2500-reset.c                  | 106 +++++++++++++++++++++++++
 4 files changed, 145 insertions(+)
 create mode 100644 drivers/reset/ast2500-reset.c

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 0fa3ecb9b9..e2556f920d 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -31,6 +31,34 @@
 
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
 
+/*
+ * SYSRESET is actually more like a Power register,
+ * except that corresponding bit set to 1 means that
+ * the peripheral is off.
+ */
+#define SCU_SYSRESET_XDMA		(1 << 25)
+#define SCU_SYSRESET_MCTP		(1 << 24)
+#define SCU_SYSRESET_ADC		(1 << 23)
+#define SCU_SYSRESET_JTAG		(1 << 22)
+#define SCU_SYSRESET_MIC		(1 << 18)
+#define SCU_SYSRESET_SDIO		(1 << 16)
+#define SCU_SYSRESET_USB11HOST		(1 << 15)
+#define SCU_SYSRESET_USBHUB		(1 << 14)
+#define SCU_SYSRESET_CRT		(1 << 13)
+#define SCU_SYSRESET_MAC2		(1 << 12)
+#define SCU_SYSRESET_MAC1		(1 << 11)
+#define SCU_SYSRESET_PECI		(1 << 10)
+#define SCU_SYSRESET_PWM		(1 << 9)
+#define SCU_SYSRESET_PCI_VGA		(1 << 8)
+#define SCU_SYSRESET_2D			(1 << 7)
+#define SCU_SYSRESET_VIDEO		(1 << 6)
+#define SCU_SYSRESET_LPC		(1 << 5)
+#define SCU_SYSRESET_HAC		(1 << 4)
+#define SCU_SYSRESET_USBHID		(1 << 3)
+#define SCU_SYSRESET_I2C		(1 << 2)
+#define SCU_SYSRESET_AHB		(1 << 1)
+#define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c42b0bcf0e..eb54189d4b 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -43,4 +43,14 @@ config RESET_UNIPHIER
 	  Say Y if you want to control reset signals provided by System Control
 	  block, Media I/O block, Peripheral Block.
 
+config AST2500_RESET
+	bool "Reset controller driver for AST2500 SoCs"
+	depends on DM_RESET && WDT_ASPEED
+	default y if ASPEED_AST2500
+	help
+	  Support for reset controller on AST2500 SoC. This controller uses
+	  watchdog to reset different peripherals and thus only supports
+	  resets that are supported by watchdog. The main limitation though
+	  is that some reset signals, like I2C or MISC reset multiple devices.
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 5c4305cc1d..16ad7eed5b 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
 obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
 obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
diff --git a/drivers/reset/ast2500-reset.c b/drivers/reset/ast2500-reset.c
new file mode 100644
index 0000000000..b2c89e1f1e
--- /dev/null
+++ b/drivers/reset/ast2500-reset.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <reset.h>
+#include <reset-uclass.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+#include <asm/arch/wdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ast2500_reset_priv {
+	/* WDT used to perform resets. */
+	struct udevice *wdt;
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt",
+					   &priv->wdt);
+	if (ret) {
+		debug("%s: can't find WDT for reset controller", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast2500_reset_assert(struct reset_ctl *reset_ctl)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	u32 reset_mode, reset_mask;
+	bool reset_sdram;
+	int ret;
+
+	/*
+	 * To reset SDRAM, a specifal flag in SYSRESET register
+	 * needs to be enabled first
+	 */
+	reset_mode = ast_reset_mode_from_flags(reset_ctl->id);
+	reset_mask = ast_reset_mask_from_flags(reset_ctl->id);
+	reset_sdram = reset_mode == WDT_CTRL_RESET_SOC &&
+		(reset_mask & WDT_RESET_SDRAM);
+
+	if (reset_sdram) {
+		ast_scu_unlock(priv->scu);
+		setbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+		clrbits_le32(&priv->scu->sysreset_ctrl1,
+			     SCU_SYSRESET_SDRAM_WDT);
+		ast_scu_lock(priv->scu);
+	} else {
+		ret = wdt_expire_now(priv->wdt, reset_ctl->id);
+	}
+
+	return ret;
+}
+
+static int ast2500_reset_request(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int ast2500_reset_probe(struct udevice *dev)
+{
+	struct ast2500_reset_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+static const struct udevice_id ast2500_reset_ids[] = {
+	{ .compatible = "aspeed,ast2500-reset" },
+	{ }
+};
+
+struct reset_ops ast2500_reset_ops = {
+	.rst_assert = ast2500_reset_assert,
+	.request = ast2500_reset_request,
+};
+
+U_BOOT_DRIVER(ast2500_reset) = {
+	.name		= "ast2500_reset",
+	.id		= UCLASS_RESET,
+	.of_match = ast2500_reset_ids,
+	.probe = ast2500_reset_probe,
+	.ops = &ast2500_reset_ops,
+	.ofdata_to_platdata = ast2500_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct ast2500_reset_priv),
+};
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 06/15] aspeed: Device Tree configuration for Reset Driver
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
for various reset signals

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/dts/ast2500-evb.dts              | 15 +++++++++++
 arch/arm/dts/ast2500-u-boot.dtsi          | 10 +++++++
 include/dt-bindings/reset/ast2500-reset.h | 45 +++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+)
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h

diff --git a/arch/arm/dts/ast2500-evb.dts b/arch/arm/dts/ast2500-evb.dts
index dc13952fb8..723941ac0b 100644
--- a/arch/arm/dts/ast2500-evb.dts
+++ b/arch/arm/dts/ast2500-evb.dts
@@ -21,3 +21,18 @@
 &sdrammc {
 	clock-frequency = <400000000>;
 };
+
+&wdt1 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt2 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt3 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index c95a7ba835..faeeec1be4 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -1,4 +1,5 @@
 #include <dt-bindings/clock/ast2500-scu.h>
+#include <dt-bindings/reset/ast2500-reset.h>
 
 #include "ast2500.dtsi"
 
@@ -11,12 +12,21 @@
 		#reset-cells = <1>;
 	};
 
+	rst: reset-controller {
+		u-boot,dm-pre-reloc;
+		compatible = "aspeed,ast2500-reset";
+		aspeed,wdt = <&wdt1>;
+		#reset-cells = <1>;
+	};
+
 	sdrammc: sdrammc@1e6e0000 {
 		u-boot,dm-pre-reloc;
 		compatible = "aspeed,ast2500-sdrammc";
 		reg = <0x1e6e0000 0x174
 			0x1e6e0200 0x1d4 >;
+		#reset-cells = <1>;
 		clocks = <&scu PLL_MPLL>;
+		resets = <&rst AST_RESET_SDRAM>;
 	};
 
 	ahb {
diff --git a/include/dt-bindings/reset/ast2500-reset.h b/include/dt-bindings/reset/ast2500-reset.h
new file mode 100644
index 0000000000..eb5e1db97b
--- /dev/null
+++ b/include/dt-bindings/reset/ast2500-reset.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ABI_MACH_ASPEED_AST2500_RESET_H_
+#define _ABI_MACH_ASPEED_AST2500_RESET_H_
+
+/*
+ * The values are intentionally layed out as flags in
+ * WDT reset parameter.
+ */
+
+#define AST_RESET_SOC			0
+#define AST_RESET_CHIP			1
+#define AST_RESET_CPU			(1 << 1)
+#define AST_RESET_ARM			(1 << 2)
+#define AST_RESET_COPROC		(1 << 3)
+#define AST_RESET_SDRAM			(1 << 4)
+#define AST_RESET_AHB			(1 << 5)
+#define AST_RESET_I2C			(1 << 6)
+#define AST_RESET_MAC1			(1 << 7)
+#define AST_RESET_MAC2			(1 << 8)
+#define AST_RESET_GCRT			(1 << 9)
+#define AST_RESET_USB20			(1 << 10)
+#define AST_RESET_USB11_HOST		(1 << 11)
+#define AST_RESET_USB11_HID		(1 << 12)
+#define AST_RESET_VIDEO			(1 << 13)
+#define AST_RESET_HAC			(1 << 14)
+#define AST_RESET_LPC			(1 << 15)
+#define AST_RESET_SDIO			(1 << 16)
+#define AST_RESET_MIC			(1 << 17)
+#define AST_RESET_CRT2D			(1 << 18)
+#define AST_RESET_PWM			(1 << 19)
+#define AST_RESET_PECI			(1 << 20)
+#define AST_RESET_JTAG			(1 << 21)
+#define AST_RESET_ADC			(1 << 22)
+#define AST_RESET_GPIO			(1 << 23)
+#define AST_RESET_MCTP			(1 << 24)
+#define AST_RESET_XDMA			(1 << 25)
+#define AST_RESET_SPI			(1 << 26)
+#define AST_RESET_MISC			(1 << 27)
+
+#endif  /* _ABI_MACH_ASPEED_AST2500_RESET_H_ */
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 06/15] aspeed: Device Tree configuration for Reset Driver
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
for various reset signals

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/dts/ast2500-evb.dts              | 15 +++++++++++
 arch/arm/dts/ast2500-u-boot.dtsi          | 10 +++++++
 include/dt-bindings/reset/ast2500-reset.h | 45 +++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+)
 create mode 100644 include/dt-bindings/reset/ast2500-reset.h

diff --git a/arch/arm/dts/ast2500-evb.dts b/arch/arm/dts/ast2500-evb.dts
index dc13952fb8..723941ac0b 100644
--- a/arch/arm/dts/ast2500-evb.dts
+++ b/arch/arm/dts/ast2500-evb.dts
@@ -21,3 +21,18 @@
 &sdrammc {
 	clock-frequency = <400000000>;
 };
+
+&wdt1 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt2 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&wdt3 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index c95a7ba835..faeeec1be4 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -1,4 +1,5 @@
 #include <dt-bindings/clock/ast2500-scu.h>
+#include <dt-bindings/reset/ast2500-reset.h>
 
 #include "ast2500.dtsi"
 
@@ -11,12 +12,21 @@
 		#reset-cells = <1>;
 	};
 
+	rst: reset-controller {
+		u-boot,dm-pre-reloc;
+		compatible = "aspeed,ast2500-reset";
+		aspeed,wdt = <&wdt1>;
+		#reset-cells = <1>;
+	};
+
 	sdrammc: sdrammc at 1e6e0000 {
 		u-boot,dm-pre-reloc;
 		compatible = "aspeed,ast2500-sdrammc";
 		reg = <0x1e6e0000 0x174
 			0x1e6e0200 0x1d4 >;
+		#reset-cells = <1>;
 		clocks = <&scu PLL_MPLL>;
+		resets = <&rst AST_RESET_SDRAM>;
 	};
 
 	ahb {
diff --git a/include/dt-bindings/reset/ast2500-reset.h b/include/dt-bindings/reset/ast2500-reset.h
new file mode 100644
index 0000000000..eb5e1db97b
--- /dev/null
+++ b/include/dt-bindings/reset/ast2500-reset.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ABI_MACH_ASPEED_AST2500_RESET_H_
+#define _ABI_MACH_ASPEED_AST2500_RESET_H_
+
+/*
+ * The values are intentionally layed out as flags in
+ * WDT reset parameter.
+ */
+
+#define AST_RESET_SOC			0
+#define AST_RESET_CHIP			1
+#define AST_RESET_CPU			(1 << 1)
+#define AST_RESET_ARM			(1 << 2)
+#define AST_RESET_COPROC		(1 << 3)
+#define AST_RESET_SDRAM			(1 << 4)
+#define AST_RESET_AHB			(1 << 5)
+#define AST_RESET_I2C			(1 << 6)
+#define AST_RESET_MAC1			(1 << 7)
+#define AST_RESET_MAC2			(1 << 8)
+#define AST_RESET_GCRT			(1 << 9)
+#define AST_RESET_USB20			(1 << 10)
+#define AST_RESET_USB11_HOST		(1 << 11)
+#define AST_RESET_USB11_HID		(1 << 12)
+#define AST_RESET_VIDEO			(1 << 13)
+#define AST_RESET_HAC			(1 << 14)
+#define AST_RESET_LPC			(1 << 15)
+#define AST_RESET_SDIO			(1 << 16)
+#define AST_RESET_MIC			(1 << 17)
+#define AST_RESET_CRT2D			(1 << 18)
+#define AST_RESET_PWM			(1 << 19)
+#define AST_RESET_PECI			(1 << 20)
+#define AST_RESET_JTAG			(1 << 21)
+#define AST_RESET_ADC			(1 << 22)
+#define AST_RESET_GPIO			(1 << 23)
+#define AST_RESET_MCTP			(1 << 24)
+#define AST_RESET_XDMA			(1 << 25)
+#define AST_RESET_SPI			(1 << 26)
+#define AST_RESET_MISC			(1 << 27)
+
+#endif  /* _ABI_MACH_ASPEED_AST2500_RESET_H_ */
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

This change switches all existing users of ast2500 Watchdog to Driver
Model based Watchdog driver.

To perform system reset Sysreset Driver uses first Watchdog device found
via uclass_first_device call. Since the system is going to be reset
anyway it does not make much difference which watchdog is used.

Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
driver to do that.

These were the only users of the old Watchdog API, so that API is
removed.

This all is done in one change to avoid having to maintain dual API for
watchdog in between.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/wdt.h       | 39 ---------------------
 arch/arm/mach-aspeed/Kconfig                 |  8 +----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c | 12 +++++--
 arch/arm/mach-aspeed/ast_wdt.c               | 51 ----------------------------
 configs/evb-ast2500_defconfig                |  2 ++
 drivers/sysreset/sysreset_ast.c              | 24 ++++++-------
 6 files changed, 24 insertions(+), 112 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index 981fa05a56..db8ecbcbe4 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -100,45 +100,6 @@ u32 ast_reset_mask_from_flags(ulong flags);
  * @reset_mask: Reset Mask
  */
 ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
-
-#ifndef CONFIG_WDT
-/**
- * Stop WDT
- *
- * @wdt: watchdog to stop
- *
- * When using driver model this function has different signature
- */
-void wdt_stop(struct ast_wdt *wdt);
-
-/**
- * Stop WDT
- *
- * @wdt: watchdog to start
- * @timeout	watchdog timeout in number of clock ticks
- *
- * When using driver model this function has different signature
- */
-void wdt_start(struct ast_wdt *wdt, u32 timeout);
-#endif  /* CONFIG_WDT */
-
-/**
- * Reset peripherals specified by mask
- *
- * Note, that this is only supported by ast2500 SoC
- *
- * @wdt: watchdog to use for this reset
- * @mask: reset mask.
- */
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask);
-
-/**
- * ast_get_wdt() - get a pointer to watchdog registers
- *
- * @wdt_number: 0-based WDT peripheral number
- * @return pointer to registers or -ve error on error
- */
-struct ast_wdt *ast_get_wdt(u8 wdt_number);
 #endif  /* __ASSEMBLY__ */
 
 #endif /* _ASM_ARCH_WDT_H */
diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig
index c5b90bd96a..4f021baa06 100644
--- a/arch/arm/mach-aspeed/Kconfig
+++ b/arch/arm/mach-aspeed/Kconfig
@@ -11,19 +11,13 @@ config SYS_TEXT_BASE
 
 config ASPEED_AST2500
 	bool "Support Aspeed AST2500 SoC"
+	depends on DM_RESET
 	select CPU_ARM1176
 	help
 	  The Aspeed AST2500 is a ARM-based SoC with arm1176 CPU.
 	  It is used as Board Management Controller on many server boards,
 	  which is enabled by support of LPC and eSPI peripherals.
 
-config WDT_NUM
-	int "Number of Watchdog Timers"
-	default 3 if ASPEED_AST2500
-	help
-	  The number of Watchdot Timers on a SoC.
-	  AST2500 has three WDTsk earlier versions have two or fewer.
-
 source "arch/arm/mach-aspeed/ast2500/Kconfig"
 
 endif
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index cb6e03fa34..efcf452b17 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <ram.h>
 #include <regmap.h>
+#include <reset.h>
 #include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 #include <asm/arch/sdram_ast2500.h>
@@ -328,6 +329,7 @@ static void ast2500_sdrammc_lock(struct dram_info *info)
 
 static int ast2500_sdrammc_probe(struct udevice *dev)
 {
+	struct reset_ctl reset_ctl;
 	struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
 	struct ast2500_sdrammc_regs *regs = priv->regs;
 	int i;
@@ -345,9 +347,15 @@ static int ast2500_sdrammc_probe(struct udevice *dev)
 	}
 
 	clk_set_rate(&priv->ddr_clk, priv->clock_rate);
-	ret = ast_wdt_reset_masked(ast_get_wdt(0), WDT_RESET_SDRAM);
+	ret = reset_get_by_index(dev, 0, &reset_ctl);
 	if (ret) {
-		debug("%s(): SDRAM reset failed\n", __func__);
+		debug("%s(): Failed to get reset signal\n", __func__);
+		return ret;
+	}
+
+	ret = reset_assert(&reset_ctl);
+	if (ret) {
+		debug("%s(): SDRAM reset failed: %u\n", __func__, ret);
 		return ret;
 	}
 
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 895fba3366..1a858b1020 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -28,54 +28,3 @@ ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
 
 	return ret;
 }
-
-#ifndef CONFIG_WDT
-void wdt_stop(struct ast_wdt *wdt)
-{
-	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
-}
-
-void wdt_start(struct ast_wdt *wdt, u32 timeout)
-{
-	writel(timeout, &wdt->counter_reload_val);
-	writel(WDT_COUNTER_RESTART_VAL, &wdt->counter_restart);
-	/*
-	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
-	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
-	 * read-only
-	 */
-	setbits_le32(&wdt->ctrl,
-		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
-}
-#endif  /* CONFIG_WDT */
-
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
-{
-#ifdef CONFIG_ASPEED_AST2500
-	if (!mask)
-		return -EINVAL;
-
-	writel(mask, &wdt->reset_mask);
-	clrbits_le32(&wdt->ctrl,
-		     WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT);
-	wdt_start(wdt, 1);
-
-	/* Wait for WDT to reset */
-	while (readl(&wdt->ctrl) & WDT_CTRL_EN)
-		;
-	wdt_stop(wdt);
-
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index cc5fea9a81..74808a71ee 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -15,3 +15,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_TIMER=y
+CONFIG_WDT=y
+CONFIG_DM_RESET=y
diff --git a/drivers/sysreset/sysreset_ast.c b/drivers/sysreset/sysreset_ast.c
index a0ab12851d..3c3f552df8 100644
--- a/drivers/sysreset/sysreset_ast.c
+++ b/drivers/sysreset/sysreset_ast.c
@@ -8,21 +8,19 @@
 #include <dm.h>
 #include <errno.h>
 #include <sysreset.h>
+#include <wdt.h>
 #include <asm/io.h>
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
-/* Number of Watchdog Timer ticks before reset */
-#define AST_WDT_RESET_TIMEOUT	10
-#define AST_WDT_FOR_RESET	0
-
 static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
-	struct ast_wdt *wdt = ast_get_wdt(AST_WDT_FOR_RESET);
-	u32 reset_mode = 0;
+	struct udevice *wdt;
+	u32 reset_mode;
+	int ret = uclass_first_device(UCLASS_WDT, &wdt);
 
-	if (IS_ERR(wdt))
-		return PTR_ERR(wdt);
+	if (ret)
+		return ret;
 
 	switch (type) {
 	case SYSRESET_WARM:
@@ -35,11 +33,11 @@ static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 		return -EPROTONOSUPPORT;
 	}
 
-	/* Clear reset mode bits */
-	clrsetbits_le32(&wdt->ctrl,
-			(WDT_CTRL_RESET_MODE_MASK << WDT_CTRL_RESET_MODE_SHIFT),
-			(reset_mode << WDT_CTRL_RESET_MODE_SHIFT));
-	wdt_start(wdt, AST_WDT_RESET_TIMEOUT);
+	ret = wdt_expire_now(wdt, reset_mode);
+	if (ret) {
+		debug("Sysreset failed: %d", ret);
+		return ret;
+	}
 
 	return -EINPROGRESS;
 }
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

This change switches all existing users of ast2500 Watchdog to Driver
Model based Watchdog driver.

To perform system reset Sysreset Driver uses first Watchdog device found
via uclass_first_device call. Since the system is going to be reset
anyway it does not make much difference which watchdog is used.

Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
driver to do that.

These were the only users of the old Watchdog API, so that API is
removed.

This all is done in one change to avoid having to maintain dual API for
watchdog in between.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1:
- Rename wdt_reset call to wdt_expire_now

---
 arch/arm/include/asm/arch-aspeed/wdt.h       | 39 ---------------------
 arch/arm/mach-aspeed/Kconfig                 |  8 +----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c | 12 +++++--
 arch/arm/mach-aspeed/ast_wdt.c               | 51 ----------------------------
 configs/evb-ast2500_defconfig                |  2 ++
 drivers/sysreset/sysreset_ast.c              | 24 ++++++-------
 6 files changed, 24 insertions(+), 112 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
index 981fa05a56..db8ecbcbe4 100644
--- a/arch/arm/include/asm/arch-aspeed/wdt.h
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -100,45 +100,6 @@ u32 ast_reset_mask_from_flags(ulong flags);
  * @reset_mask: Reset Mask
  */
 ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask);
-
-#ifndef CONFIG_WDT
-/**
- * Stop WDT
- *
- * @wdt: watchdog to stop
- *
- * When using driver model this function has different signature
- */
-void wdt_stop(struct ast_wdt *wdt);
-
-/**
- * Stop WDT
- *
- * @wdt: watchdog to start
- * @timeout	watchdog timeout in number of clock ticks
- *
- * When using driver model this function has different signature
- */
-void wdt_start(struct ast_wdt *wdt, u32 timeout);
-#endif  /* CONFIG_WDT */
-
-/**
- * Reset peripherals specified by mask
- *
- * Note, that this is only supported by ast2500 SoC
- *
- * @wdt: watchdog to use for this reset
- * @mask: reset mask.
- */
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask);
-
-/**
- * ast_get_wdt() - get a pointer to watchdog registers
- *
- * @wdt_number: 0-based WDT peripheral number
- * @return pointer to registers or -ve error on error
- */
-struct ast_wdt *ast_get_wdt(u8 wdt_number);
 #endif  /* __ASSEMBLY__ */
 
 #endif /* _ASM_ARCH_WDT_H */
diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig
index c5b90bd96a..4f021baa06 100644
--- a/arch/arm/mach-aspeed/Kconfig
+++ b/arch/arm/mach-aspeed/Kconfig
@@ -11,19 +11,13 @@ config SYS_TEXT_BASE
 
 config ASPEED_AST2500
 	bool "Support Aspeed AST2500 SoC"
+	depends on DM_RESET
 	select CPU_ARM1176
 	help
 	  The Aspeed AST2500 is a ARM-based SoC with arm1176 CPU.
 	  It is used as Board Management Controller on many server boards,
 	  which is enabled by support of LPC and eSPI peripherals.
 
-config WDT_NUM
-	int "Number of Watchdog Timers"
-	default 3 if ASPEED_AST2500
-	help
-	  The number of Watchdot Timers on a SoC.
-	  AST2500 has three WDTsk earlier versions have two or fewer.
-
 source "arch/arm/mach-aspeed/ast2500/Kconfig"
 
 endif
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index cb6e03fa34..efcf452b17 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <ram.h>
 #include <regmap.h>
+#include <reset.h>
 #include <asm/io.h>
 #include <asm/arch/scu_ast2500.h>
 #include <asm/arch/sdram_ast2500.h>
@@ -328,6 +329,7 @@ static void ast2500_sdrammc_lock(struct dram_info *info)
 
 static int ast2500_sdrammc_probe(struct udevice *dev)
 {
+	struct reset_ctl reset_ctl;
 	struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
 	struct ast2500_sdrammc_regs *regs = priv->regs;
 	int i;
@@ -345,9 +347,15 @@ static int ast2500_sdrammc_probe(struct udevice *dev)
 	}
 
 	clk_set_rate(&priv->ddr_clk, priv->clock_rate);
-	ret = ast_wdt_reset_masked(ast_get_wdt(0), WDT_RESET_SDRAM);
+	ret = reset_get_by_index(dev, 0, &reset_ctl);
 	if (ret) {
-		debug("%s(): SDRAM reset failed\n", __func__);
+		debug("%s(): Failed to get reset signal\n", __func__);
+		return ret;
+	}
+
+	ret = reset_assert(&reset_ctl);
+	if (ret) {
+		debug("%s(): SDRAM reset failed: %u\n", __func__, ret);
 		return ret;
 	}
 
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
index 895fba3366..1a858b1020 100644
--- a/arch/arm/mach-aspeed/ast_wdt.c
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -28,54 +28,3 @@ ulong ast_flags_from_reset_mode_mask(u32 reset_mode, u32 reset_mask)
 
 	return ret;
 }
-
-#ifndef CONFIG_WDT
-void wdt_stop(struct ast_wdt *wdt)
-{
-	clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
-}
-
-void wdt_start(struct ast_wdt *wdt, u32 timeout)
-{
-	writel(timeout, &wdt->counter_reload_val);
-	writel(WDT_COUNTER_RESTART_VAL, &wdt->counter_restart);
-	/*
-	 * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
-	 * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
-	 * read-only
-	 */
-	setbits_le32(&wdt->ctrl,
-		     WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
-}
-#endif  /* CONFIG_WDT */
-
-int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
-{
-#ifdef CONFIG_ASPEED_AST2500
-	if (!mask)
-		return -EINVAL;
-
-	writel(mask, &wdt->reset_mask);
-	clrbits_le32(&wdt->ctrl,
-		     WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT);
-	wdt_start(wdt, 1);
-
-	/* Wait for WDT to reset */
-	while (readl(&wdt->ctrl) & WDT_CTRL_EN)
-		;
-	wdt_stop(wdt);
-
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
-struct ast_wdt *ast_get_wdt(u8 wdt_number)
-{
-	if (wdt_number > CONFIG_WDT_NUM - 1)
-		return ERR_PTR(-EINVAL);
-
-	return (struct ast_wdt *)(WDT_BASE +
-				  sizeof(struct ast_wdt) * wdt_number);
-}
diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index cc5fea9a81..74808a71ee 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -15,3 +15,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_TIMER=y
+CONFIG_WDT=y
+CONFIG_DM_RESET=y
diff --git a/drivers/sysreset/sysreset_ast.c b/drivers/sysreset/sysreset_ast.c
index a0ab12851d..3c3f552df8 100644
--- a/drivers/sysreset/sysreset_ast.c
+++ b/drivers/sysreset/sysreset_ast.c
@@ -8,21 +8,19 @@
 #include <dm.h>
 #include <errno.h>
 #include <sysreset.h>
+#include <wdt.h>
 #include <asm/io.h>
 #include <asm/arch/wdt.h>
 #include <linux/err.h>
 
-/* Number of Watchdog Timer ticks before reset */
-#define AST_WDT_RESET_TIMEOUT	10
-#define AST_WDT_FOR_RESET	0
-
 static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
-	struct ast_wdt *wdt = ast_get_wdt(AST_WDT_FOR_RESET);
-	u32 reset_mode = 0;
+	struct udevice *wdt;
+	u32 reset_mode;
+	int ret = uclass_first_device(UCLASS_WDT, &wdt);
 
-	if (IS_ERR(wdt))
-		return PTR_ERR(wdt);
+	if (ret)
+		return ret;
 
 	switch (type) {
 	case SYSRESET_WARM:
@@ -35,11 +33,11 @@ static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
 		return -EPROTONOSUPPORT;
 	}
 
-	/* Clear reset mode bits */
-	clrsetbits_le32(&wdt->ctrl,
-			(WDT_CTRL_RESET_MODE_MASK << WDT_CTRL_RESET_MODE_SHIFT),
-			(reset_mode << WDT_CTRL_RESET_MODE_SHIFT));
-	wdt_start(wdt, AST_WDT_RESET_TIMEOUT);
+	ret = wdt_expire_now(wdt, reset_mode);
+	if (ret) {
+		debug("Sysreset failed: %d", ret);
+		return ret;
+	}
 
 	return -EINPROGRESS;
 }
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 08/15] aspeed: AST2500 Pinctrl Driver
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass
  Cc: openbmc, Maxim Sloyko, Thomas Abraham, Konstantin Porotchkin,
	Wills Wang, Kever Yang, Albert Aribaud, Beniamino Galvani,
	Stefan Roese, Heiko Stübner, Minkyu Kang,
	Daniel Schwierzeck, Wenyou Yang

This driver uses Generic Pinctrl framework and is compatible with
the Linux driver for ast2500: it uses the same device tree
configuration.

Not all pins are supported by the driver at the moment, so it actually
compatible with ast2400. In general, however, there are differences that
in the future would be easier to maintain separately.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++++++++++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  19 ++++
 drivers/pinctrl/Kconfig                        |   9 ++
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 +++++++++++++++++++++++++
 6 files changed, 209 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c

diff --git a/arch/arm/include/asm/arch-aspeed/pinctrl.h b/arch/arm/include/asm/arch-aspeed/pinctrl.h
new file mode 100644
index 0000000000..365dc21dbc
--- /dev/null
+++ b/arch/arm/include/asm/arch-aspeed/pinctrl.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _ASM_ARCH_PERIPH_H
+#define _ASM_ARCH_PERIPH_H
+
+/*
+ * Peripherals supported by the hardware.
+ * These are used to specify pinctrl settings.
+ */
+
+enum periph_id {
+	PERIPH_ID_UART1,
+	PERIPH_ID_UART2,
+	PERIPH_ID_UART3,
+	PERIPH_ID_UART4,
+	PERIPH_ID_LPC,
+	PERIPH_ID_PWM0,
+	PERIPH_ID_PWM1,
+	PERIPH_ID_PWM2,
+	PERIPH_ID_PWM3,
+	PERIPH_ID_PWM4,
+	PERIPH_ID_PWM5,
+	PERIPH_ID_PWM6,
+	PERIPH_ID_PWM7,
+	PERIPH_ID_PWM8,
+	PERIPH_ID_MAC1,
+	PERIPH_ID_MAC2,
+	PERIPH_ID_VIDEO,
+	PERIPH_ID_SPI1,
+	PERIPH_ID_SPI2,
+	PERIPH_ID_I2C1,
+	PERIPH_ID_I2C2,
+	PERIPH_ID_I2C3,
+	PERIPH_ID_I2C4,
+	PERIPH_ID_I2C5,
+	PERIPH_ID_I2C6,
+	PERIPH_ID_I2C7,
+	PERIPH_ID_I2C8,
+	PERIPH_ID_I2C9,
+	PERIPH_ID_I2C10,
+	PERIPH_ID_I2C11,
+	PERIPH_ID_I2C12,
+	PERIPH_ID_I2C13,
+	PERIPH_ID_I2C14,
+	PERIPH_ID_SD1,
+	PERIPH_ID_SD2,
+};
+
+#endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index e2556f920d..1cdd3b9198 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -10,6 +10,8 @@
 
 #define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
+#define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
 #define SCU_HWSTRAP_CLKIN_25MHZ		(1 << 23)
 
@@ -59,6 +61,23 @@
 #define SCU_SYSRESET_AHB		(1 << 1)
 #define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
 
+/* Bits 16-27 in the register control pin functions for I2C devices 3-14 */
+#define SCU_PINMUX_CTRL5_I2C		(1 << 16)
+
+/*
+ * The values are grouped by function, not by register.
+ * They are actually scattered across multiple loosely related registers.
+ */
+#define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
+#define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
+#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
+#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_SCL1		(1 << 12)
+#define SCU_PIN_FUN_SCL2		(1 << 14)
+#define SCU_PIN_FUN_SDA1		(1 << 13)
+#define SCU_PIN_FUN_SDA2		(1 << 15)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index efcb4c0003..3b7dd5f0c5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -175,6 +175,15 @@ config PIC32_PINCTRL
 	  by a device tree node which contains both GPIO defintion and pin control
 	  functions.
 
+config ASPEED_AST2500_PINCTRL
+  bool "Aspeed AST2500 pin control driver"
+  depends on DM && PINCTRL_GENERIC && ASPEED_AST2500
+  default y
+  help
+    Support pin multiplexing control on Aspeed ast2500 SoC. The driver uses
+	Generic Pinctrl framework and is compatible with the Linux driver,
+	i.e. it uses the same device tree configuration.
+
 endif
 
 source "drivers/pinctrl/meson/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 512112af64..5392c3ed45 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
 obj-$(CONFIG_PINCTRL_MVEBU)	+= mvebu/
+obj-$(CONFIG_ARCH_ASPEED) += aspeed/
diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
new file mode 100644
index 0000000000..2e6ed604c8
--- /dev/null
+++ b/drivers/pinctrl/aspeed/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ASPEED_AST2500_PINCTRL) += pinctrl_ast2500.o
diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2500.c b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
new file mode 100644
index 0000000000..01f97c1b48
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/pinctrl.h>
+#include <asm/arch/scu_ast2500.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This driver works with very simple configuration that has the same name
+ * for group and function. This way it is compatible with the Linux Kernel
+ * driver.
+ */
+
+struct ast2500_pinctrl_priv {
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_pinctrl_probe(struct udevice *dev)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+struct ast2500_group_config {
+	char *group_name;
+	/* Control register number (1-10) */
+	unsigned reg_num;
+	/* The mask of control bits in the register */
+	u32 ctrl_bit_mask;
+};
+
+static const struct ast2500_group_config ast2500_groups[] = {
+	{ "I2C1", 8, (1 << 13) | (1 << 12) },
+	{ "I2C2", 8, (1 << 15) | (1 << 14) },
+	{ "I2C3", 8, (1 << 16) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C5", 5, (1 << 18) },
+	{ "I2C6", 5, (1 << 19) },
+	{ "I2C7", 5, (1 << 20) },
+	{ "I2C8", 5, (1 << 21) },
+	{ "I2C9", 5, (1 << 22) },
+	{ "I2C10", 5, (1 << 23) },
+	{ "I2C11", 5, (1 << 24) },
+	{ "I2C12", 5, (1 << 25) },
+	{ "I2C13", 5, (1 << 26) },
+	{ "I2C14", 5, (1 << 27) },
+	{ "MAC1LINK", 1, (1 << 0) },
+	{ "MDIO1", 3, (1 << 31) | (1 << 30) },
+	{ "MAC2LINK", 1, (1 << 1) },
+	{ "MDIO2", 5, (1 << 2) },
+};
+
+static int ast2500_pinctrl_get_groups_count(struct udevice *dev)
+{
+	debug("PINCTRL: get_(functions/groups)_count\n");
+
+	return ARRAY_SIZE(ast2500_groups);
+}
+
+static const char *ast2500_pinctrl_get_group_name(struct udevice *dev,
+						  unsigned selector)
+{
+	debug("PINCTRL: get_(function/group)_name %u\n", selector);
+
+	return ast2500_groups[selector].group_name;
+}
+
+static int ast2500_pinctrl_group_set(struct udevice *dev, unsigned selector,
+				     unsigned func_selector)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct ast2500_group_config *config;
+	u32 *ctrl_reg;
+
+	debug("PINCTRL: group_set <%u, %u>\n", selector, func_selector);
+	if (selector >= ARRAY_SIZE(ast2500_groups))
+		return -EINVAL;
+
+	config = &ast2500_groups[selector];
+	if (config->reg_num > 6)
+		ctrl_reg = &priv->scu->pinmux_ctrl1[config->reg_num - 7];
+	else
+		ctrl_reg = &priv->scu->pinmux_ctrl[config->reg_num - 1];
+
+	ast_scu_unlock(priv->scu);
+	setbits_le32(ctrl_reg, config->ctrl_bit_mask);
+	ast_scu_lock(priv->scu);
+
+	return 0;
+}
+
+static struct pinctrl_ops ast2500_pinctrl_ops = {
+	.set_state = pinctrl_generic_set_state,
+	.get_groups_count = ast2500_pinctrl_get_groups_count,
+	.get_group_name = ast2500_pinctrl_get_group_name,
+	.get_functions_count = ast2500_pinctrl_get_groups_count,
+	.get_function_name = ast2500_pinctrl_get_group_name,
+	.pinmux_group_set = ast2500_pinctrl_group_set,
+};
+
+static const struct udevice_id ast2500_pinctrl_ids[] = {
+	{ .compatible = "aspeed,ast2500-pinctrl" },
+	{ .compatible = "aspeed,g5-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_ast2500) = {
+	.name = "aspeed_ast2500_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = ast2500_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct ast2500_pinctrl_priv),
+	.ops = &ast2500_pinctrl_ops,
+	.probe = ast2500_pinctrl_probe,
+};
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 08/15] aspeed: AST2500 Pinctrl Driver
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

This driver uses Generic Pinctrl framework and is compatible with
the Linux driver for ast2500: it uses the same device tree
configuration.

Not all pins are supported by the driver at the moment, so it actually
compatible with ast2400. In general, however, there are differences that
in the future would be easier to maintain separately.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/pinctrl.h     |  52 ++++++++++
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  19 ++++
 drivers/pinctrl/Kconfig                        |   9 ++
 drivers/pinctrl/Makefile                       |   1 +
 drivers/pinctrl/aspeed/Makefile                |   1 +
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       | 127 +++++++++++++++++++++++++
 6 files changed, 209 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-aspeed/pinctrl.h
 create mode 100644 drivers/pinctrl/aspeed/Makefile
 create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2500.c

diff --git a/arch/arm/include/asm/arch-aspeed/pinctrl.h b/arch/arm/include/asm/arch-aspeed/pinctrl.h
new file mode 100644
index 0000000000..365dc21dbc
--- /dev/null
+++ b/arch/arm/include/asm/arch-aspeed/pinctrl.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _ASM_ARCH_PERIPH_H
+#define _ASM_ARCH_PERIPH_H
+
+/*
+ * Peripherals supported by the hardware.
+ * These are used to specify pinctrl settings.
+ */
+
+enum periph_id {
+	PERIPH_ID_UART1,
+	PERIPH_ID_UART2,
+	PERIPH_ID_UART3,
+	PERIPH_ID_UART4,
+	PERIPH_ID_LPC,
+	PERIPH_ID_PWM0,
+	PERIPH_ID_PWM1,
+	PERIPH_ID_PWM2,
+	PERIPH_ID_PWM3,
+	PERIPH_ID_PWM4,
+	PERIPH_ID_PWM5,
+	PERIPH_ID_PWM6,
+	PERIPH_ID_PWM7,
+	PERIPH_ID_PWM8,
+	PERIPH_ID_MAC1,
+	PERIPH_ID_MAC2,
+	PERIPH_ID_VIDEO,
+	PERIPH_ID_SPI1,
+	PERIPH_ID_SPI2,
+	PERIPH_ID_I2C1,
+	PERIPH_ID_I2C2,
+	PERIPH_ID_I2C3,
+	PERIPH_ID_I2C4,
+	PERIPH_ID_I2C5,
+	PERIPH_ID_I2C6,
+	PERIPH_ID_I2C7,
+	PERIPH_ID_I2C8,
+	PERIPH_ID_I2C9,
+	PERIPH_ID_I2C10,
+	PERIPH_ID_I2C11,
+	PERIPH_ID_I2C12,
+	PERIPH_ID_I2C13,
+	PERIPH_ID_I2C14,
+	PERIPH_ID_SD1,
+	PERIPH_ID_SD2,
+};
+
+#endif  /* _ASM_ARCH_SCU_AST2500_H */
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index e2556f920d..1cdd3b9198 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -10,6 +10,8 @@
 
 #define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
+#define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
 #define SCU_HWSTRAP_CLKIN_25MHZ		(1 << 23)
 
@@ -59,6 +61,23 @@
 #define SCU_SYSRESET_AHB		(1 << 1)
 #define SCU_SYSRESET_SDRAM_WDT		(1 << 0)
 
+/* Bits 16-27 in the register control pin functions for I2C devices 3-14 */
+#define SCU_PINMUX_CTRL5_I2C		(1 << 16)
+
+/*
+ * The values are grouped by function, not by register.
+ * They are actually scattered across multiple loosely related registers.
+ */
+#define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
+#define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
+#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
+#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_SCL1		(1 << 12)
+#define SCU_PIN_FUN_SCL2		(1 << 14)
+#define SCU_PIN_FUN_SDA1		(1 << 13)
+#define SCU_PIN_FUN_SDA2		(1 << 15)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index efcb4c0003..3b7dd5f0c5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -175,6 +175,15 @@ config PIC32_PINCTRL
 	  by a device tree node which contains both GPIO defintion and pin control
 	  functions.
 
+config ASPEED_AST2500_PINCTRL
+  bool "Aspeed AST2500 pin control driver"
+  depends on DM && PINCTRL_GENERIC && ASPEED_AST2500
+  default y
+  help
+    Support pin multiplexing control on Aspeed ast2500 SoC. The driver uses
+	Generic Pinctrl framework and is compatible with the Linux driver,
+	i.e. it uses the same device tree configuration.
+
 endif
 
 source "drivers/pinctrl/meson/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 512112af64..5392c3ed45 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
 obj-$(CONFIG_PINCTRL_MVEBU)	+= mvebu/
+obj-$(CONFIG_ARCH_ASPEED) += aspeed/
diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
new file mode 100644
index 0000000000..2e6ed604c8
--- /dev/null
+++ b/drivers/pinctrl/aspeed/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ASPEED_AST2500_PINCTRL) += pinctrl_ast2500.o
diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2500.c b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
new file mode 100644
index 0000000000..01f97c1b48
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/pinctrl.h>
+#include <asm/arch/scu_ast2500.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This driver works with very simple configuration that has the same name
+ * for group and function. This way it is compatible with the Linux Kernel
+ * driver.
+ */
+
+struct ast2500_pinctrl_priv {
+	struct ast2500_scu *scu;
+};
+
+static int ast2500_pinctrl_probe(struct udevice *dev)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+
+	priv->scu = ast_get_scu();
+
+	return 0;
+}
+
+struct ast2500_group_config {
+	char *group_name;
+	/* Control register number (1-10) */
+	unsigned reg_num;
+	/* The mask of control bits in the register */
+	u32 ctrl_bit_mask;
+};
+
+static const struct ast2500_group_config ast2500_groups[] = {
+	{ "I2C1", 8, (1 << 13) | (1 << 12) },
+	{ "I2C2", 8, (1 << 15) | (1 << 14) },
+	{ "I2C3", 8, (1 << 16) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C4", 5, (1 << 17) },
+	{ "I2C5", 5, (1 << 18) },
+	{ "I2C6", 5, (1 << 19) },
+	{ "I2C7", 5, (1 << 20) },
+	{ "I2C8", 5, (1 << 21) },
+	{ "I2C9", 5, (1 << 22) },
+	{ "I2C10", 5, (1 << 23) },
+	{ "I2C11", 5, (1 << 24) },
+	{ "I2C12", 5, (1 << 25) },
+	{ "I2C13", 5, (1 << 26) },
+	{ "I2C14", 5, (1 << 27) },
+	{ "MAC1LINK", 1, (1 << 0) },
+	{ "MDIO1", 3, (1 << 31) | (1 << 30) },
+	{ "MAC2LINK", 1, (1 << 1) },
+	{ "MDIO2", 5, (1 << 2) },
+};
+
+static int ast2500_pinctrl_get_groups_count(struct udevice *dev)
+{
+	debug("PINCTRL: get_(functions/groups)_count\n");
+
+	return ARRAY_SIZE(ast2500_groups);
+}
+
+static const char *ast2500_pinctrl_get_group_name(struct udevice *dev,
+						  unsigned selector)
+{
+	debug("PINCTRL: get_(function/group)_name %u\n", selector);
+
+	return ast2500_groups[selector].group_name;
+}
+
+static int ast2500_pinctrl_group_set(struct udevice *dev, unsigned selector,
+				     unsigned func_selector)
+{
+	struct ast2500_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct ast2500_group_config *config;
+	u32 *ctrl_reg;
+
+	debug("PINCTRL: group_set <%u, %u>\n", selector, func_selector);
+	if (selector >= ARRAY_SIZE(ast2500_groups))
+		return -EINVAL;
+
+	config = &ast2500_groups[selector];
+	if (config->reg_num > 6)
+		ctrl_reg = &priv->scu->pinmux_ctrl1[config->reg_num - 7];
+	else
+		ctrl_reg = &priv->scu->pinmux_ctrl[config->reg_num - 1];
+
+	ast_scu_unlock(priv->scu);
+	setbits_le32(ctrl_reg, config->ctrl_bit_mask);
+	ast_scu_lock(priv->scu);
+
+	return 0;
+}
+
+static struct pinctrl_ops ast2500_pinctrl_ops = {
+	.set_state = pinctrl_generic_set_state,
+	.get_groups_count = ast2500_pinctrl_get_groups_count,
+	.get_group_name = ast2500_pinctrl_get_group_name,
+	.get_functions_count = ast2500_pinctrl_get_groups_count,
+	.get_function_name = ast2500_pinctrl_get_group_name,
+	.pinmux_group_set = ast2500_pinctrl_group_set,
+};
+
+static const struct udevice_id ast2500_pinctrl_ids[] = {
+	{ .compatible = "aspeed,ast2500-pinctrl" },
+	{ .compatible = "aspeed,g5-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_ast2500) = {
+	.name = "aspeed_ast2500_pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = ast2500_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct ast2500_pinctrl_priv),
+	.ops = &ast2500_pinctrl_ops,
+	.probe = ast2500_pinctrl_probe,
+};
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko

Enable Pinctrl Driver in AST2500 Eval Board's defconfig

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 configs/evb-ast2500_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index 74808a71ee..f8ef9b779c 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -17,3 +17,4 @@ CONFIG_SYSRESET=y
 CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
+CONFIG_PINCTRL=y
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Enable Pinctrl Driver in AST2500 Eval Board's defconfig

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 configs/evb-ast2500_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index 74808a71ee..f8ef9b779c 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -17,3 +17,4 @@ CONFIG_SYSRESET=y
 CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
+CONFIG_PINCTRL=y
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Add P-Bus Clock support to ast2500 clock driver.
This is the clock used by I2C devices.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  3 ++-
 drivers/clk/aspeed/clk_ast2500.c               | 11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 1cdd3b9198..319d75e05c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -21,7 +21,8 @@
 #define SCU_MPLL_NUM_MASK		0xff
 #define SCU_MPLL_POST_SHIFT		13
 #define SCU_MPLL_POST_MASK		0x3f
-
+#define SCU_PCLK_DIV_SHIFT		23
+#define SCU_PCLK_DIV_MASK		7
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 504731271c..9e4c66ea85 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -110,6 +110,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 		rate = ast2500_get_mpll_rate(clkin,
 					     readl(&priv->scu->m_pll_param));
 		break;
+	case BCLK_PCLK:
+		{
+			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
+						  >> SCU_PCLK_DIV_SHIFT) &
+						 SCU_PCLK_DIV_MASK);
+			rate = ast2500_get_hpll_rate(clkin,
+						     readl(&priv->scu->
+							   h_pll_param));
+			rate = rate / apb_div;
+		}
+		break;
 	case PCLK_UART1:
 		rate = ast2500_get_uart_clk_rate(priv->scu, 1);
 		break;
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Add P-Bus Clock support to ast2500 clock driver.
This is the clock used by I2C devices.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  3 ++-
 drivers/clk/aspeed/clk_ast2500.c               | 11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 1cdd3b9198..319d75e05c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -21,7 +21,8 @@
 #define SCU_MPLL_NUM_MASK		0xff
 #define SCU_MPLL_POST_SHIFT		13
 #define SCU_MPLL_POST_MASK		0x3f
-
+#define SCU_PCLK_DIV_SHIFT		23
+#define SCU_PCLK_DIV_MASK		7
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 504731271c..9e4c66ea85 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -110,6 +110,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 		rate = ast2500_get_mpll_rate(clkin,
 					     readl(&priv->scu->m_pll_param));
 		break;
+	case BCLK_PCLK:
+		{
+			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
+						  >> SCU_PCLK_DIV_SHIFT) &
+						 SCU_PCLK_DIV_MASK);
+			rate = ast2500_get_hpll_rate(clkin,
+						     readl(&priv->scu->
+							   h_pll_param));
+			rate = rate / apb_div;
+		}
+		break;
 	case PCLK_UART1:
 		rate = ast2500_get_uart_clk_rate(priv->scu, 1);
 		break;
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 11/15] aspeed: Add I2C Driver
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Heiko Schocher

Add Device Model based I2C driver for ast2500/ast2400 SoCs.
The driver is very limited, it only supports master mode and
synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Heiko Schocher <hs@denx.de>

---

Changes in v2: None
Changes in v1:
- Style fixes


---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
 4 files changed, 499 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 39f62daf5d..e661a308b0 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 	  enable status register. This config option can be enabled in such
 	  cases.
 
+config SYS_I2C_ASPEED
+	bool "Aspeed I2C Controller"
+	depends on DM_I2C && ARCH_ASPEED
+	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
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 7c86198863..229fd476db 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -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_ASPEED) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
new file mode 100644
index 0000000000..16dfb57066
--- /dev/null
+++ b/drivers/i2c/ast_i2c.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 Google, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US 100000
+#define I2C_SLEEP_STEP_US 20
+
+#define HIGHSPEED_TTIMEOUT		3
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Device private data
+ */
+struct ast_i2c_priv {
+	/* This device's clock */
+	struct clk clk;
+	/* 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)
+			| (div << I2CD_BASE_DIV_SHIFT);
+
+	return data;
+}
+
+static void ast_i2c_clear_interrupts(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(~0, &priv->regs->isr);
+}
+
+static void ast_i2c_init_bus(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Reset device */
+	writel(0, &priv->regs->fcr);
+	/* Enable Master Mode. Assuming single-master */
+	writel(I2CD_MASTER_EN
+	       | I2CD_M_SDA_LOCK_EN
+	       | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
+	       &priv->regs->fcr);
+	/* Enable Interrupts */
+	writel(I2CD_INTR_TX_ACK
+	       | I2CD_INTR_TX_NAK
+	       | I2CD_INTR_RX_DONE
+	       | I2CD_INTR_BUS_RECOVER_DONE
+	       | I2CD_INTR_NORMAL_STOP
+	       | I2CD_INTR_ABNORMAL, &priv->regs->icr);
+}
+
+static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret < 0) {
+		debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
+		      ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast_i2c_probe(struct udevice *dev)
+{
+	struct ast2500_scu *scu;
+
+	debug("Enabling I2C%u\n", dev->seq);
+
+	/*
+	 * Get all I2C devices out of Reset.
+	 * Only needs to be done once, but doing it for every
+	 * device does not hurt.
+	 */
+	scu = ast_get_scu();
+	ast_scu_unlock(scu);
+	clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
+	ast_scu_lock(scu);
+
+	ast_i2c_init_bus(dev);
+
+	return 0;
+}
+
+static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+
+	while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
+		udelay(I2C_SLEEP_STEP_US);
+		timeout -= I2C_SLEEP_STEP_US;
+	}
+
+	ast_i2c_clear_interrupts(dev);
+	if (timeout <= 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int ast_i2c_send_stop(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(I2CD_M_STOP_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
+}
+
+static int ast_i2c_wait_tx(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+	u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
+	u32 status = readl(&priv->regs->isr) & flag;
+	int ret = 0;
+
+	while (!status && timeout > 0) {
+		status = readl(&priv->regs->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(dev);
+
+	return ret;
+}
+
+static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Start and Send Device Address */
+	writel(devaddr, &priv->regs->trbbr);
+	writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_tx(dev);
+}
+
+static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8 *buffer,
+			     size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	u32 i2c_cmd = I2CD_M_RX_CMD;
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		if (len == 1)
+			i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
+		writel(i2c_cmd, &priv->regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
+		if (ret < 0)
+			return ret;
+		*buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
+				>> I2CD_RX_DATA_SHIFT;
+	}
+	ast_i2c_clear_interrupts(dev);
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
+			      *buffer, size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1));
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		writel(*buffer, &priv->regs->trbbr);
+		writel(I2CD_M_TX_CMD, &priv->regs->csr);
+		ret = ast_i2c_wait_tx(dev);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	u32 csr = readl(&regs->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(dev);
+	} else if (scl_high) {
+		/* Possibly stuck slave */
+		debug("Bus stuck (%x), attempting recovery\n", csr);
+		writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
+	} else {
+		/* Just try to reinit the device. */
+		ast_i2c_init_bus(dev);
+	}
+
+	return ret;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+	int ret;
+
+	ret = ast_i2c_deblock(dev);
+	if (ret < 0)
+		return ret;
+
+	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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	ulong i2c_rate, divider;
+
+	debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
+	if (!speed) {
+		debug("No valid speed specified\n");
+		return -EINVAL;
+	}
+
+	i2c_rate = clk_get_rate(&priv->clk);
+	divider = i2c_rate / speed;
+
+	priv->speed = speed;
+	if (speed > I2C_HIGHSPEED_RATE) {
+		debug("Enable High Speed\n");
+		setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
+			     | I2CD_M_SDA_DRIVE_1T_EN
+			     | I2CD_SDA_DRIVE_1T_EN);
+		writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
+	} else {
+		debug("Enabling Normal Speed\n");
+		writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
+	}
+
+	writel(get_clk_reg_val(divider), &regs->cactcr1);
+	ast_i2c_clear_interrupts(dev);
+
+	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-bus" },
+	{ .compatible = "aspeed,ast2500-i2c-bus" },
+	{ },
+};
+
+U_BOOT_DRIVER(ast_i2c) = {
+	.name = "ast_i2c",
+	.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_priv),
+	.ops = &ast_i2c_ops,
+};
diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
new file mode 100644
index 0000000000..e5dec7a480
--- /dev/null
+++ b/drivers/i2c/ast_i2c.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 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_ASPEED_AST2500
+	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)
+
+#define I2C_HIGHSPEED_RATE    400000
+
+#endif				/* __AST_I2C_H_ */
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 11/15] aspeed: Add I2C Driver
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Add Device Model based I2C driver for ast2500/ast2400 SoCs.
The driver is very limited, it only supports master mode and
synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Heiko Schocher <hs@denx.de>

---

Changes in v2: None
Changes in v1:
- Style fixes


---
 drivers/i2c/Kconfig   |   9 ++
 drivers/i2c/Makefile  |   1 +
 drivers/i2c/ast_i2c.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++
 4 files changed, 499 insertions(+)
 create mode 100644 drivers/i2c/ast_i2c.c
 create mode 100644 drivers/i2c/ast_i2c.h

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 39f62daf5d..e661a308b0 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -100,6 +100,15 @@ config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 	  enable status register. This config option can be enabled in such
 	  cases.
 
+config SYS_I2C_ASPEED
+	bool "Aspeed I2C Controller"
+	depends on DM_I2C && ARCH_ASPEED
+	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
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 7c86198863..229fd476db 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -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_ASPEED) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
new file mode 100644
index 0000000000..16dfb57066
--- /dev/null
+++ b/drivers/i2c/ast_i2c.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 Google, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/scu_ast2500.h>
+
+#include "ast_i2c.h"
+
+#define I2C_TIMEOUT_US 100000
+#define I2C_SLEEP_STEP_US 20
+
+#define HIGHSPEED_TTIMEOUT		3
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Device private data
+ */
+struct ast_i2c_priv {
+	/* This device's clock */
+	struct clk clk;
+	/* 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)
+			| (div << I2CD_BASE_DIV_SHIFT);
+
+	return data;
+}
+
+static void ast_i2c_clear_interrupts(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(~0, &priv->regs->isr);
+}
+
+static void ast_i2c_init_bus(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Reset device */
+	writel(0, &priv->regs->fcr);
+	/* Enable Master Mode. Assuming single-master */
+	writel(I2CD_MASTER_EN
+	       | I2CD_M_SDA_LOCK_EN
+	       | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
+	       &priv->regs->fcr);
+	/* Enable Interrupts */
+	writel(I2CD_INTR_TX_ACK
+	       | I2CD_INTR_TX_NAK
+	       | I2CD_INTR_RX_DONE
+	       | I2CD_INTR_BUS_RECOVER_DONE
+	       | I2CD_INTR_NORMAL_STOP
+	       | I2CD_INTR_ABNORMAL, &priv->regs->icr);
+}
+
+static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->regs = dev_get_addr_ptr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret < 0) {
+		debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
+		      ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ast_i2c_probe(struct udevice *dev)
+{
+	struct ast2500_scu *scu;
+
+	debug("Enabling I2C%u\n", dev->seq);
+
+	/*
+	 * Get all I2C devices out of Reset.
+	 * Only needs to be done once, but doing it for every
+	 * device does not hurt.
+	 */
+	scu = ast_get_scu();
+	ast_scu_unlock(scu);
+	clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
+	ast_scu_lock(scu);
+
+	ast_i2c_init_bus(dev);
+
+	return 0;
+}
+
+static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+
+	while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
+		udelay(I2C_SLEEP_STEP_US);
+		timeout -= I2C_SLEEP_STEP_US;
+	}
+
+	ast_i2c_clear_interrupts(dev);
+	if (timeout <= 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int ast_i2c_send_stop(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	writel(I2CD_M_STOP_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
+}
+
+static int ast_i2c_wait_tx(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int timeout = I2C_TIMEOUT_US;
+	u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
+	u32 status = readl(&priv->regs->isr) & flag;
+	int ret = 0;
+
+	while (!status && timeout > 0) {
+		status = readl(&priv->regs->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(dev);
+
+	return ret;
+}
+
+static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+
+	/* Start and Send Device Address */
+	writel(devaddr, &priv->regs->trbbr);
+	writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
+
+	return ast_i2c_wait_tx(dev);
+}
+
+static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8 *buffer,
+			     size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	u32 i2c_cmd = I2CD_M_RX_CMD;
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		if (len == 1)
+			i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
+		writel(i2c_cmd, &priv->regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
+		if (ret < 0)
+			return ret;
+		*buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
+				>> I2CD_RX_DATA_SHIFT;
+	}
+	ast_i2c_clear_interrupts(dev);
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
+			      *buffer, size_t len, bool send_stop)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ast_i2c_start_txn(dev, (chip_addr << 1));
+	if (ret < 0)
+		return ret;
+
+	for (; len > 0; len--, buffer++) {
+		writel(*buffer, &priv->regs->trbbr);
+		writel(I2CD_M_TX_CMD, &priv->regs->csr);
+		ret = ast_i2c_wait_tx(dev);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (send_stop)
+		return ast_i2c_send_stop(dev);
+
+	return 0;
+}
+
+static int ast_i2c_deblock(struct udevice *dev)
+{
+	struct ast_i2c_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	u32 csr = readl(&regs->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(dev);
+	} else if (scl_high) {
+		/* Possibly stuck slave */
+		debug("Bus stuck (%x), attempting recovery\n", csr);
+		writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
+		ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
+	} else {
+		/* Just try to reinit the device. */
+		ast_i2c_init_bus(dev);
+	}
+
+	return ret;
+}
+
+static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+	int ret;
+
+	ret = ast_i2c_deblock(dev);
+	if (ret < 0)
+		return ret;
+
+	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(dev, 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(dev, 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_priv *priv = dev_get_priv(dev);
+	struct ast_i2c_regs *regs = priv->regs;
+	ulong i2c_rate, divider;
+
+	debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
+	if (!speed) {
+		debug("No valid speed specified\n");
+		return -EINVAL;
+	}
+
+	i2c_rate = clk_get_rate(&priv->clk);
+	divider = i2c_rate / speed;
+
+	priv->speed = speed;
+	if (speed > I2C_HIGHSPEED_RATE) {
+		debug("Enable High Speed\n");
+		setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
+			     | I2CD_M_SDA_DRIVE_1T_EN
+			     | I2CD_SDA_DRIVE_1T_EN);
+		writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
+	} else {
+		debug("Enabling Normal Speed\n");
+		writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
+	}
+
+	writel(get_clk_reg_val(divider), &regs->cactcr1);
+	ast_i2c_clear_interrupts(dev);
+
+	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-bus" },
+	{ .compatible = "aspeed,ast2500-i2c-bus" },
+	{ },
+};
+
+U_BOOT_DRIVER(ast_i2c) = {
+	.name = "ast_i2c",
+	.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_priv),
+	.ops = &ast_i2c_ops,
+};
diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
new file mode 100644
index 0000000000..e5dec7a480
--- /dev/null
+++ b/drivers/i2c/ast_i2c.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012-2020  ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2017 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_ASPEED_AST2500
+	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)
+
+#define I2C_HIGHSPEED_RATE    400000
+
+#endif				/* __AST_I2C_H_ */
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 12/15] aspeed: Enable I2C in EVB defconfig
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko

Enable I2C driver in ast2500 Eval Board defconfig.
Also enable i2c command.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 configs/evb-ast2500_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index f8ef9b779c..08b5f85a34 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -18,3 +18,6 @@ CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
 CONFIG_PINCTRL=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_ASPEED=y
+CONFIG_CMD_I2C=y
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 12/15] aspeed: Enable I2C in EVB defconfig
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Enable I2C driver in ast2500 Eval Board defconfig.
Also enable i2c command.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 configs/evb-ast2500_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index f8ef9b779c..08b5f85a34 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -18,3 +18,6 @@ CONFIG_TIMER=y
 CONFIG_WDT=y
 CONFIG_DM_RESET=y
 CONFIG_PINCTRL=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_ASPEED=y
+CONFIG_CMD_I2C=y
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 13/15] aspeed: Add support for Clocks needed by MACs
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Add support for clocks needed by MACs to ast2500 clock driver.
The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
PCLK_MAC2 for MAC1 and MAC2 respectively.

The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
SDK. It is not entirely clear from the datasheet how this clock is used
by MACs, so not clear if the rate would ever need to be different. So,
for now, hardcoding it is probably safer.

The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
hardware strapping.

So, the network driver would only need to enable these clocks, no need
to configure the rate.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/dts/ast2500-u-boot.dtsi               |   8 +
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  62 +++++-
 drivers/clk/aspeed/clk_ast2500.c               | 265 ++++++++++++++++++++++---
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 4 files changed, 304 insertions(+), 33 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index faeeec1be4..f826646095 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -61,3 +61,11 @@
 		};
 	};
 };
+
+&mac0 {
+	clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;
+};
+
+&mac1 {
+	clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>;
+};
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 319d75e05c..fe877b5430 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -30,9 +30,36 @@
 #define SCU_HPLL_POST_SHIFT		13
 #define SCU_HPLL_POST_MASK		0x3f
 
+#define SCU_MACCLK_SHIFT		16
+#define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
+
+#define SCU_MISC2_RGMII_HPLL		(1 << 23)
+#define SCU_MISC2_RGMII_CLKDIV_SHIFT	20
+#define SCU_MISC2_RGMII_CLKDIV_MASK	(3 << SCU_MISC2_RGMII_CLKDIV_SHIFT)
+#define SCU_MISC2_RMII_MPLL		(1 << 19)
+#define SCU_MISC2_RMII_CLKDIV_SHIFT	16
+#define SCU_MISC2_RMII_CLKDIV_MASK	(3 << SCU_MISC2_RMII_CLKDIV_SHIFT)
 #define SCU_MISC2_UARTCLK_SHIFT		24
 
+#define SCU_MISC_D2PLL_OFF		(1 << 4)
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
+#define SCU_MISC_GCRT_USB20CLK		(1 << 21)
+
+#define SCU_MICDS_MAC1RGMII_TXDLY_SHIFT	0
+#define SCU_MICDS_MAC1RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC2RGMII_TXDLY_SHIFT	6
+#define SCU_MICDS_MAC2RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_RDLY_SHIFT	12
+#define SCU_MICDS_MAC1RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC2RMII_RDLY_SHIFT	18
+#define SCU_MICDS_MAC2RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_TXFALL	(1 << 24)
+#define SCU_MICDS_MAC2RMII_TXFALL	(1 << 25)
+#define SCU_MICDS_RMII1_RCLKEN		(1 << 29)
+#define SCU_MICDS_RMII2_RCLKEN		(1 << 30)
+#define SCU_MICDS_RGMIIPLL		(1 << 31)
 
 /*
  * SYSRESET is actually more like a Power register,
@@ -71,14 +98,45 @@
  */
 #define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
 #define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
-#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC1_PHY_LINK	(1 << 0)
 #define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
-#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_MAC2_PHY_LINK	(1 << 1)
 #define SCU_PIN_FUN_SCL1		(1 << 12)
 #define SCU_PIN_FUN_SCL2		(1 << 14)
 #define SCU_PIN_FUN_SDA1		(1 << 13)
 #define SCU_PIN_FUN_SDA2		(1 << 15)
 
+#define SCU_CLKSTOP_MAC1		(1 << 20)
+#define SCU_CLKSTOP_MAC2		(1 << 21)
+
+#define SCU_D2PLL_EXT1_OFF		(1 << 0)
+#define SCU_D2PLL_EXT1_BYPASS		(1 << 1)
+#define SCU_D2PLL_EXT1_RESET		(1 << 2)
+#define SCU_D2PLL_EXT1_MODE_SHIFT	3
+#define SCU_D2PLL_EXT1_MODE_MASK	(3 << SCU_D2PLL_EXT1_MODE_SHIFT)
+#define SCU_D2PLL_EXT1_PARAM_SHIFT	5
+#define SCU_D2PLL_EXT1_PARAM_MASK	(0x1ff << SCU_D2PLL_EXT1_PARAM_SHIFT)
+
+#define SCU_D2PLL_NUM_SHIFT		0
+#define SCU_D2PLL_NUM_MASK		(0xff << SCU_D2PLL_NUM_SHIFT)
+#define SCU_D2PLL_DENUM_SHIFT		8
+#define SCU_D2PLL_DENUM_MASK		(0x1f << SCU_D2PLL_DENUM_SHIFT)
+#define SCU_D2PLL_POST_SHIFT		13
+#define SCU_D2PLL_POST_MASK		(0x3f << SCU_D2PLL_POST_SHIFT)
+#define SCU_D2PLL_ODIV_SHIFT		19
+#define SCU_D2PLL_ODIV_MASK		(7 << SCU_D2PLL_ODIV_SHIFT)
+#define SCU_D2PLL_SIC_SHIFT		22
+#define SCU_D2PLL_SIC_MASK		(0x1f << SCU_D2PLL_SIC_SHIFT)
+#define SCU_D2PLL_SIP_SHIFT		27
+#define SCU_D2PLL_SIP_MASK		(0x1f << SCU_D2PLL_SIP_SHIFT)
+
+#define SCU_CLKDUTY_DCLK_SHIFT		0
+#define SCU_CLKDUTY_DCLK_MASK		(0x3f << SCU_CLKDUTY_DCLK_SHIFT)
+#define SCU_CLKDUTY_RGMII1TXCK_SHIFT	8
+#define SCU_CLKDUTY_RGMII1TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII1TXCK_SHIFT)
+#define SCU_CLKDUTY_RGMII2TXCK_SHIFT	16
+#define SCU_CLKDUTY_RGMII2TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 9e4c66ea85..7b4b5c64ac 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -12,16 +12,39 @@
 #include <dm/lists.h>
 #include <dt-bindings/clock/ast2500-scu.h>
 
+/*
+ * MAC Clock Delay settings, taken from Aspeed SDK
+ */
+#define RGMII_TXCLK_ODLY		8
+#define RMII_RXCLK_IDLY		2
+
+/*
+ * TGMII Clock Duty constants, taken from Aspeed SDK
+ */
+#define RGMII2_TXCK_DUTY	0x66
+#define RGMII1_TXCK_DUTY	0x64
+
+#define D2PLL_DEFAULT_RATE	(250 * 1000 * 1000)
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
+ * Clock divider/multiplier configuration struct.
  * For H-PLL and M-PLL the formula is
  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
  * M - Numerator
  * N - Denumerator
  * P - Post Divider
  * They have the same layout in their control register.
+ *
+ * D-PLL and D2-PLL have extra divider (OD + 1), which is not
+ * yet needed and ignored by clock configurations.
  */
+struct ast2500_div_config {
+	unsigned int num;
+	unsigned int denum;
+	unsigned int post_div;
+};
 
 /*
  * Get the rate of the M-PLL clock from input clock frequency and
@@ -143,30 +166,41 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+/*
+ * @input_rate - the rate of input clock in Hz
+ * @requested_rate - desired output rate in Hz
+ * @div - this is an IN/OUT parameter, at input all fields of the config
+ * need to be set to their maximum allowed values.
+ * The result (the best config we could find), would also be returned
+ * in this structure.
+ *
+ * @return The clock rate, when the resulting div_config is used.
+ */
+static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
+				       struct ast2500_div_config *cfg)
 {
-	ulong clkin = ast2500_get_clkin(scu);
-	u32 mpll_reg;
-
 	/*
-	 * There are not that many combinations of numerator, denumerator
-	 * and post divider, so just brute force the best combination.
-	 * However, to avoid overflow when multiplying, use kHz.
+	 * The assumption is that kHz precision is good enough and
+	 * also enough to avoid overflow when multiplying.
 	 */
-	const ulong clkin_khz = clkin / 1000;
-	const ulong rate_khz = rate / 1000;
-	ulong best_num = 0;
-	ulong best_denum = 0;
-	ulong best_post = 0;
-	ulong delta = rate;
-	ulong num, denum, post;
-
-	for (denum = 0; denum <= SCU_MPLL_DENUM_MASK; ++denum) {
-		for (post = 0; post <= SCU_MPLL_POST_MASK; ++post) {
-			num = (rate_khz * (post + 1) / clkin_khz) * (denum + 1);
-			ulong new_rate_khz = (clkin_khz
-					      * ((num + 1) / (denum + 1)))
-					     / (post + 1);
+	const ulong input_rate_khz = input_rate / 1000;
+	const ulong rate_khz = requested_rate / 1000;
+	const struct ast2500_div_config max_vals = *cfg;
+	struct ast2500_div_config it = { 0, 0, 0 };
+	ulong delta = rate_khz;
+	ulong new_rate_khz = 0;
+
+	for (; it.denum <= max_vals.denum; ++it.denum) {
+		for (it.post_div = 0; it.post_div <= max_vals.post_div;
+		     ++it.post_div) {
+			it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
+			    * (it.denum + 1);
+			if (it.num > max_vals.num)
+				continue;
+
+			new_rate_khz = (input_rate_khz
+					* ((it.num + 1) / (it.denum + 1)))
+			    / (it.post_div + 1);
 
 			/* Keep the rate below requested one. */
 			if (new_rate_khz > rate_khz)
@@ -174,25 +208,35 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 
 			if (new_rate_khz - rate_khz < delta) {
 				delta = new_rate_khz - rate_khz;
-
-				best_num = num;
-				best_denum = denum;
-				best_post = post;
-
+				*cfg = it;
 				if (delta == 0)
-					goto rate_calc_done;
+					return new_rate_khz * 1000;
 			}
 		}
 	}
 
- rate_calc_done:
+	return new_rate_khz * 1000;
+}
+
+static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	u32 mpll_reg;
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_MPLL_NUM_MASK,
+		.denum = SCU_MPLL_DENUM_MASK,
+		.post_div = SCU_MPLL_POST_MASK
+	};
+
+	ast2500_calc_clock_config(clkin, rate, &div_cfg);
+
 	mpll_reg = readl(&scu->m_pll_param);
 	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
 		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
 		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
-	mpll_reg |= (best_post << SCU_MPLL_POST_SHIFT)
-	    | (best_num << SCU_MPLL_NUM_SHIFT)
-	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
+	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
+	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
+	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
 
 	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
@@ -201,6 +245,136 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
 
+static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong hpll_rate = ast2500_get_hpll_rate(clkin,
+						readl(&scu->h_pll_param));
+	ulong required_rate;
+	u32 hwstrap;
+	u32 divisor;
+	u32 reset_bit;
+	u32 clkstop_bit;
+
+	/*
+	 * According to data sheet, for 10/100 mode the MAC clock frequency
+	 * should be at least 25MHz and for 1000 mode at least 100MHz
+	 */
+	hwstrap = readl(&scu->hwstrap);
+	if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
+		required_rate = 100 * 1000 * 1000;
+	else
+		required_rate = 25 * 1000 * 1000;
+
+	divisor = hpll_rate / required_rate;
+
+	if (divisor < 4) {
+		/* Clock can't run fast enough, but let's try anyway */
+		debug("MAC clock too slow\n");
+		divisor = 4;
+	} else if (divisor > 16) {
+		/* Can't slow down the clock enough, but let's try anyway */
+		debug("MAC clock too fast\n");
+		divisor = 16;
+	}
+
+	switch (index) {
+	case 1:
+		reset_bit = SCU_SYSRESET_MAC1;
+		clkstop_bit = SCU_CLKSTOP_MAC1;
+		break;
+	case 2:
+		reset_bit = SCU_SYSRESET_MAC2;
+		clkstop_bit = SCU_CLKSTOP_MAC2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ast_scu_unlock(scu);
+	clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
+			((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
+
+	/*
+	 * Disable MAC, start its clock and re-enable it.
+	 * The procedure and the delays (100us & 10ms) are
+	 * specified in the datasheet.
+	 */
+	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
+	udelay(100);
+	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
+	mdelay(10);
+	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
+
+	writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+	       | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
+	       &scu->clk_duty_sel);
+
+	ast_scu_lock(scu);
+
+	return required_rate;
+}
+
+static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
+{
+	/*
+	 * The values and the meaning of the next three
+	 * parameters are undocumented. Taken from Aspeed SDK.
+	 */
+	const u32 d2_pll_ext_param = 0x2c;
+	const u32 d2_pll_sip = 0x11;
+	const u32 d2_pll_sic = 0x18;
+	u32 clk_delay_settings =
+	    (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+	    | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
+		.denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
+		.post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
+	};
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong new_rate;
+
+	ast_scu_unlock(scu);
+	writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
+	       | SCU_D2PLL_EXT1_OFF
+	       | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
+
+	/*
+	 * Select USB2.0 port1 PHY clock as a clock source for GCRT.
+	 * This would disconnect it from D2-PLL.
+	 */
+	clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
+			SCU_MISC_GCRT_USB20CLK);
+
+	new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
+	writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
+	       | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
+	       | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
+	       | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
+	       | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
+	       &scu->d2_pll_param);
+
+	clrbits_le32(&scu->d2_pll_ext_param[0],
+		     SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
+
+	clrsetbits_le32(&scu->misc_ctrl2,
+			SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
+			| SCU_MISC2_RGMII_CLKDIV_MASK |
+			SCU_MISC2_RMII_CLKDIV_MASK,
+			(4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
+
+	writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
+	writel(clk_delay_settings, &scu->mac_clk_delay_100M);
+	writel(clk_delay_settings, &scu->mac_clk_delay_10M);
+
+	ast_scu_lock(scu);
+
+	return new_rate;
+}
+
 static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 {
 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
@@ -211,6 +385,9 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	case MCLK_DDR:
 		new_rate = ast2500_configure_ddr(priv->scu, rate);
 		break;
+	case PLL_D2PLL:
+		new_rate = ast2500_configure_d2pll(priv->scu, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -218,9 +395,35 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	return new_rate;
 }
 
+static int ast2500_clk_enable(struct clk *clk)
+{
+	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	/*
+	 * For MAC clocks the clock rate is
+	 * configured based on whether RGMII or RMII mode has been selected
+	 * through hardware strapping.
+	 */
+	case PCLK_MAC1:
+		ast2500_configure_mac(priv->scu, 1);
+		break;
+	case PCLK_MAC2:
+		ast2500_configure_mac(priv->scu, 2);
+		break;
+	case PLL_D2PLL:
+		ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
+	default:
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
 struct clk_ops ast2500_clk_ops = {
 	.get_rate = ast2500_clk_get_rate,
 	.set_rate = ast2500_clk_set_rate,
+	.enable = ast2500_clk_enable,
 };
 
 static int ast2500_clk_probe(struct udevice *dev)
diff --git a/include/dt-bindings/clock/ast2500-scu.h b/include/dt-bindings/clock/ast2500-scu.h
index ca58b12943..e2d7aaf9fe 100644
--- a/include/dt-bindings/clock/ast2500-scu.h
+++ b/include/dt-bindings/clock/ast2500-scu.h
@@ -27,3 +27,5 @@
 #define PCLK_UART3	503
 #define PCLK_UART4	504
 #define PCLK_UART5	505
+#define PCLK_MAC1	506
+#define PCLK_MAC2	507
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 13/15] aspeed: Add support for Clocks needed by MACs
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Add support for clocks needed by MACs to ast2500 clock driver.
The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
PCLK_MAC2 for MAC1 and MAC2 respectively.

The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
SDK. It is not entirely clear from the datasheet how this clock is used
by MACs, so not clear if the rate would ever need to be different. So,
for now, hardcoding it is probably safer.

The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
hardware strapping.

So, the network driver would only need to enable these clocks, no need
to configure the rate.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/dts/ast2500-u-boot.dtsi               |   8 +
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  62 +++++-
 drivers/clk/aspeed/clk_ast2500.c               | 265 ++++++++++++++++++++++---
 include/dt-bindings/clock/ast2500-scu.h        |   2 +
 4 files changed, 304 insertions(+), 33 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index faeeec1be4..f826646095 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -61,3 +61,11 @@
 		};
 	};
 };
+
+&mac0 {
+	clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;
+};
+
+&mac1 {
+	clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>;
+};
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 319d75e05c..fe877b5430 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -30,9 +30,36 @@
 #define SCU_HPLL_POST_SHIFT		13
 #define SCU_HPLL_POST_MASK		0x3f
 
+#define SCU_MACCLK_SHIFT		16
+#define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
+
+#define SCU_MISC2_RGMII_HPLL		(1 << 23)
+#define SCU_MISC2_RGMII_CLKDIV_SHIFT	20
+#define SCU_MISC2_RGMII_CLKDIV_MASK	(3 << SCU_MISC2_RGMII_CLKDIV_SHIFT)
+#define SCU_MISC2_RMII_MPLL		(1 << 19)
+#define SCU_MISC2_RMII_CLKDIV_SHIFT	16
+#define SCU_MISC2_RMII_CLKDIV_MASK	(3 << SCU_MISC2_RMII_CLKDIV_SHIFT)
 #define SCU_MISC2_UARTCLK_SHIFT		24
 
+#define SCU_MISC_D2PLL_OFF		(1 << 4)
 #define SCU_MISC_UARTCLK_DIV13		(1 << 12)
+#define SCU_MISC_GCRT_USB20CLK		(1 << 21)
+
+#define SCU_MICDS_MAC1RGMII_TXDLY_SHIFT	0
+#define SCU_MICDS_MAC1RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC2RGMII_TXDLY_SHIFT	6
+#define SCU_MICDS_MAC2RGMII_TXDLY_MASK	(0x3f\
+					 << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_RDLY_SHIFT	12
+#define SCU_MICDS_MAC1RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC2RMII_RDLY_SHIFT	18
+#define SCU_MICDS_MAC2RMII_RDLY_MASK	(0x3f << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+#define SCU_MICDS_MAC1RMII_TXFALL	(1 << 24)
+#define SCU_MICDS_MAC2RMII_TXFALL	(1 << 25)
+#define SCU_MICDS_RMII1_RCLKEN		(1 << 29)
+#define SCU_MICDS_RMII2_RCLKEN		(1 << 30)
+#define SCU_MICDS_RGMIIPLL		(1 << 31)
 
 /*
  * SYSRESET is actually more like a Power register,
@@ -71,14 +98,45 @@
  */
 #define SCU_PIN_FUN_MAC1_MDC		(1 << 30)
 #define SCU_PIN_FUN_MAC1_MDIO		(1 << 31)
-#define SCU_PIN_FUN_MAC1_PHY_LINK		(1 << 0)
+#define SCU_PIN_FUN_MAC1_PHY_LINK	(1 << 0)
 #define SCU_PIN_FUN_MAC2_MDIO		(1 << 2)
-#define SCU_PIN_FUN_MAC2_PHY_LINK		(1 << 1)
+#define SCU_PIN_FUN_MAC2_PHY_LINK	(1 << 1)
 #define SCU_PIN_FUN_SCL1		(1 << 12)
 #define SCU_PIN_FUN_SCL2		(1 << 14)
 #define SCU_PIN_FUN_SDA1		(1 << 13)
 #define SCU_PIN_FUN_SDA2		(1 << 15)
 
+#define SCU_CLKSTOP_MAC1		(1 << 20)
+#define SCU_CLKSTOP_MAC2		(1 << 21)
+
+#define SCU_D2PLL_EXT1_OFF		(1 << 0)
+#define SCU_D2PLL_EXT1_BYPASS		(1 << 1)
+#define SCU_D2PLL_EXT1_RESET		(1 << 2)
+#define SCU_D2PLL_EXT1_MODE_SHIFT	3
+#define SCU_D2PLL_EXT1_MODE_MASK	(3 << SCU_D2PLL_EXT1_MODE_SHIFT)
+#define SCU_D2PLL_EXT1_PARAM_SHIFT	5
+#define SCU_D2PLL_EXT1_PARAM_MASK	(0x1ff << SCU_D2PLL_EXT1_PARAM_SHIFT)
+
+#define SCU_D2PLL_NUM_SHIFT		0
+#define SCU_D2PLL_NUM_MASK		(0xff << SCU_D2PLL_NUM_SHIFT)
+#define SCU_D2PLL_DENUM_SHIFT		8
+#define SCU_D2PLL_DENUM_MASK		(0x1f << SCU_D2PLL_DENUM_SHIFT)
+#define SCU_D2PLL_POST_SHIFT		13
+#define SCU_D2PLL_POST_MASK		(0x3f << SCU_D2PLL_POST_SHIFT)
+#define SCU_D2PLL_ODIV_SHIFT		19
+#define SCU_D2PLL_ODIV_MASK		(7 << SCU_D2PLL_ODIV_SHIFT)
+#define SCU_D2PLL_SIC_SHIFT		22
+#define SCU_D2PLL_SIC_MASK		(0x1f << SCU_D2PLL_SIC_SHIFT)
+#define SCU_D2PLL_SIP_SHIFT		27
+#define SCU_D2PLL_SIP_MASK		(0x1f << SCU_D2PLL_SIP_SHIFT)
+
+#define SCU_CLKDUTY_DCLK_SHIFT		0
+#define SCU_CLKDUTY_DCLK_MASK		(0x3f << SCU_CLKDUTY_DCLK_SHIFT)
+#define SCU_CLKDUTY_RGMII1TXCK_SHIFT	8
+#define SCU_CLKDUTY_RGMII1TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII1TXCK_SHIFT)
+#define SCU_CLKDUTY_RGMII2TXCK_SHIFT	16
+#define SCU_CLKDUTY_RGMII2TXCK_MASK	(0x7f << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 struct ast2500_clk_priv {
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 9e4c66ea85..7b4b5c64ac 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -12,16 +12,39 @@
 #include <dm/lists.h>
 #include <dt-bindings/clock/ast2500-scu.h>
 
+/*
+ * MAC Clock Delay settings, taken from Aspeed SDK
+ */
+#define RGMII_TXCLK_ODLY		8
+#define RMII_RXCLK_IDLY		2
+
+/*
+ * TGMII Clock Duty constants, taken from Aspeed SDK
+ */
+#define RGMII2_TXCK_DUTY	0x66
+#define RGMII1_TXCK_DUTY	0x64
+
+#define D2PLL_DEFAULT_RATE	(250 * 1000 * 1000)
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
+ * Clock divider/multiplier configuration struct.
  * For H-PLL and M-PLL the formula is
  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
  * M - Numerator
  * N - Denumerator
  * P - Post Divider
  * They have the same layout in their control register.
+ *
+ * D-PLL and D2-PLL have extra divider (OD + 1), which is not
+ * yet needed and ignored by clock configurations.
  */
+struct ast2500_div_config {
+	unsigned int num;
+	unsigned int denum;
+	unsigned int post_div;
+};
 
 /*
  * Get the rate of the M-PLL clock from input clock frequency and
@@ -143,30 +166,41 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	return rate;
 }
 
-static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+/*
+ * @input_rate - the rate of input clock in Hz
+ * @requested_rate - desired output rate in Hz
+ * @div - this is an IN/OUT parameter, at input all fields of the config
+ * need to be set to their maximum allowed values.
+ * The result (the best config we could find), would also be returned
+ * in this structure.
+ *
+ * @return The clock rate, when the resulting div_config is used.
+ */
+static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
+				       struct ast2500_div_config *cfg)
 {
-	ulong clkin = ast2500_get_clkin(scu);
-	u32 mpll_reg;
-
 	/*
-	 * There are not that many combinations of numerator, denumerator
-	 * and post divider, so just brute force the best combination.
-	 * However, to avoid overflow when multiplying, use kHz.
+	 * The assumption is that kHz precision is good enough and
+	 * also enough to avoid overflow when multiplying.
 	 */
-	const ulong clkin_khz = clkin / 1000;
-	const ulong rate_khz = rate / 1000;
-	ulong best_num = 0;
-	ulong best_denum = 0;
-	ulong best_post = 0;
-	ulong delta = rate;
-	ulong num, denum, post;
-
-	for (denum = 0; denum <= SCU_MPLL_DENUM_MASK; ++denum) {
-		for (post = 0; post <= SCU_MPLL_POST_MASK; ++post) {
-			num = (rate_khz * (post + 1) / clkin_khz) * (denum + 1);
-			ulong new_rate_khz = (clkin_khz
-					      * ((num + 1) / (denum + 1)))
-					     / (post + 1);
+	const ulong input_rate_khz = input_rate / 1000;
+	const ulong rate_khz = requested_rate / 1000;
+	const struct ast2500_div_config max_vals = *cfg;
+	struct ast2500_div_config it = { 0, 0, 0 };
+	ulong delta = rate_khz;
+	ulong new_rate_khz = 0;
+
+	for (; it.denum <= max_vals.denum; ++it.denum) {
+		for (it.post_div = 0; it.post_div <= max_vals.post_div;
+		     ++it.post_div) {
+			it.num = (rate_khz * (it.post_div + 1) / input_rate_khz)
+			    * (it.denum + 1);
+			if (it.num > max_vals.num)
+				continue;
+
+			new_rate_khz = (input_rate_khz
+					* ((it.num + 1) / (it.denum + 1)))
+			    / (it.post_div + 1);
 
 			/* Keep the rate below requested one. */
 			if (new_rate_khz > rate_khz)
@@ -174,25 +208,35 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 
 			if (new_rate_khz - rate_khz < delta) {
 				delta = new_rate_khz - rate_khz;
-
-				best_num = num;
-				best_denum = denum;
-				best_post = post;
-
+				*cfg = it;
 				if (delta == 0)
-					goto rate_calc_done;
+					return new_rate_khz * 1000;
 			}
 		}
 	}
 
- rate_calc_done:
+	return new_rate_khz * 1000;
+}
+
+static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	u32 mpll_reg;
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_MPLL_NUM_MASK,
+		.denum = SCU_MPLL_DENUM_MASK,
+		.post_div = SCU_MPLL_POST_MASK
+	};
+
+	ast2500_calc_clock_config(clkin, rate, &div_cfg);
+
 	mpll_reg = readl(&scu->m_pll_param);
 	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
 		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
 		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
-	mpll_reg |= (best_post << SCU_MPLL_POST_SHIFT)
-	    | (best_num << SCU_MPLL_NUM_SHIFT)
-	    | (best_denum << SCU_MPLL_DENUM_SHIFT);
+	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
+	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
+	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
 
 	ast_scu_unlock(scu);
 	writel(mpll_reg, &scu->m_pll_param);
@@ -201,6 +245,136 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	return ast2500_get_mpll_rate(clkin, mpll_reg);
 }
 
+static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index)
+{
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong hpll_rate = ast2500_get_hpll_rate(clkin,
+						readl(&scu->h_pll_param));
+	ulong required_rate;
+	u32 hwstrap;
+	u32 divisor;
+	u32 reset_bit;
+	u32 clkstop_bit;
+
+	/*
+	 * According to data sheet, for 10/100 mode the MAC clock frequency
+	 * should be at least 25MHz and for 1000 mode at least 100MHz
+	 */
+	hwstrap = readl(&scu->hwstrap);
+	if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII))
+		required_rate = 100 * 1000 * 1000;
+	else
+		required_rate = 25 * 1000 * 1000;
+
+	divisor = hpll_rate / required_rate;
+
+	if (divisor < 4) {
+		/* Clock can't run fast enough, but let's try anyway */
+		debug("MAC clock too slow\n");
+		divisor = 4;
+	} else if (divisor > 16) {
+		/* Can't slow down the clock enough, but let's try anyway */
+		debug("MAC clock too fast\n");
+		divisor = 16;
+	}
+
+	switch (index) {
+	case 1:
+		reset_bit = SCU_SYSRESET_MAC1;
+		clkstop_bit = SCU_CLKSTOP_MAC1;
+		break;
+	case 2:
+		reset_bit = SCU_SYSRESET_MAC2;
+		clkstop_bit = SCU_CLKSTOP_MAC2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ast_scu_unlock(scu);
+	clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK,
+			((divisor - 2) / 2) << SCU_MACCLK_SHIFT);
+
+	/*
+	 * Disable MAC, start its clock and re-enable it.
+	 * The procedure and the delays (100us & 10ms) are
+	 * specified in the datasheet.
+	 */
+	setbits_le32(&scu->sysreset_ctrl1, reset_bit);
+	udelay(100);
+	clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit);
+	mdelay(10);
+	clrbits_le32(&scu->sysreset_ctrl1, reset_bit);
+
+	writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT)
+	       | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT),
+	       &scu->clk_duty_sel);
+
+	ast_scu_lock(scu);
+
+	return required_rate;
+}
+
+static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
+{
+	/*
+	 * The values and the meaning of the next three
+	 * parameters are undocumented. Taken from Aspeed SDK.
+	 */
+	const u32 d2_pll_ext_param = 0x2c;
+	const u32 d2_pll_sip = 0x11;
+	const u32 d2_pll_sic = 0x18;
+	u32 clk_delay_settings =
+	    (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT)
+	    | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT)
+	    | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT);
+	struct ast2500_div_config div_cfg = {
+		.num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT,
+		.denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT,
+		.post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT,
+	};
+	ulong clkin = ast2500_get_clkin(scu);
+	ulong new_rate;
+
+	ast_scu_unlock(scu);
+	writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT)
+	       | SCU_D2PLL_EXT1_OFF
+	       | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]);
+
+	/*
+	 * Select USB2.0 port1 PHY clock as a clock source for GCRT.
+	 * This would disconnect it from D2-PLL.
+	 */
+	clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF,
+			SCU_MISC_GCRT_USB20CLK);
+
+	new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg);
+	writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT)
+	       | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT)
+	       | (div_cfg.num << SCU_D2PLL_NUM_SHIFT)
+	       | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT)
+	       | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT),
+	       &scu->d2_pll_param);
+
+	clrbits_le32(&scu->d2_pll_ext_param[0],
+		     SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET);
+
+	clrsetbits_le32(&scu->misc_ctrl2,
+			SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL
+			| SCU_MISC2_RGMII_CLKDIV_MASK |
+			SCU_MISC2_RMII_CLKDIV_MASK,
+			(4 << SCU_MISC2_RMII_CLKDIV_SHIFT));
+
+	writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay);
+	writel(clk_delay_settings, &scu->mac_clk_delay_100M);
+	writel(clk_delay_settings, &scu->mac_clk_delay_10M);
+
+	ast_scu_lock(scu);
+
+	return new_rate;
+}
+
 static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 {
 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
@@ -211,6 +385,9 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	case MCLK_DDR:
 		new_rate = ast2500_configure_ddr(priv->scu, rate);
 		break;
+	case PLL_D2PLL:
+		new_rate = ast2500_configure_d2pll(priv->scu, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -218,9 +395,35 @@ static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate)
 	return new_rate;
 }
 
+static int ast2500_clk_enable(struct clk *clk)
+{
+	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	/*
+	 * For MAC clocks the clock rate is
+	 * configured based on whether RGMII or RMII mode has been selected
+	 * through hardware strapping.
+	 */
+	case PCLK_MAC1:
+		ast2500_configure_mac(priv->scu, 1);
+		break;
+	case PCLK_MAC2:
+		ast2500_configure_mac(priv->scu, 2);
+		break;
+	case PLL_D2PLL:
+		ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
+	default:
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
 struct clk_ops ast2500_clk_ops = {
 	.get_rate = ast2500_clk_get_rate,
 	.set_rate = ast2500_clk_set_rate,
+	.enable = ast2500_clk_enable,
 };
 
 static int ast2500_clk_probe(struct udevice *dev)
diff --git a/include/dt-bindings/clock/ast2500-scu.h b/include/dt-bindings/clock/ast2500-scu.h
index ca58b12943..e2d7aaf9fe 100644
--- a/include/dt-bindings/clock/ast2500-scu.h
+++ b/include/dt-bindings/clock/ast2500-scu.h
@@ -27,3 +27,5 @@
 #define PCLK_UART3	503
 #define PCLK_UART4	504
 #define PCLK_UART5	505
+#define PCLK_MAC1	506
+#define PCLK_MAC2	507
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 14/15] aspeed: Refactor SCU to use consistent mask & shift
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Refactor SCU header to use consistent Mask & Shift values.
Now, consistently, to read value from SCU register, mask needs
to be applied before shift.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 12 ++++----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  5 ++--
 drivers/clk/aspeed/clk_ast2500.c               | 39 +++++++++++++-------------
 3 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fe877b5430..590aed2f6c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -8,8 +8,8 @@
 
 #define SCU_UNLOCK_VALUE		0x1688a8a8
 
-#define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_VGAMEM_MASK		(3 << SCU_HWSTRAP_VGAMEM_SHIFT)
 #define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
 #define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
@@ -18,17 +18,17 @@
 #define SCU_MPLL_DENUM_SHIFT		0
 #define SCU_MPLL_DENUM_MASK		0x1f
 #define SCU_MPLL_NUM_SHIFT		5
-#define SCU_MPLL_NUM_MASK		0xff
+#define SCU_MPLL_NUM_MASK		(0xff << SCU_MPLL_NUM_SHIFT)
 #define SCU_MPLL_POST_SHIFT		13
-#define SCU_MPLL_POST_MASK		0x3f
+#define SCU_MPLL_POST_MASK		(0x3f << SCU_MPLL_POST_SHIFT)
 #define SCU_PCLK_DIV_SHIFT		23
-#define SCU_PCLK_DIV_MASK		7
+#define SCU_PCLK_DIV_MASK		(7 << SCU_PCLK_DIV_SHIFT)
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
-#define SCU_HPLL_NUM_MASK		0xff
+#define SCU_HPLL_NUM_MASK		(0xff << SCU_HPLL_NUM_SHIFT)
 #define SCU_HPLL_POST_SHIFT		13
-#define SCU_HPLL_POST_MASK		0x3f
+#define SCU_HPLL_POST_MASK		(0x3f << SCU_HPLL_POST_SHIFT)
 
 #define SCU_MACCLK_SHIFT		16
 #define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index efcf452b17..6383f727f2 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -183,9 +183,8 @@ static int ast2500_sdrammc_ddr4_calibrate_vref(struct dram_info *info)
 static size_t ast2500_sdrammc_get_vga_mem_size(struct dram_info *info)
 {
 	size_t vga_mem_size_base = 8 * 1024 * 1024;
-	u32 vga_hwconf = (readl(&info->scu->hwstrap)
-			  >> SCU_HWSTRAP_VGAMEM_SHIFT)
-			& SCU_HWSTRAP_VGAMEM_MASK;
+	u32 vga_hwconf = (readl(&info->scu->hwstrap) & SCU_HWSTRAP_VGAMEM_MASK)
+	    >> SCU_HWSTRAP_VGAMEM_SHIFT;
 
 	return vga_mem_size_base << vga_hwconf;
 }
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 7b4b5c64ac..ccf47a1da1 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -52,11 +52,11 @@ struct ast2500_div_config {
  */
 static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
 {
-	const ulong num = (mpll_reg >> SCU_MPLL_NUM_SHIFT) & SCU_MPLL_NUM_MASK;
-	const ulong denum = (mpll_reg >> SCU_MPLL_DENUM_SHIFT)
-			& SCU_MPLL_DENUM_MASK;
-	const ulong post_div = (mpll_reg >> SCU_MPLL_POST_SHIFT)
-			& SCU_MPLL_POST_MASK;
+	const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT;
+	const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK)
+			>> SCU_MPLL_DENUM_SHIFT;
+	const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK)
+			>> SCU_MPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -67,11 +67,11 @@ static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
  */
 static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg)
 {
-	const ulong num = (hpll_reg >> SCU_HPLL_NUM_SHIFT) & SCU_HPLL_NUM_MASK;
-	const ulong denum = (hpll_reg >> SCU_HPLL_DENUM_SHIFT)
-			& SCU_HPLL_DENUM_MASK;
-	const ulong post_div = (hpll_reg >> SCU_HPLL_POST_SHIFT)
-			& SCU_HPLL_POST_MASK;
+	const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT;
+	const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK)
+			>> SCU_HPLL_DENUM_SHIFT;
+	const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK)
+			>> SCU_HPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -136,11 +136,11 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	case BCLK_PCLK:
 		{
 			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
-						  >> SCU_PCLK_DIV_SHIFT) &
-						 SCU_PCLK_DIV_MASK);
+						  & SCU_PCLK_DIV_MASK)
+						 >> SCU_PCLK_DIV_SHIFT);
 			rate = ast2500_get_hpll_rate(clkin,
-						     readl(&priv->scu->
-							   h_pll_param));
+						     readl(&priv->
+							   scu->h_pll_param));
 			rate = rate / apb_div;
 		}
 		break;
@@ -223,17 +223,16 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	ulong clkin = ast2500_get_clkin(scu);
 	u32 mpll_reg;
 	struct ast2500_div_config div_cfg = {
-		.num = SCU_MPLL_NUM_MASK,
-		.denum = SCU_MPLL_DENUM_MASK,
-		.post_div = SCU_MPLL_POST_MASK
+		.num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
+		.denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
+		.post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
 	};
 
 	ast2500_calc_clock_config(clkin, rate, &div_cfg);
 
 	mpll_reg = readl(&scu->m_pll_param);
-	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
-		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
-		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
+	mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
+		      | SCU_MPLL_DENUM_MASK);
 	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
 	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
 	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 14/15] aspeed: Refactor SCU to use consistent mask & shift
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Refactor SCU header to use consistent Mask & Shift values.
Now, consistently, to read value from SCU register, mask needs
to be applied before shift.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 12 ++++----
 arch/arm/mach-aspeed/ast2500/sdram_ast2500.c   |  5 ++--
 drivers/clk/aspeed/clk_ast2500.c               | 39 +++++++++++++-------------
 3 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index fe877b5430..590aed2f6c 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -8,8 +8,8 @@
 
 #define SCU_UNLOCK_VALUE		0x1688a8a8
 
-#define SCU_HWSTRAP_VGAMEM_MASK		3
 #define SCU_HWSTRAP_VGAMEM_SHIFT	2
+#define SCU_HWSTRAP_VGAMEM_MASK		(3 << SCU_HWSTRAP_VGAMEM_SHIFT)
 #define SCU_HWSTRAP_MAC1_RGMII		(1 << 6)
 #define SCU_HWSTRAP_MAC2_RGMII		(1 << 7)
 #define SCU_HWSTRAP_DDR4		(1 << 24)
@@ -18,17 +18,17 @@
 #define SCU_MPLL_DENUM_SHIFT		0
 #define SCU_MPLL_DENUM_MASK		0x1f
 #define SCU_MPLL_NUM_SHIFT		5
-#define SCU_MPLL_NUM_MASK		0xff
+#define SCU_MPLL_NUM_MASK		(0xff << SCU_MPLL_NUM_SHIFT)
 #define SCU_MPLL_POST_SHIFT		13
-#define SCU_MPLL_POST_MASK		0x3f
+#define SCU_MPLL_POST_MASK		(0x3f << SCU_MPLL_POST_SHIFT)
 #define SCU_PCLK_DIV_SHIFT		23
-#define SCU_PCLK_DIV_MASK		7
+#define SCU_PCLK_DIV_MASK		(7 << SCU_PCLK_DIV_SHIFT)
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
-#define SCU_HPLL_NUM_MASK		0xff
+#define SCU_HPLL_NUM_MASK		(0xff << SCU_HPLL_NUM_SHIFT)
 #define SCU_HPLL_POST_SHIFT		13
-#define SCU_HPLL_POST_MASK		0x3f
+#define SCU_HPLL_POST_MASK		(0x3f << SCU_HPLL_POST_SHIFT)
 
 #define SCU_MACCLK_SHIFT		16
 #define SCU_MACCLK_MASK			(7 << SCU_MACCLK_SHIFT)
diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
index efcf452b17..6383f727f2 100644
--- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
+++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c
@@ -183,9 +183,8 @@ static int ast2500_sdrammc_ddr4_calibrate_vref(struct dram_info *info)
 static size_t ast2500_sdrammc_get_vga_mem_size(struct dram_info *info)
 {
 	size_t vga_mem_size_base = 8 * 1024 * 1024;
-	u32 vga_hwconf = (readl(&info->scu->hwstrap)
-			  >> SCU_HWSTRAP_VGAMEM_SHIFT)
-			& SCU_HWSTRAP_VGAMEM_MASK;
+	u32 vga_hwconf = (readl(&info->scu->hwstrap) & SCU_HWSTRAP_VGAMEM_MASK)
+	    >> SCU_HWSTRAP_VGAMEM_SHIFT;
 
 	return vga_mem_size_base << vga_hwconf;
 }
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 7b4b5c64ac..ccf47a1da1 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -52,11 +52,11 @@ struct ast2500_div_config {
  */
 static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
 {
-	const ulong num = (mpll_reg >> SCU_MPLL_NUM_SHIFT) & SCU_MPLL_NUM_MASK;
-	const ulong denum = (mpll_reg >> SCU_MPLL_DENUM_SHIFT)
-			& SCU_MPLL_DENUM_MASK;
-	const ulong post_div = (mpll_reg >> SCU_MPLL_POST_SHIFT)
-			& SCU_MPLL_POST_MASK;
+	const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT;
+	const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK)
+			>> SCU_MPLL_DENUM_SHIFT;
+	const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK)
+			>> SCU_MPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -67,11 +67,11 @@ static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg)
  */
 static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg)
 {
-	const ulong num = (hpll_reg >> SCU_HPLL_NUM_SHIFT) & SCU_HPLL_NUM_MASK;
-	const ulong denum = (hpll_reg >> SCU_HPLL_DENUM_SHIFT)
-			& SCU_HPLL_DENUM_MASK;
-	const ulong post_div = (hpll_reg >> SCU_HPLL_POST_SHIFT)
-			& SCU_HPLL_POST_MASK;
+	const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT;
+	const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK)
+			>> SCU_HPLL_DENUM_SHIFT;
+	const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK)
+			>> SCU_HPLL_POST_SHIFT;
 
 	return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1);
 }
@@ -136,11 +136,11 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 	case BCLK_PCLK:
 		{
 			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
-						  >> SCU_PCLK_DIV_SHIFT) &
-						 SCU_PCLK_DIV_MASK);
+						  & SCU_PCLK_DIV_MASK)
+						 >> SCU_PCLK_DIV_SHIFT);
 			rate = ast2500_get_hpll_rate(clkin,
-						     readl(&priv->scu->
-							   h_pll_param));
+						     readl(&priv->
+							   scu->h_pll_param));
 			rate = rate / apb_div;
 		}
 		break;
@@ -223,17 +223,16 @@ static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate)
 	ulong clkin = ast2500_get_clkin(scu);
 	u32 mpll_reg;
 	struct ast2500_div_config div_cfg = {
-		.num = SCU_MPLL_NUM_MASK,
-		.denum = SCU_MPLL_DENUM_MASK,
-		.post_div = SCU_MPLL_POST_MASK
+		.num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT),
+		.denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT),
+		.post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT),
 	};
 
 	ast2500_calc_clock_config(clkin, rate, &div_cfg);
 
 	mpll_reg = readl(&scu->m_pll_param);
-	mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT)
-		      | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT)
-		      | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT));
+	mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK
+		      | SCU_MPLL_DENUM_MASK);
 	mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT)
 	    | (div_cfg.num << SCU_MPLL_NUM_SHIFT)
 	    | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT);
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [PATCH v2 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
  2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
@ 2017-05-05 22:01     ` Maxim Sloyko
  -1 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot, Simon Glass; +Cc: openbmc, Maxim Sloyko, Albert Aribaud

Remove unnecessary apb and ahb nodes and just override necessary
nodes/values.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1: None


---
 arch/arm/dts/ast2500-u-boot.dtsi | 41 ++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index f826646095..7f80bad7d0 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -34,32 +34,33 @@
 
 		apb {
 			u-boot,dm-pre-reloc;
+		};
 
-			timer: timer@1e782000 {
-				u-boot,dm-pre-reloc;
-			};
+	};
+};
 
-			uart1: serial@1e783000 {
-				clocks = <&scu PCLK_UART1>;
-			};
+&uart1 {
+	clocks = <&scu PCLK_UART1>;
+};
 
-			uart2: serial@1e78d000 {
-				clocks = <&scu PCLK_UART2>;
-			};
+&uart2 {
+	clocks = <&scu PCLK_UART2>;
+};
 
-			uart3: serial@1e78e000 {
-				clocks = <&scu PCLK_UART3>;
-			};
+&uart3 {
+	clocks = <&scu PCLK_UART3>;
+};
 
-			uart4: serial@1e78f000 {
-				clocks = <&scu PCLK_UART4>;
-			};
+&uart4 {
+	clocks = <&scu PCLK_UART4>;
+};
 
-			uart5: serial@1e784000 {
-				clocks = <&scu PCLK_UART5>;
-			};
-		};
-	};
+&uart5 {
+	clocks = <&scu PCLK_UART5>;
+};
+
+&timer {
+	u-boot,dm-pre-reloc;
 };
 
 &mac0 {
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* [U-Boot] [PATCH v2 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
@ 2017-05-05 22:01     ` Maxim Sloyko
  0 siblings, 0 replies; 132+ messages in thread
From: Maxim Sloyko @ 2017-05-05 22:01 UTC (permalink / raw)
  To: u-boot

Remove unnecessary apb and ahb nodes and just override necessary
nodes/values.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2: None
Changes in v1: None


---
 arch/arm/dts/ast2500-u-boot.dtsi | 41 ++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi
index f826646095..7f80bad7d0 100644
--- a/arch/arm/dts/ast2500-u-boot.dtsi
+++ b/arch/arm/dts/ast2500-u-boot.dtsi
@@ -34,32 +34,33 @@
 
 		apb {
 			u-boot,dm-pre-reloc;
+		};
 
-			timer: timer at 1e782000 {
-				u-boot,dm-pre-reloc;
-			};
+	};
+};
 
-			uart1: serial at 1e783000 {
-				clocks = <&scu PCLK_UART1>;
-			};
+&uart1 {
+	clocks = <&scu PCLK_UART1>;
+};
 
-			uart2: serial at 1e78d000 {
-				clocks = <&scu PCLK_UART2>;
-			};
+&uart2 {
+	clocks = <&scu PCLK_UART2>;
+};
 
-			uart3: serial at 1e78e000 {
-				clocks = <&scu PCLK_UART3>;
-			};
+&uart3 {
+	clocks = <&scu PCLK_UART3>;
+};
 
-			uart4: serial at 1e78f000 {
-				clocks = <&scu PCLK_UART4>;
-			};
+&uart4 {
+	clocks = <&scu PCLK_UART4>;
+};
 
-			uart5: serial at 1e784000 {
-				clocks = <&scu PCLK_UART5>;
-			};
-		};
-	};
+&uart5 {
+	clocks = <&scu PCLK_UART5>;
+};
+
+&timer {
+	u-boot,dm-pre-reloc;
 };
 
 &mac0 {
-- 
2.13.0.rc1.294.g07d810a77f-goog

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

* Re: [U-Boot,v1,01/15] aspeed: Update ast2500 Device Tree
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:20PM -0700, maxims@google.com wrote:

> Pull in the Device Tree for ast2500 from the mainline Linux kernel.
> The file is copied from
> https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot,v1,01/15] aspeed: Update ast2500 Device Tree
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:20PM -0700, maxims at google.com wrote:

> Pull in the Device Tree for ast2500 from the mainline Linux kernel.
> The file is copied from
> https://raw.githubusercontent.com/torvalds/linux/34ea5c9d/arch/arm/boot/dts/aspeed-g5.dtsi
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/83709bc1/attachment.sig>

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

* Re: [U-Boot,v1,02/15] dm: Simple Watchdog uclass
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, Stephen Warren, openbmc

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

On Mon, Apr 17, 2017 at 12:00:21PM -0700, maxims@google.com wrote:

> This is a simple uclass for Watchdog Timers. It has four operations:
> start, restart, reset, stop. Drivers must implement start, restart and
> stop operations, while implementing reset is optional: It's default
> implementation expires watchdog timer in one clock tick.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot,v1,02/15] dm: Simple Watchdog uclass
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:21PM -0700, maxims at google.com wrote:

> This is a simple uclass for Watchdog Timers. It has four operations:
> start, restart, reset, stop. Drivers must implement start, restart and
> stop operations, while implementing reset is optional: It's default
> implementation expires watchdog timer in one clock tick.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/5aefee6d/attachment.sig>

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

* Re: [U-Boot,v1,03/15] aspeed: Watchdog Timer Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:22PM -0700, maxims@google.com wrote:

> This driver supports ast2500 and ast2400 SoCs.
> Only ast2500 supports reset_mask and thus the option of resettting
> individual peripherals using WDT.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot,v1,03/15] aspeed: Watchdog Timer Driver
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:22PM -0700, maxims at google.com wrote:

> This driver supports ast2500 and ast2400 SoCs.
> Only ast2500 supports reset_mask and thus the option of resettting
> individual peripherals using WDT.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/0352a0b0/attachment.sig>

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

* Re: [U-Boot, v1, 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:23PM -0700, maxims@google.com wrote:

> Make functions for locking and unlocking SCU part of SCU API.
> Many drivers need to modify settings in SCU and thus need to unlock it
> first. This change makes it possible.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 04/15] aspeed: Make SCU lock/unlock functions part of SCU API
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:23PM -0700, maxims at google.com wrote:

> Make functions for locking and unlocking SCU part of SCU API.
> Many drivers need to modify settings in SCU and thus need to unlock it
> first. This change makes it possible.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/6dfe1c35/attachment.sig>

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

* Re: [U-Boot,v1,05/15] aspeed: Reset Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, Stephen Warren, openbmc, Tom Warren

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

On Mon, Apr 17, 2017 at 12:00:24PM -0700, maxims@google.com wrote:

> Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
> perform resets and thus depends on it. The actual Watchdog device used
> needs to be configured in Device Tree using "aspeed,wdt" property, which
> must be WDT phandle, for example:
> 
> rst: reset-controller {
>     compatible = "aspeed,ast2500-reset";
>     aspeed,wdt = <&wdt1>;
> }
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot,v1,05/15] aspeed: Reset Driver
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:24PM -0700, maxims at google.com wrote:

> Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
> perform resets and thus depends on it. The actual Watchdog device used
> needs to be configured in Device Tree using "aspeed,wdt" property, which
> must be WDT phandle, for example:
> 
> rst: reset-controller {
>     compatible = "aspeed,ast2500-reset";
>     aspeed,wdt = <&wdt1>;
> }
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/99cd10b7/attachment.sig>

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

* Re: [U-Boot,v1,06/15] aspeed: Device Tree configuration for Reset Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:25PM -0700, maxims@google.com wrote:

> Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
> for various reset signals
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 06/15] aspeed: Device Tree configuration for Reset Driver
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:25PM -0700, maxims at google.com wrote:

> Add Reset Driver configuration to ast2500 SoC Device Tree and bindings
> for various reset signals
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/3fefe114/attachment.sig>

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

* Re: [U-Boot, v1, 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:26PM -0700, maxims@google.com wrote:

> This change switches all existing users of ast2500 Watchdog to Driver
> Model based Watchdog driver.
> 
> To perform system reset Sysreset Driver uses first Watchdog device found
> via uclass_first_device call. Since the system is going to be reset
> anyway it does not make much difference which watchdog is used.
> 
> Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
> driver to do that.
> 
> These were the only users of the old Watchdog API, so that API is
> removed.
> 
> This all is done in one change to avoid having to maintain dual API for
> watchdog in between.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:26PM -0700, maxims at google.com wrote:

> This change switches all existing users of ast2500 Watchdog to Driver
> Model based Watchdog driver.
> 
> To perform system reset Sysreset Driver uses first Watchdog device found
> via uclass_first_device call. Since the system is going to be reset
> anyway it does not make much difference which watchdog is used.
> 
> Instead of using Watchdog to reset itself, SDRAM driver now uses Reset
> driver to do that.
> 
> These were the only users of the old Watchdog API, so that API is
> removed.
> 
> This all is done in one change to avoid having to maintain dual API for
> watchdog in between.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/732b4344/attachment.sig>

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

* Re: [U-Boot,v1,08/15] aspeed: AST2500 Pinctrl Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc, Wills Wang, Thomas Abraham

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

On Mon, Apr 17, 2017 at 12:00:27PM -0700, maxims@google.com wrote:

> This driver uses Generic Pinctrl framework and is compatible with
> the Linux driver for ast2500: it uses the same device tree
> configuration.
> 
> Not all pins are supported by the driver at the moment, so it actually
> compatible with ast2400. In general, however, there are differences that
> in the future would be easier to maintain separately.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot,v1,08/15] aspeed: AST2500 Pinctrl Driver
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:27PM -0700, maxims at google.com wrote:

> This driver uses Generic Pinctrl framework and is compatible with
> the Linux driver for ast2500: it uses the same device tree
> configuration.
> 
> Not all pins are supported by the driver at the moment, so it actually
> compatible with ast2400. In general, however, there are differences that
> in the future would be easier to maintain separately.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/db0d9974/attachment.sig>

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

* Re: [U-Boot,v1,09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:28PM -0700, maxims@google.com wrote:

> Enable Pinctrl Driver in AST2500 Eval Board's defconfig
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:28PM -0700, maxims at google.com wrote:

> Enable Pinctrl Driver in AST2500 Eval Board's defconfig
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/8a02dc9c/attachment.sig>

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

* Re: [U-Boot, v1, 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:29PM -0700, maxims@google.com wrote:

> Add P-Bus Clock support to ast2500 clock driver.
> This is the clock used by I2C devices.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 10/15] aspeed: Add P-Bus clock in ast2500 clock driver
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:29PM -0700, maxims at google.com wrote:

> Add P-Bus Clock support to ast2500 clock driver.
> This is the clock used by I2C devices.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/0c865943/attachment.sig>

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

* Re: [U-Boot,v1,11/15] aspeed: Add I2C Driver
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:42     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:30PM -0700, maxims@google.com wrote:

> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> The driver is very limited, it only supports master mode and
> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Acked-by: Heiko Schocher <hs@denx.de>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot,v1,11/15] aspeed: Add I2C Driver
@ 2017-05-08 19:42     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:42 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:30PM -0700, maxims at google.com wrote:

> Add Device Model based I2C driver for ast2500/ast2400 SoCs.
> The driver is very limited, it only supports master mode and
> synchronous byte-by-byte reads/writes, no DMA or Pool Buffers.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Acked-by: Heiko Schocher <hs@denx.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/de68648a/attachment-0001.sig>

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

* Re: [U-Boot,v1,12/15] aspeed: Enable I2C in EVB defconfig
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:43     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:31PM -0700, maxims@google.com wrote:

> Enable I2C driver in ast2500 Eval Board defconfig.
> Also enable i2c command.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot,v1,12/15] aspeed: Enable I2C in EVB defconfig
@ 2017-05-08 19:43     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:31PM -0700, maxims at google.com wrote:

> Enable I2C driver in ast2500 Eval Board defconfig.
> Also enable i2c command.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/459f2da9/attachment.sig>

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

* Re: [U-Boot,v1,13/15] aspeed: Add support for Clocks needed by MACs
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:43     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:32PM -0700, maxims@google.com wrote:

> Add support for clocks needed by MACs to ast2500 clock driver.
> The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
> PCLK_MAC2 for MAC1 and MAC2 respectively.
> 
> The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
> SDK. It is not entirely clear from the datasheet how this clock is used
> by MACs, so not clear if the rate would ever need to be different. So,
> for now, hardcoding it is probably safer.
> 
> The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
> hardware strapping.
> 
> So, the network driver would only need to enable these clocks, no need
> to configure the rate.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 13/15] aspeed: Add support for Clocks needed by MACs
@ 2017-05-08 19:43     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:32PM -0700, maxims at google.com wrote:

> Add support for clocks needed by MACs to ast2500 clock driver.
> The clocks are D2-PLL, which is used by both MACs and PCLK_MAC1 and
> PCLK_MAC2 for MAC1 and MAC2 respectively.
> 
> The rate of D2-PLL is hardcoded to 250MHz -- the value used in Aspeed
> SDK. It is not entirely clear from the datasheet how this clock is used
> by MACs, so not clear if the rate would ever need to be different. So,
> for now, hardcoding it is probably safer.
> 
> The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected through
> hardware strapping.
> 
> So, the network driver would only need to enable these clocks, no need
> to configure the rate.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/d106e1f2/attachment.sig>

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

* Re: [U-Boot, v1, 14/15] aspeed: Refactor SCU to use consistent mask & shift
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:43     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:33PM -0700, maxims@google.com wrote:

> Refactor SCU header to use consistent Mask & Shift values.
> Now, consistently, to read value from SCU register, mask needs
> to be applied before shift.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 14/15] aspeed: Refactor SCU to use consistent mask & shift
@ 2017-05-08 19:43     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:33PM -0700, maxims at google.com wrote:

> Refactor SCU header to use consistent Mask & Shift values.
> Now, consistently, to read value from SCU register, mask needs
> to be applied before shift.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/09e71d7e/attachment.sig>

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

* Re: [U-Boot, v1, 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
  2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
@ 2017-05-08 19:43     ` Tom Rini
  -1 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: maxims; +Cc: u-boot, Simon Glass, openbmc

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

On Mon, Apr 17, 2017 at 12:00:34PM -0700, maxims@google.com wrote:

> Remove unnecessary apb and ahb nodes and just override necessary
> nodes/values.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

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

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

* [U-Boot] [U-Boot, v1, 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
@ 2017-05-08 19:43     ` Tom Rini
  0 siblings, 0 replies; 132+ messages in thread
From: Tom Rini @ 2017-05-08 19:43 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 17, 2017 at 12:00:34PM -0700, maxims at google.com wrote:

> Remove unnecessary apb and ahb nodes and just override necessary
> nodes/values.
> 
> Signed-off-by: Maxim Sloyko <maxims@google.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170508/929dc9ed/attachment.sig>

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

end of thread, other threads:[~2017-05-08 19:43 UTC | newest]

Thread overview: 132+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-17 19:00 [PATCH v1 00/15] Expand Aspeed AST2500 Support Maxim Sloyko
2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
2017-04-17 19:00 ` [PATCH v1 01/15] aspeed: Update ast2500 Device Tree Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,01/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 02/15] dm: Simple Watchdog uclass Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,02/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 03/15] aspeed: Watchdog Timer Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,03/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 04/15] aspeed: Make SCU lock/unlock functions part of SCU API Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 05/15] aspeed: Reset Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,05/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 06/15] aspeed: Device Tree configuration for " Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,06/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] [U-Boot, v1, 06/15] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 08/15] aspeed: AST2500 Pinctrl Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,08/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,09/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] [U-Boot, v1, 09/15] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 10/15] aspeed: Add P-Bus clock in ast2500 clock driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 11/15] aspeed: Add I2C Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-05 19:18     ` Maxim Sloyko
2017-05-05 19:18       ` [U-Boot] " Maxim Sloyko
2017-04-19 11:58   ` Heiko Schocher
2017-04-19 11:58     ` [U-Boot] " Heiko Schocher
2017-04-19 16:02     ` Maxim Sloyko
2017-04-19 16:02       ` [U-Boot] " Maxim Sloyko
2017-04-20  4:03       ` Heiko Schocher
2017-04-20  4:03         ` [U-Boot] " Heiko Schocher
2017-05-08 19:42   ` [U-Boot,v1,11/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 12/15] aspeed: Enable I2C in EVB defconfig Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot,v1,12/15] " Tom Rini
2017-05-08 19:43     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 13/15] aspeed: Add support for Clocks needed by MACs Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot,v1,13/15] " Tom Rini
2017-05-08 19:43     ` [U-Boot] [U-Boot, v1, 13/15] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 14/15] aspeed: Refactor SCU to use consistent mask & shift Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:43     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:43     ` [U-Boot] " Tom Rini
2017-05-05 22:01 ` [PATCH v2 00/15] Expand Aspeed AST2500 Support Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 01/15] aspeed: Update ast2500 Device Tree Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 02/15] dm: Simple Watchdog uclass Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 03/15] aspeed: Watchdog Timer Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 04/15] aspeed: Make SCU lock/unlock functions part of SCU API Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 05/15] aspeed: Reset Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 06/15] aspeed: Device Tree configuration for " Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 08/15] aspeed: AST2500 Pinctrl Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 10/15] aspeed: Add P-Bus clock in ast2500 clock driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 11/15] aspeed: Add I2C Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 12/15] aspeed: Enable I2C in EVB defconfig Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 13/15] aspeed: Add support for Clocks needed by MACs Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 14/15] aspeed: Refactor SCU to use consistent mask & shift Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko

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