Expand Aspeed AST2500 Support
Subsystems (12)
cover Expand Aspeed AST2500 Support
This series expands support for Aspeed AST2500 SoC, commonly used as Board Management Controller in many servers, to the point where it can actually be useful.
The main goal of this series is I2C and Network drivers, 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.
Maxim Sloyko (17):
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
aspeed: Add AST2500/AST2400 compatible NIC Driver
aspeed: Network Driver configuration for EVB
arch/arm/dts/ast2500-evb.dts | 29 + 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 +- configs/evb-ast2500_defconfig | 13 + drivers/clk/aspeed/clk_ast2500.c | 321 +++++++-- drivers/i2c/Kconfig | 9 + drivers/i2c/Makefile | 1 + drivers/i2c/ast_i2c.c | 355 ++++++++++ drivers/i2c/ast_i2c.h | 132 ++++ drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/ast_nic.c | 584 ++++++++++++++++ drivers/net/ast_nic.h | 198 ++++++ 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 | 109 +++ drivers/sysreset/sysreset_ast.c | 24 +- drivers/watchdog/Kconfig | 24 + drivers/watchdog/Makefile | 2 + drivers/watchdog/ast_wdt.c | 125 ++++ drivers/watchdog/wdt-uclass.c | 79 +++ 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 | 97 +++ 36 files changed, 3390 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/net/ast_nic.c create mode 100644 drivers/net/ast_nic.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/wdt-uclass.c create mode 100644 include/dt-bindings/reset/ast2500-reset.h create mode 100644 include/wdt.h
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
PATCH 1/17 aspeed: Update ast2500 Device Tree
Pull in the Device Tree for ast2500 from the mainline Linux kernel
---
arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 880 insertions(+), 1 deletion(-)
arch/arm/dts/ast2500.dtsi +880 -1
@@ -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>;
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 01/17] aspeed: Update ast2500 Device Tree
Hi Maxim,
Quoted 8 lines · Maxim Sloyko
Pull in the Device Tree for ast2500 from the mainline Linux kernel
Signed-off-by Maxim Sloyko <[email protected]>---
arch/arm/dts/ast2500.dtsi | 881 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 880 insertions(+), 1 deletion(-)
It's not a bad idea to mention the Llinux version or commit your pulled this from.
Regards,
Simon
PATCH 2/17 dm: Simple Watchdog uclass
In reply to Maxim SloykoThis 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.
---
drivers/watchdog/Kconfig | 11 +++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/wdt-uclass.c | 79 +++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/wdt.h | 97 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+) create mode 100644 drivers/watchdog/wdt-uclass.c create mode 100644 include/wdt.h
drivers/watchdog/Kconfig +11 -0
@@ -0,0 +1,11 @@ +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.
drivers/watchdog/Makefile +1 -0
@@ -15,3 +15,4 @@ 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
drivers/watchdog/wdt-uclass.c new file +79 -0
79 lines not on this page · raw message
include/dm/uclass-id.h +1 -0
@@ -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,
include/wdt.h new file +97 -0
97 lines not on this page · raw message
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [U-Boot] [PATCH 02/17] dm: Simple Watchdog uclass
Hi Maxim,
Quoted 6 lines
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 <[email protected]>
Quoted 237 lines
---
drivers/watchdog/Kconfig | 11 +++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/wdt-uclass.c | 79+++++++++++++++++++++++++++++++++++
include/dm/uclass-id.h|
1 +include/wdt.h| 97
+++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+) create mode 100644drivers/watchdog/wdt-uclass.ccreate mode 100644 include/wdt.hdrivers/watchdog/Kconfig +7
-0@@ -0,0 +1,11 @@ +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 theAPI
drivers/watchdog/Kconfig +3
-0+ 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 aparticular
drivers/watchdog/Kconfig +1
-0+ device/driver.drivers/watchdog/Makefile +1
-0@@ -15,3 +15,4 @@ 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(quoted diff) +0
-0
b/drivers/watchdog/wdt-uclass.cnew file mode 100644 index 0000000000..98a8b529f9drivers/watchdog/wdt-uclass.c new file +17
-0@@ -0,0 +1,79 @@ +/* +* Copyright 2017 Google, Inc +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <wdt.h> +#include <dm/lists.h> +#include <dm/device-internal.h> + +DECLARE_GLOBAL_DATA_PTR ; + +/* +* 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.
+ */drivers/watchdog/wdt-uclass.c new file +55
-0+ +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_restart (struct udevice *dev) +{ +const struct wdt_ops *ops =device_get_ops (dev); + +if (!ops->restart) +return -ENOSYS ; + +return ops->restart (dev); +} + +int wdt_reset (struct udevice *dev,ulong flags) +{ +const struct wdt_ops *ops; + +debug ("WDT Resettting: %lu\n" , flags); + ops =device_get_ops (dev); +if (ops->reset) { +return ops->reset (dev, flags); + }else { +if (!ops->start) +return -ENOSYS ; + + ops->start (dev,1 , flags); +while (1 ) + ; + } + +return 0 ; +} + +UCLASS_DRIVER (wdt) = { + .id =UCLASS_WDT , + .name ="wdt" , +};include/dm/uclass-id.h +0
-0@@ -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 */include/dm/uclass-id.h +1
-0+UCLASS_WDT ,/* Watchdot Timer driver */ UCLASS_COUNT , UCLASS_INVALID = -1,include/wdt.h new file +62
-0@@ -0,0 +1,97 @@ +/* +* Copyright 2017 Google, Inc +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _WDT_H_ +#define _WDT_H_ + +/* +* 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 +* +* @dev: WDT Device +* @return: 0 if OK, -ve on error +*/ +int wdt_stop (struct udevice *dev); + +/* +* Restart the timer, typically restoring the counter to +* the value configured by start() +* +* @dev: WDT Device +* @return: 0 if OK, -ve on error +*/ +int wdt_restart (struct udevice *dev); + +/* +* Expire the timer, thus executing its action immediately +* +* Will either use chosen wdt, based on reset-wdt +* chosen property, or the first one available. +* +* @flags: Driver specific flags +* @return 0 if OK -ve on error. If wdt action is system reset, +* this function may never return. +*/ +int wdt_reset (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
include/wdt.h new file +21
-0+* 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); +/* +* Restart the timer, typically restoring the counter to +* the value configured by start() +* +* @dev: WDT Device +* @return: 0 if OK, -ve on error +*/ +int (*restart)(struct udevice *dev); +/* +* Expire the timer, thus executing the action immediately (optional)
include/wdt.h new file +3
-0+* +* If this function is not provided, default implementation +* will be used for wdt_reset(), which is set the counter to 1
include/wdt.h new file +1
-0+* and wait forever. This is good enough for system level
include/wdt.h line 97
Quoted 10 lines
include/wdt.h new file +10
-0+* reset, but not good enough for resetting peripherals. +* +* @dev: WDT Device +* @flags: Driver specific flags +* @return 0 if OK -ve on error. May not return. +*/ + int (*reset)(struct udevice *dev, ulong flags); +}; + +#endif /* _WDT_H_ */
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Re: [PATCH 02/17] dm: Simple Watchdog uclass
In reply to Maxim SloykoHi Maxim,
Quoted 23 lines · Maxim Sloyko
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 <[email protected]>---
drivers/watchdog/Kconfig | 11 +++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/wdt-uclass.c | 79 +++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/wdt.h | 97 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+) create mode 100644 drivers/watchdog/wdt-uclass.c create mode 100644 include/wdt.hdrivers/watchdog/Kconfig +1
-0@@ -0,0 +1,11 @@ +menu "Watchdog Timer Support"
drivers/watchdog/Kconfig line 11
Quoted 10 lines
drivers/watchdog/Kconfig +10
-0+ +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.
My main comment is that I think using 'reset' to mean 'reset the board' instead of 'reset the wdt' is confusing w.r.t the rest of U-Boot. Resetting the board could be handled by something like expire_now(), perhaps?
Also please add a fake sandbox wdt driver and a test/dm test.
Quoted 17 lines
drivers/watchdog/Makefile +1
-0@@ -15,3 +15,4 @@ 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.odrivers/watchdog/wdt-uclass.c new file +2
-0@@ -0,0 +1,79 @@ +/* +* Copyright 2017 Google, Inc
drivers/watchdog/wdt-uclass.c line 12
Quoted 10 lines
drivers/watchdog/wdt-uclass.c new file +10
-0+* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <wdt.h> +#include <dm/lists.h> +#include <dm/device-internal.h>
nit: move this up one
drivers/watchdog/wdt-uclass.c line 23
Quoted 11 lines
drivers/watchdog/wdt-uclass.c new file +11
-0+ +DECLARE_GLOBAL_DATA_PTR ; + +/* +* 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.
This comment might be more useful in the header file.
Quoted 35 lines
drivers/watchdog/wdt-uclass.c new file +35
-0+*/ + +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_restart (struct udevice *dev) +{ +const struct wdt_ops *ops =device_get_ops (dev); + +if (!ops->restart) +return -ENOSYS ; + +return ops->restart (dev); +} + +int wdt_reset (struct udevice *dev,ulong flags) +{ +const struct wdt_ops *ops;
drivers/watchdog/wdt-uclass.c line 68
Quoted 10 lines
drivers/watchdog/wdt-uclass.c new file +10
-0+ +debug ("WDT Resettting: %lu\n" , flags); + ops =device_get_ops (dev); +if (ops->reset) { +return ops->reset (dev, flags); + }else { +if (!ops->start) +return -ENOSYS ; + + ops->start (dev,1 , flags);
Check error here. Is the intent to start the watchdog and force it to reset the machine?
drivers/watchdog/wdt-uclass.c line 70
Quoted 2 lines
drivers/watchdog/wdt-uclass.c new file +2
-0+while (1 ) + ;
Can you use hang() here?
Quoted 40 lines
drivers/watchdog/wdt-uclass.c new file +9
-0+ } + +return 0 ; +} + +UCLASS_DRIVER (wdt) = { + .id =UCLASS_WDT , + .name ="wdt" , +};include/dm/uclass-id.h +1
-0@@ -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,include/wdt.h new file +13
-0@@ -0,0 +1,97 @@ +/* +* Copyright 2017 Google, Inc +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _WDT_H_ +#define _WDT_H_ + +/* +* Start the timer +* +* @dev: WDT Device
include/wdt.h line 23
Quoted 10 lines
include/wdt.h new file +10
-0+* @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 +*
What does stopping the timer mean? Does it pause so that the watchdog is now disabled? If so, how to enable it again?
include/wdt.h line 36
Quoted 13 lines
include/wdt.h new file +13
-0+* @dev: WDT Device +* @return: 0 if OK, -ve on error +*/ +int wdt_stop (struct udevice *dev); + +/* +* Restart the timer, typically restoring the counter to +* the value configured by start() +* +* @dev: WDT Device +* @return: 0 if OK, -ve on error +*/ +int wdt_restart (struct udevice *dev);
At present in U-Boot this operation is called 'reset'. It might be better to keep the same name.
include/wdt.h line 42
Quoted 6 lines
include/wdt.h new file +6
-0+ +/* +* Expire the timer, thus executing its action immediately +* +* Will either use chosen wdt, based on reset-wdt +* chosen property, or the first one available.
What does this refer to? Also, the function title is a little vague. Perhaps somewhere you should include that it may (for example) reset the board?
include/wdt.h line 46
Quoted 4 lines
include/wdt.h new file +4
-0+* +* @flags: Driver specific flags +* @return 0 if OK -ve on error. If wdt action is system reset, +* this function may never return.
This doesn't seem to match the args.
Quoted 29 lines
include/wdt.h new file +29
-0+*/ +int wdt_reset (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); +/* +* Restart the timer, typically restoring the counter to
include/wdt.h line 85
Quoted 10 lines
include/wdt.h new file +10
-0+* the value configured by start() +* +* @dev: WDT Device +* @return: 0 if OK, -ve on error +*/ +int (*restart)(struct udevice *dev); +/* +* Expire the timer, thus executing the action immediately (optional) +* +* If this function is not provided, default implementation
a default
include/wdt.h line 86
Quoted 1 line
include/wdt.h new file +1
-0+* will be used for wdt_reset(), which is set the counter to 1
s/set/sets/
include/wdt.h line 87
Quoted 1 line
include/wdt.h new file +1
-0+* and wait forever. This is good enough for system level
a system-level
include/wdt.h line 88
Quoted 1 line
include/wdt.h new file +1
-0+* reset, but not good enough for resetting peripherals.
Why not? I don't really understand this bit.
Quoted 10 lines
include/wdt.h new file +9
-1+* +* @dev: WDT Device +* @flags: Driver specific flags +* @return 0 if OK -ve on error. May not return. +*/ + int (*reset)(struct udevice *dev, ulong flags); +}; + +#endif /* _WDT_H_ */ --
Quoted 2 lines
2.12.0.367.g23dc2f6d3c-goog
Regards,
Simon
PATCH 3/17 aspeed: Watchdog Timer Driver
In reply to Maxim SloykoThis driver supports ast2500 and ast2400 SoCs.
Only ast2500 supports reset_mask and thus the option of resettting individual peripherals using WDT.
---
arch/arm/include/asm/arch-aspeed/wdt.h | 53 ++++++++++++-- arch/arm/mach-aspeed/ast_wdt.c | 40 ++++++++--- drivers/watchdog/Kconfig | 13 ++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/ast_wdt.c | 125 +++++++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 drivers/watchdog/ast_wdt.c
arch/arm/include/asm/arch-aspeed/wdt.h +49 -4
@@ -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
arch/arm/mach-aspeed/ast_wdt.c +31 -9
@@ -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); +}
drivers/watchdog/Kconfig +13 -0
@@ -9,3 +9,16 @@ config WDT start, restart, stop and reset (expire immediately). What exactly happens when the timer expires is up to a particular device/driver. + +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
drivers/watchdog/Makefile +1 -0
@@ -16,3 +16,4 @@ 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_ASPEED) += ast_wdt.o
drivers/watchdog/ast_wdt.c new file +125 -0
125 lines not on this page · raw message
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 03/17] aspeed: Watchdog Timer Driver
Hi Maxim,
Quoted 9 lines · Maxim Sloyko
This driver supports ast2500 and ast2400 SoCs.
Only ast2500 supportsreset_maskand thus the option of resettting individual peripherals using WDT.Signed-off-by Maxim Sloyko <[email protected]>---
arch/arm/include/asm/arch-aspeed/wdt.h | 53 ++++++++++++-- arch/arm/mach-aspeed/ast_wdt.c | 40 ++++++++---
I feel that all of the code in this file should move into the driver file below.
Quoted 82 lines
drivers/watchdog/Kconfig | 13 ++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/ast_wdt.c | 125 +++++++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 drivers/watchdog/ast_wdt.carch/arm/include/asm/arch-aspeed/wdt.h +49
-4@@ -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 arch/arm/mach-aspeed/ast_wdt.c +0
-0@@ -9,6 +9,27 @@#include <asm/arch/wdt.h> #include <linux/err.h>
arch/arm/mach-aspeed/ast_wdt.c line 20
Quoted 10 lines
arch/arm/mach-aspeed/ast_wdt.c +9
-0+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 ; +}
I'm not sure those two functions are worth it. Who calls them?
arch/arm/mach-aspeed/ast_wdt.c line 22
Quoted 2 lines
arch/arm/mach-aspeed/ast_wdt.c +2
-0+ +ulong ast_flags_from_reset_mode_mask (u32 reset_mode,u32 reset_mask)
function comment?
Quoted 31 lines
arch/arm/mach-aspeed/ast_wdt.c +11
-9+{ +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) {
arch/arm/mach-aspeed/ast_wdt.c int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask) · line 74
Quoted 5 lines
arch/arm/mach-aspeed/ast_wdt.c +2
-0@@ -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)
s/u8/uint/ or similar. It can only hurt code size to require the compiler to mask arguments.
arch/arm/mach-aspeed/ast_wdt.c int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask) · line 79
Quoted 5 lines
arch/arm/mach-aspeed/ast_wdt.c +5
-0+{ +if (wdt_number >CONFIG_WDT_NUM -1 ) +return ERR_PTR (-EINVAL ); + + return (struct ast_wdt *)(WDT_BASE +
Can this come from the device tree?
Quoted 103 lines
arch/arm/mach-aspeed/ast_wdt.c +2
-0+ sizeof(struct ast_wdt) * wdt_number); +}drivers/watchdog/Kconfig +13
-0@@ -9,3 +9,16 @@ config WDT start, restart, stop and reset (expire immediately). What exactly happens when the timer expires is up to a particular device/driver. + +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. + +endmenudrivers/watchdog/Makefile +1
-0@@ -16,3 +16,4 @@ 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_ASPEED) += ast_wdt.odrivers/watchdog/ast_wdt.c new file +65
-0@@ -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_restart (struct udevice *dev) +{ +struct ast_wdt_priv *priv =dev_get_priv (dev); + +writel (WDT_COUNTER_RESTART_VAL , &priv->regs->counter_restart); + +return 0 ;
drivers/watchdog/ast_wdt.c line 75
Quoted 10 lines
drivers/watchdog/ast_wdt.c new file +10
-0+} + +static int ast_wdt_reset (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;
This feels a bit like what the default uclass imp does?
drivers/watchdog/ast_wdt.c line 78
Quoted 3 lines
drivers/watchdog/ast_wdt.c new file +3
-0+ +while (readl (&priv->regs->ctrl) &WDT_CTRL_EN ) + ;
I am keen to avoid loops in drivers. Can this return -EINPROGRESS and have the loop be in the uclass? This is how sysreset works.
drivers/watchdog/ast_wdt.c line 88
Quoted 10 lines
drivers/watchdog/ast_wdt.c new file +10
-0+ +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))
This actually returns NULL on error.
Quoted 13 lines
drivers/watchdog/ast_wdt.c new file +13
-0+return PTR_ERR (priv->regs); + +return 0 ; +} + +static const struct wdt_ops ast_wdt_ops = { + .start = ast_wdt_start, + .restart = ast_wdt_restart, + .stop = ast_wdt_stop, + .reset = ast_wdt_reset, +}; + +static const struct udevice_id ast_wdt_ids[] = {
drivers/watchdog/ast_wdt.c line 111
Quoted 10 lines
drivers/watchdog/ast_wdt.c new file +10
-0+ { .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);
check error? Why would you call stop when probing?
Quoted 15 lines
drivers/watchdog/ast_wdt.c new file +14
-1+ +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 , +}; --
Quoted 2 lines
2.12.0.367.g23dc2f6d3c-goog
Regards,
Simon
PATCH 4/17 aspeed: Make SCU lock/unlock functions part of SCU API
In reply to Maxim SloykoMake 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.
---
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(-)
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +14 -0
@@ -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 */
arch/arm/mach-aspeed/ast2500/clk_ast2500.c +15 -0
@@ -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)) + ; +}
drivers/clk/aspeed/clk_ast2500.c +2 -16
@@ -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); }
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 04/17] aspeed: Make SCU lock/unlock functions part of SCU API
Quoted 11 lines · Maxim Sloyko
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 <[email protected]>---
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(-)
PATCH 5/17 aspeed: Reset Driver
In reply to Maxim SloykoAdd 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>;
}---
arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 28 +++++++ drivers/reset/Kconfig | 10 +++ drivers/reset/Makefile | 1 + drivers/reset/ast2500-reset.c | 109 +++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 drivers/reset/ast2500-reset.c
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +28 -0
@@ -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 {
drivers/reset/Kconfig +10 -0
@@ -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
drivers/reset/Makefile +1 -0
@@ -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
drivers/reset/ast2500-reset.c new file +109 -0
109 lines not on this page · raw message
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 05/17] aspeed: Reset Driver
Hi Maxim,
Quoted 11 lines · Maxim Sloyko
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 <[email protected]>
Quoted 9 lines
---
arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 28 +++++++ drivers/reset/Kconfig | 10 +++ drivers/reset/Makefile | 1 + drivers/reset/ast2500-reset.c | 109 +++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 drivers/reset/ast2500-reset.c
Nits below.
Quoted 111 lines
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +28
-0@@ -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 {drivers/reset/Kconfig +10
-0@@ -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. + endmenudrivers/reset/Makefile +1
-0@@ -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.odrivers/reset/ast2500-reset.c new file +38
-0@@ -0,0 +1,109 @@ +/* +* 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 ; +}
drivers/reset/ast2500-reset.c line 48
Quoted 10 lines
drivers/reset/ast2500-reset.c new file +10
-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; + +if (IS_ERR (priv)) +return PTR_ERR (priv);
This can never happen so you can drop this code.
drivers/reset/ast2500-reset.c line 51
Quoted 3 lines
drivers/reset/ast2500-reset.c new file +3
-0+ +/* +* To reset SDRAM, specifal flag in SYSRESET register
a special
Quoted 16 lines
drivers/reset/ast2500-reset.c new file +16
-0+* 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_reset (priv->wdt, reset_ctl->id); +clrbits_le32 (&priv->scu->sysreset_ctrl1, +SCU_SYSRESET_SDRAM_WDT ); +ast_scu_lock (priv->scu); + }else {
drivers/reset/ast2500-reset.c line 77
Quoted 10 lines
drivers/reset/ast2500-reset.c new file +10
-0+ ret =wdt_reset (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);
Should this do anything?
drivers/reset/ast2500-reset.c line 86
Quoted 9 lines
drivers/reset/ast2500-reset.c new file +9
-0+ +return 0 ; +} + +static int ast2500_reset_probe (struct udevice *dev) +{ +struct ast2500_reset_priv *priv =dev_get_priv (dev); + + priv->scu =ast_get_scu ();
OK, but perhaps at some point scu should be a SYSCON device accessed with syscon_get_first_range()?
Quoted 24 lines
drivers/reset/ast2500-reset.c new file +23
-1+ +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 ), +}; --
Quoted 2 lines
2.12.0.367.g23dc2f6d3c-goog
Regards,
Simon
Re: [PATCH 05/17] aspeed: Reset Driver
Quoted 179 lines · Simon Glass
Hi Maxim,
Quoted 11 lines · Maxim Sloyko
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 <[email protected]>Quoted 9 lines
---
arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 28 +++++++ drivers/reset/Kconfig | 10 +++ drivers/reset/Makefile | 1 + drivers/reset/ast2500-reset.c | 109 +++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 drivers/reset/ast2500-reset.cReviewed-by Simon Glass <[email protected]>Nits below.
Quoted 111 lines
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +28
-0@@ -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 {drivers/reset/Kconfig +10
-0@@ -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. + endmenudrivers/reset/Makefile +1
-0@@ -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.odrivers/reset/ast2500-reset.c new file +38
-0@@ -0,0 +1,109 @@ +/* +* 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 ; +}drivers/reset/ast2500-reset.c line 48
Quoted 10 lines
drivers/reset/ast2500-reset.c new file +10
-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; + +if (IS_ERR (priv)) +return PTR_ERR (priv);This can never happen so you can drop this code.
drivers/reset/ast2500-reset.c line 51
Quoted 3 lines
drivers/reset/ast2500-reset.c new file +3
-0+ +/* +* To reset SDRAM, specifal flag in SYSRESET register a special
Quoted 20 lines
drivers/reset/ast2500-reset.c new file +20
-0+* 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_reset (priv->wdt, reset_ctl->id); +clrbits_le32 (&priv->scu->sysreset_ctrl1, +SCU_SYSRESET_SDRAM_WDT ); +ast_scu_lock (priv->scu); + }else { + ret =wdt_reset (priv->wdt, reset_ctl->id); + } + +return ret;
Quoted 8 lines
drivers/reset/ast2500-reset.c line 77
Quoted 6 lines
drivers/reset/ast2500-reset.c new file +6
-0+} + +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);Should this do anything?
It needs to be there, because it is called unconditionally from uclass. I don't know what it supposed to do though. It does not do anything in tegra186-reset driver that I used as an example.
Quoted 13 lines
drivers/reset/ast2500-reset.c line 86
Quoted 10 lines
drivers/reset/ast2500-reset.c new file +9
-0+ +return 0 ; +} + +static int ast2500_reset_probe (struct udevice *dev) +{ +struct ast2500_reset_priv *priv =dev_get_priv (dev); + + priv->scu =ast_get_scu ();OK, but perhaps at some point scu should be a SYSCON device accessed with
syscon_get_first_range()?
Ack.
Quoted 30 lines
Quoted 25 lines
drivers/reset/ast2500-reset.c new file +23
-1+ +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 ), +}; --Quoted 2 lines
2.12.0.367.g23dc2f6d3c-goog
Regards,
Simon
Signature · 1 line
Maxim Sloyko
PATCH 6/17 aspeed: Device Tree configuration for Reset Driver
In reply to Maxim SloykoAdd Reset Driver configuration to ast2500 SoC Device Tree and bindings for various reset signals
---
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
arch/arm/dts/ast2500-evb.dts +15 -0
@@ -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"; +};
arch/arm/dts/ast2500-u-boot.dtsi +10 -0
@@ -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 {
include/dt-bindings/reset/ast2500-reset.h new file +45 -0
45 lines not on this page · raw message
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 06/17] aspeed: Device Tree configuration for Reset Driver
Quoted 11 lines · Maxim Sloyko
Add Reset Driver configuration to ast2500 SoC Device Tree and bindings for various reset signals
Signed-off-by Maxim Sloyko <[email protected]>---
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
PATCH 7/17 aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
In reply to Maxim SloykoThis 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.
---
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(-)
arch/arm/include/asm/arch-aspeed/wdt.h +0 -39
@@ -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 */
arch/arm/mach-aspeed/Kconfig +1 -7
@@ -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
arch/arm/mach-aspeed/ast2500/sdram_ast2500.c +10 -2
@@ -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; }
arch/arm/mach-aspeed/ast_wdt.c +0 -51
54 lines not on this page · raw message
configs/evb-ast2500_defconfig +2 -0
@@ -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
drivers/sysreset/sysreset_ast.c +11 -13
@@ -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_reset (wdt, reset_mode); +if (ret) { +debug ("Sysreset failed: %d" , ret); +return ret; + }return -EINPROGRESS ; }
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 07/17] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver
Hi Maxim,
Quoted 19 lines · Maxim Sloyko
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_devicecall. 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 <[email protected]>---
Quoted 7 lines
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(-)
OK, ignore my earlier comment on removing ast_wdt.c as I see you do it here.
Regards,
Simon
PATCH 8/17 aspeed: AST2500 Pinctrl Driver
In reply to Maxim SloykoThis 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.
---
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
arch/arm/include/asm/arch-aspeed/pinctrl.h new file +52 -0
@@ -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 */
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +19 -0
@@ -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 {
drivers/pinctrl/Kconfig +9 -0
@@ -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"
drivers/pinctrl/Makefile +1 -0
@@ -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/
drivers/pinctrl/aspeed/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_ASPEED_AST2500_PINCTRL) += pinctrl_ast2500.o
drivers/pinctrl/aspeed/pinctrl_ast2500.c new file +127 -0
127 lines not on this page · raw message
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 08/17] aspeed: AST2500 Pinctrl Driver
Quoted 11 lines · Maxim Sloyko
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 <[email protected]>---
Quoted 11 lines
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
PATCH 9/17 aspeed: Enable Pinctrl Driver in AST2500 EVB
In reply to Maxim SloykoEnable Pinctrl Driver in AST2500 Eval Board's defconfig
---
configs/evb-ast2500_defconfig | 1 + 1 file changed, 1 insertion(+)
configs/evb-ast2500_defconfig +1 -0
@@ -17,3 +17,4 @@ CONFIG_SYSRESET=y CONFIG_TIMER=y CONFIG_WDT=y CONFIG_DM_RESET=y +CONFIG_PINCTRL=y
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 09/17] aspeed: Enable Pinctrl Driver in AST2500 EVB
Quoted 7 lines · Maxim Sloyko
Enable Pinctrl Driver in AST2500 Eval Board's defconfig
Signed-off-by Maxim Sloyko <[email protected]>---
configs/evb-ast2500_defconfig | 1 + 1 file changed, 1 insertion(+)
PATCH 10/17 aspeed: Add P-Bus clock in ast2500 clock driver
In reply to Maxim SloykoAdd P-Bus Clock support to ast2500 clock driver.
This is the clock used by I2C devices.
---
arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 ++- drivers/clk/aspeed/clk_ast2500.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-)
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +2 -1
@@ -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
drivers/clk/aspeed/clk_ast2500.c +11 -0
@@ -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 ;
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 10/17] aspeed: Add P-Bus clock in ast2500 clock driver
Quoted 9 lines · Maxim Sloyko
Add P-Bus Clock support to ast2500 clock driver.
This is the clock used by I2C devices.Signed-off-by Maxim Sloyko <[email protected]>---
arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 ++- drivers/clk/aspeed/clk_ast2500.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-)
PATCH 11/17 aspeed: Add I2C Driver
In reply to Maxim SloykoAdd 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.
---
drivers/i2c/Kconfig | 9 ++ drivers/i2c/Makefile | 1 + drivers/i2c/ast_i2c.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++ 4 files changed, 497 insertions(+) create mode 100644 drivers/i2c/ast_i2c.c create mode 100644 drivers/i2c/ast_i2c.h
drivers/i2c/Kconfig +9 -0
@@ -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
drivers/i2c/Makefile +1 -0
@@ -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
drivers/i2c/ast_i2c.c new file +355 -0
355 lines not on this page · raw message
drivers/i2c/ast_i2c.h new file +132 -0
132 lines not on this page · raw message
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 11/17] aspeed: Add I2C Driver
Hello Maxim,
Am 16.03.2017 um 22:36 schrieb Maxim Sloyko:
Quoted 7 lines
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 <[email protected]>---
Quoted 7 lines
drivers/i2c/Kconfig | 9 ++ drivers/i2c/Makefile | 1 + drivers/i2c/ast_i2c.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++ 4 files changed, 497 insertions(+)create mode 100644
drivers/i2c/ast_i2c.c
create mode 100644drivers/i2c/ast_i2c.h
Thanks for this patch. Just nitpick:
[...]
Quoted 179 lines
drivers/i2c/ast_i2c.c new file +173
-0@@ -0,0 +1,355 @@ +/* +* 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 )
drivers/i2c/ast_i2c.c line 183
Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10
-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);
add an empty line here please.
Quoted 86 lines
drivers/i2c/ast_i2c.c new file +86
-0+/* 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 (®s->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 , ®s->csr); + ret =ast_i2c_wait_isr (dev,I2CD_INTR_BUS_RECOVER_DONE ); + }else { +/* Just try to reinit the device. */ +ast_i2c_init_bus (dev); + } +
drivers/i2c/ast_i2c.c line 279
Quoted 10 lines
drivers/i2c/ast_i2c.c new file +10
-0+return ret; +} + +static int ast_i2c_xfer (struct udevice *dev,struct i2c_msg *msg,int nmsgs) +{ +int ret; + + ret =ast_i2c_deblock (dev); +if (ret <0 ) +return ret;
here too.
Beside of this, as this patch is in a patchserie which goes not through i2c tree, you can add my:
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Re: [PATCH 11/17] aspeed: Add I2C Driver
In reply to Maxim SloykoQuoted 7 lines · 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 <[email protected]>---
Quoted 7 lines
drivers/i2c/Kconfig | 9 ++ drivers/i2c/Makefile | 1 + drivers/i2c/ast_i2c.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++ 4 files changed, 497 insertions(+) create mode 100644 drivers/i2c/ast_i2c.c create mode 100644 drivers/i2c/ast_i2c.h
Re: [PATCH 11/17] aspeed: Add I2C Driver
Quoted 7 lines · Simon Glass
Quoted 6 lines · 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 <[email protected]>---
Ah interesting, I was just rewriting that driver last week ... I'll review yours ASAP.
Quoted 10 lines
Quoted 8 lines
drivers/i2c/Kconfig | 9 ++
drivers/i2c/Makefile | 1 +
drivers/i2c/ast_i2c.c | 355
++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++4 files changed, 497 insertions(+)create mode 100644
drivers/i2c/ast_i2c.c
create mode 100644drivers/i2c/ast_i2c.hReviewed-by Simon Glass <[email protected]>
Re: [PATCH 11/17] aspeed: Add I2C Driver
Quoted 11 lines · Benjamin Herrenschmidt
Quoted 7 lines · Simon Glass
Quoted 6 lines · 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 <[email protected]>---
Ah interesting, I was just rewriting that driver last week ... I'll review yours ASAP.
Ignore me, I was talking about the Linux one.
Quoted 11 lines
Quoted 11 lines
Quoted 9 lines
drivers/i2c/Kconfig | 9 ++
drivers/i2c/Makefile | 1 +
drivers/i2c/ast_i2c.c | 355
++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/i2c/ast_i2c.h | 132 +++++++++++++++++++4 files changed, 497 insertions(+)create mode 100644
drivers/i2c/ast_i2c.c
create mode 100644drivers/i2c/ast_i2c.hReviewed-by Simon Glass <[email protected]>
PATCH 12/17 aspeed: Enable I2C in EVB defconfig
In reply to Maxim SloykoEnable I2C driver in ast2500 Eval Board defconfig. Also enable i2c command.
---
configs/evb-ast2500_defconfig | 3 +++ 1 file changed, 3 insertions(+)
configs/evb-ast2500_defconfig +3 -0
@@ -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
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 12/17] aspeed: Enable I2C in EVB defconfig
Quoted 8 lines · Maxim Sloyko
Enable I2C driver in ast2500 Eval Board defconfig. Also enable i2c command.
Signed-off-by Maxim Sloyko <[email protected]>---
configs/evb-ast2500_defconfig | 3 +++ 1 file changed, 3 insertions(+)
PATCH 13/17 aspeed: Add support for Clocks needed by MACs
In reply to Maxim SloykoAdd 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.
---
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(-)
arch/arm/dts/ast2500-u-boot.dtsi +8 -0
@@ -61,3 +61,11 @@ }; }; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>; +}; + +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +60 -2
83 lines not on this page · raw message
drivers/clk/aspeed/clk_ast2500.c +234 -31
326 lines not on this page · raw message
include/dt-bindings/clock/ast2500-scu.h +2 -0
@@ -27,3 +27,5 @@#define PCLK_UART3 503#define PCLK_UART4 504#define PCLK_UART5 505 +#define PCLK_MAC1 506 +#define PCLK_MAC2 507
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
Quoted 30 lines · Maxim Sloyko
Add support for clocks needed by MACs to ast2500 clock driver. The clocks are D2-PLL, which is used by both MACs and
PCLK_MAC1andPCLK_MAC2for 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 <[email protected]>---
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(-)arch/arm/dts/ast2500-u-boot.dtsi +0
-0@@ -61,3 +61,11 @@ };
arch/arm/dts/ast2500-u-boot.dtsi line 71
Quoted 10 lines
arch/arm/dts/ast2500-u-boot.dtsi +8
-0}; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>; +}; + +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};
Why is this here and not in the main dts file? The -u-boot.dtsi is for stuff that's not appropriate in the upstream dts file. Thanks!
Signature · 1 line
Tom
Re: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
Quoted 38 lines · Tom Rini
Quoted 15 lines · Maxim Sloyko
Add support for clocks needed by MACs to ast2500 clock driver. The clocks are D2-PLL, which is used by both MACs and
PCLK_MAC1andPCLK_MAC2for 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.
Quoted 6 lines
Signed-off-by Maxim Sloyko <[email protected]>---
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++++++++++++++++++++++---
Review
Quoted 4 lines
include/dt-bindings/clock/ast2500-scu.h | 2 + 4 files changed, 304 insertions(+), 33 deletions(-)(quoted diff) +0
-0
b/arch/arm/dts/ast2500-u-boot.dtsiQuoted 10 lines
index
faeeec1be4..f826646095100644arch/arm/dts/ast2500-u-boot.dtsi +3
-0@@ -61,3 +61,11 @@ }; }; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;
Quoted 9 lines
arch/arm/dts/ast2500-u-boot.dtsi line 71
Quoted 5 lines
arch/arm/dts/ast2500-u-boot.dtsi +5
-0+}; + +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};Why is this here and not in the main dts file? The
-u-boot.dtsiis for stuff that's not appropriate in the upstream dts file. Thanks!
There is no clock driver for this part in mainline Linux Kernel yet and I don't know how it will end up being configured. I suspect that they might not use the same bindings though.
Should I put this into board specific dts?
Quoted 4 lines
--
Tom
Signature · 1 line
*M*axim *S*loyko
Re: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
Quoted 49 lines · Maxim Sloyko
Quoted 38 lines · Tom Rini
Quoted 15 lines · Maxim Sloyko
Add support for clocks needed by MACs to ast2500 clock driver. The clocks are D2-PLL, which is used by both MACs and
PCLK_MAC1andPCLK_MAC2for 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.
Quoted 6 lines
Signed-off-by Maxim Sloyko <[email protected]>---
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++++++++++++++++++++++---
Review
Quoted 4 lines
include/dt-bindings/clock/ast2500-scu.h | 2 + 4 files changed, 304 insertions(+), 33 deletions(-)(quoted diff) +0
-0
b/arch/arm/dts/ast2500-u-boot.dtsiQuoted 10 lines
index
faeeec1be4..f826646095100644arch/arm/dts/ast2500-u-boot.dtsi +3
-0@@ -61,3 +61,11 @@ }; }; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;Quoted 8 lines
arch/arm/dts/ast2500-u-boot.dtsi line 71
Quoted 5 lines
arch/arm/dts/ast2500-u-boot.dtsi +5
-0+}; + +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};Why is this here and not in the main dts file? The
-u-boot.dtsiis for stuff that's not appropriate in the upstream dts file. Thanks!
Quoted 5 lines
There is no clock driver for this part in mainline Linux Kernel yet and I don't know how it will end up being configured. I suspect that they might not use the same bindings though.
Should I put this into board specific dts?
So this applies to a lot of parts of the series here. What we don't want to do is have places where the DTS here diverges from the Linux kernel DTS and we don't reconcile them. If the relevant Linux drivers are not in mainline, are they at least in linux-next or otherwise submitted to the relevant subtrees?
Signature · 1 line
Tom
Re: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
Quoted 58 lines · Tom Rini
Quoted 9 lines · Maxim Sloyko
Quoted 7 lines · Tom Rini
Quoted 6 lines · Maxim Sloyko
Add support for clocks needed by MACs to ast2500 clock driver. The clocks are D2-PLL, which is used by both MACs and
PCLK_MAC1andPCLK_MAC2for 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
Quoted 1 line
Quoted 1 line
Quoted 1 line
by MACs, so not clear if the rate would ever need to be different.
So,
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
for now, hardcoding it is probably safer.
The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected
through
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
hardware strapping.
So, the network driver would only need to enable these clocks, no
need
Quoted 37 lines
Quoted 24 lines
Quoted 8 lines
to configure the rate.
Signed-off-by Maxim Sloyko <[email protected]>---
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++++++++++++++++++++++---
Review
Quoted 4 lines
include/dt-bindings/clock/ast2500-scu.h | 2 + 4 files changed, 304 insertions(+), 33 deletions(-)(quoted diff) +0
-0
b/arch/arm/dts/ast2500-u-boot.dtsiQuoted 10 lines
index
faeeec1be4..f826646095100644arch/arm/dts/ast2500-u-boot.dtsi +3
-0@@ -61,3 +61,11 @@ }; }; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;Quoted 8 lines
arch/arm/dts/ast2500-u-boot.dtsi line 71
Quoted 5 lines
arch/arm/dts/ast2500-u-boot.dtsi +5
-0+}; + +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};Why is this here and not in the main dts file? The
-u-boot.dtsiis for stuff that's not appropriate in the upstream dts file. Thanks!There is no clock driver for this part in mainline Linux Kernel yet and I don't know how it will end up being configured. I suspect that they might not use the same bindings though.
Quoted 8 lines
Quoted 1 line
Should I put this into board specific dts?
So this applies to a lot of parts of the series here. What we don't want to do is have places where the DTS here diverges from the Linux kernel DTS and we don't reconcile them. If the relevant Linux drivers are not in mainline, are they at least in linux-next or otherwise submitted to the relevant subtrees?
No, as far as I know, maybe Rick (cc'ed) knows what is the plan there.
I'm not really working on the linux driver and it's outside of my control.
I can change network driver, so that it does not use this DT configuration and either hard code clock config into it, or configure it's clocks in board specific file -- would that be more acceptable?
Quoted 4 lines
--
Tom
Signature · 1 line
*M*axim *S*loyko
Re: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
Quoted 69 lines · Maxim Sloyko
Quoted 58 lines · Tom Rini
Quoted 9 lines · Maxim Sloyko
Quoted 7 lines · Tom Rini
Quoted 6 lines · Maxim Sloyko
Add support for clocks needed by MACs to ast2500 clock driver. The clocks are D2-PLL, which is used by both MACs and
PCLK_MAC1andPCLK_MAC2for 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
Quoted 1 line
Quoted 1 line
Quoted 1 line
by MACs, so not clear if the rate would ever need to be different.
So,
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
for now, hardcoding it is probably safer.
The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected
through
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
hardware strapping.
So, the network driver would only need to enable these clocks, no
need
Quoted 37 lines
Quoted 24 lines
Quoted 8 lines
to configure the rate.
Signed-off-by Maxim Sloyko <[email protected]>---
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++++++++++++++++++++++---
Review
Quoted 4 lines
include/dt-bindings/clock/ast2500-scu.h | 2 + 4 files changed, 304 insertions(+), 33 deletions(-)(quoted diff) +0
-0
b/arch/arm/dts/ast2500-u-boot.dtsiQuoted 10 lines
index
faeeec1be4..f826646095100644arch/arm/dts/ast2500-u-boot.dtsi +3
-0@@ -61,3 +61,11 @@ }; }; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;Quoted 8 lines
arch/arm/dts/ast2500-u-boot.dtsi line 71
Quoted 5 lines
arch/arm/dts/ast2500-u-boot.dtsi +5
-0+}; + +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};Why is this here and not in the main dts file? The
-u-boot.dtsiis for stuff that's not appropriate in the upstream dts file. Thanks!There is no clock driver for this part in mainline Linux Kernel yet and I don't know how it will end up being configured. I suspect that they might not use the same bindings though.
Quoted 8 lines
Quoted 1 line
Should I put this into board specific dts?
So this applies to a lot of parts of the series here. What we don't want to do is have places where the DTS here diverges from the Linux kernel DTS and we don't reconcile them. If the relevant Linux drivers are not in mainline, are they at least in linux-next or otherwise submitted to the relevant subtrees?
Quoted 7 lines
No, as far as I know, maybe Rick (cc'ed) knows what is the plan there.
I'm not really working on the linux driver and it's outside of my control.
I can change network driver, so that it does not use this DT configuration and either hard code clock config into it, or configure it's clocks in board specific file -- would that be more acceptable?
For all the cases where you don't have the DT portion itself upstream yet, go with platdata instead for now. Unless I'm mis-recalling things that is.
Signature · 1 line
Tom
Re: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
Quoted 75 lines · Tom Rini
Quoted 73 lines · Maxim Sloyko
Quoted 58 lines · Tom Rini
Quoted 9 lines · Maxim Sloyko
Quoted 7 lines · Tom Rini
Quoted 6 lines · Maxim Sloyko
Add support for clocks needed by MACs to ast2500 clock driver. The clocks are D2-PLL, which is used by both MACs and
PCLK_MAC1andPCLK_MAC2for 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
Quoted 1 line
Quoted 1 line
Quoted 1 line
by MACs, so not clear if the rate would ever need to be different.
So,
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
for now, hardcoding it is probably safer.
The rate of PCLK_MAC{1,2} is chosen based on MAC speed selected
through
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
hardware strapping.
So, the network driver would only need to enable these clocks, no
need
Quoted 37 lines
Quoted 24 lines
Quoted 8 lines
to configure the rate.
Signed-off-by Maxim Sloyko <[email protected]>---
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++++++++++++++++++++++---
Review
Quoted 4 lines
include/dt-bindings/clock/ast2500-scu.h | 2 + 4 files changed, 304 insertions(+), 33 deletions(-)(quoted diff) +0
-0
b/arch/arm/dts/ast2500-u-boot.dtsiQuoted 10 lines
index
faeeec1be4..f826646095100644arch/arm/dts/ast2500-u-boot.dtsi +3
-0@@ -61,3 +61,11 @@ }; }; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>;Quoted 8 lines
arch/arm/dts/ast2500-u-boot.dtsi line 71
Quoted 5 lines
arch/arm/dts/ast2500-u-boot.dtsi +5
-0+}; + +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};Why is this here and not in the main dts file? The
-u-boot.dtsiis for stuff that's not appropriate in the upstream dts file. Thanks!There is no clock driver for this part in mainline Linux Kernel yet and I don't know how it will end up being configured. I suspect that they might not use the same bindings though.
Quoted 8 lines
Quoted 1 line
Should I put this into board specific dts?
So this applies to a lot of parts of the series here. What we don't want to do is have places where the DTS here diverges from the Linux kernel DTS and we don't reconcile them. If the relevant Linux drivers are not in mainline, are they at least in linux-next or otherwise submitted to the relevant subtrees?
No, as far as I know, maybe Rick (cc'ed) knows what is the plan there.
I'm not really working on the linux driver and it's outside of my control.
Quoted 7 lines
Quoted 3 lines
I can change network driver, so that it does not use this DT configuration and either hard code clock config into it, or configure it's clocks in board specific file -- would that be more acceptable?
For all the cases where you don't have the DT portion itself upstream yet, go with platdata instead for now. Unless I'm mis-recalling things that is.
Sorry, I don't quite follow.
My understanding is that platdata is supposed to be used as a substitute for DT nodes, but in this case there is a node for MAC present in upstream linux device tree, it's just that one specific option that needs to be different. Is there an overwrite mechanism that is platdata based?
What I was thinking about is changing the driver so that instead of reading the clock configuration from DT it would use clock ids based on device's sequence number, i.e. mac0 would use PCLK_MAC0, mac1 would use PCLK_MAC1. Same for I2C.
Quoted 4 lines
--
Tom
Signature · 1 line
Maxim Sloyko
Re: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
In reply to Maxim Sloyko+Joel
Quoted 75 lines · Maxim Sloyko
Quoted 63 lines · Tom Rini
Quoted 61 lines · Maxim Sloyko
Quoted 44 lines · Tom Rini
Quoted 20 lines · Maxim Sloyko
Add support for clocks needed by MACs to ast2500 clock driver. The clocks are D2-PLL, which is used by both MACs and
PCLK_MAC1andPCLK_MAC2for 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.Quoted 6 lines
Signed-off-by Maxim Sloyko <[email protected]>---
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++++++++++++++++++++++---
Review
Quoted 4 lines
include/dt-bindings/clock/ast2500-scu.h | 2 + 4 files changed, 304 insertions(+), 33 deletions(-)(quoted diff) +0
-0
b/arch/arm/dts/ast2500-u-boot.dtsiQuoted 11 lines
index
faeeec1be4..f826646095100644arch/arm/dts/ast2500-u-boot.dtsi +4
-0@@ -61,3 +61,11 @@ }; }; }; + +&mac0 { + clocks = <&scu PCLK_MAC1>, <&scu PLL_D2PLL>; +};Quoted 8 lines
arch/arm/dts/ast2500-u-boot.dtsi line 71
Quoted 4 lines
arch/arm/dts/ast2500-u-boot.dtsi +4
-0+ +&mac1 { + clocks = <&scu PCLK_MAC2>, <&scu PLL_D2PLL>; +};Why is this here and not in the main dts file? The
-u-boot.dtsiis for
stuff that's not appropriate in the upstream dts file. Thanks!There is no clock driver for this part in mainline Linux Kernel yet and I
don't know how it will end up being configured. I suspect that they might
not use the same bindings though.Quoted 7 lines
Quoted 1 line
Should I put this into board specific dts?
So this applies to a lot of parts of the series here. What we don't want to do is have places where the DTS here diverges from the Linux kernel DTS and we don't reconcile them. If the relevant Linux drivers are not in mainline, are they at least in linux-next or otherwise submitted to the relevant subtrees?
Quoted 4 lines
No, as far as I know, maybe Rick (cc'ed) knows what is the plan there.
I'm not really working on the linux driver and it's outside of my control.
Looks like the Aspeed SDK version of U-Boot was configuring D2PLL as part of platform_g5.S
(https://github.com/openbmc/u-boot/blob/v2016.07-aspeed-openbmc/arch/arm/mach-aspeed/platform_g5.S).
OpenBMC kernel doesn't seem to have any clock drivers for these PLLs. I assume that since they were enabled by U-Boot, the ftgmac100 driver doesn't need to do anything for it to work. It should be straightforward to follow the pattern of the other clock drivers in
https://github.com/openbmc/linux/blob/dev-4.7/arch/arm/boot/dts/aspeed-g5.dtsi
and create a new driver for D2PLL.
Quoted 14 lines
I can change network driver, so that it does not use this DT configuration and either hard code clock config into it, or configure it's clocks in board specific file -- would that be more acceptable?
Quoted 4 lines
--
Tom--
Maxim Sloyko
Joel Stanley
maintainerRe: [U-Boot] [PATCH 13/17] aspeed: Add support for Clocks needed by MACs
Quoted 16 lines · Rick Altherr
+Joel
Quoted 8 lines · Maxim Sloyko
Quoted 5 lines · Tom Rini
So this applies to a lot of parts of the series here. What we don't want to do is have places where the DTS here diverges from the Linux kernel DTS and we don't reconcile them. If the relevant Linux drivers are not in mainline, are they at least in linux-next or otherwise submitted to the relevant subtrees?
Quoted 4 lines
No, as far as I know, maybe Rick (cc'ed) knows what is the plan there.
I'm not really working on the linux driver and it's outside of my control.
Quoted 9 lines
Looks like the Aspeed SDK version of U-Boot was configuring D2PLL as part of
platform_g5.S
(https://github.com/openbmc/u-boot/blob/v2016.07-aspeed-openbmc/arch/arm/mach-aspeed/platform_g5.S).
OpenBMC kernel doesn't seem to have any clock drivers for these PLLs. I assume that since they were enabled by U-Boot, the ftgmac100 driver doesn't need to do anything for it to work. It should be straightforward to follow the pattern of the other clock drivers in
https://github.com/openbmc/linux/blob/dev-4.7/arch/arm/boot/dts/aspeed-g5.dtsi
and create a new driver for D2PLL.
We don't have clock drivers upstream. I submitted them about a year ago, they got naked, and I haven't got around to resubmititng them.
I have reworked them in our upcoming 4.10 tree. The device tree currently looks like this. Note that I haven't sent this version of the patches out for review, so it may change again.
syscon: syscon at 1e6e2000 {
compatible = "aspeed,g5-scu", "syscon", "simple-mfd";
reg = <0x1e6e2000 0x1a8>;
#address-cells = <1>;
#size-cells = <0>;
clk_clkin: clk_clkin at 70 {
#clock-cells = <0>;
compatible = "aspeed,g5-clkin-clock";
reg = <0x70>;
};
clk_hpll: clk_hpll at 24 {
#clock-cells = <0>;
compatible = "aspeed,g5-hpll-clock";
reg = <0x24>;
clocks = <&clk_clkin>;
};
clk_ahb: clk_ahb at 70 {
#clock-cells = <0>;
compatible = "aspeed,g5-ahb-clock";
reg = <0x70>;
clocks = <&clk_hpll>;
};
clk_apb: clk_apb at 08 {
#clock-cells = <0>;
compatible = "aspeed,g5-apb-clock";
reg = <0x08>;
clocks = <&clk_hpll>;
};We don't (yet) have anything in there for the D2PLL as Linux hasn't needed to touch them.
I recently requested detailed clock documentation from Aspeed. I will use this to add bindings for all of the clocks in the Aspeed SoC.
Cheers,
Joel
PATCH 14/17 aspeed: Refactor SCU to use consistent mask & shift
In reply to Maxim SloykoRefactor SCU header to use consistent Mask & Shift values. Now, consistently, to read value from SCU register, mask needs to be applied before shift.
---
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(-)
arch/arm/include/asm/arch-aspeed/scu_ast2500.h +6 -6
@@ -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)
arch/arm/mach-aspeed/ast2500/sdram_ast2500.c +2 -3
@@ -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; }
drivers/clk/aspeed/clk_ast2500.c +19 -20
@@ -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 );
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 14/17] aspeed: Refactor SCU to use consistent mask & shift
Quoted 11 lines · Maxim Sloyko
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 <[email protected]>---
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(-)
PATCH 15/17 aspeed: Cleanup ast2500-u-boot.dtsi Device Tree
In reply to Maxim SloykoRemove unnecessary apb and ahb nodes and just override necessary nodes/values.
---
arch/arm/dts/ast2500-u-boot.dtsi | 41 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-)
arch/arm/dts/ast2500-u-boot.dtsi +21 -20
@@ -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 {
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
PATCH 16/17 aspeed: Add AST2500/AST2400 compatible NIC Driver
In reply to Maxim SloykoThe device that Aspeed uses is basically Faraday FTGMAC100, but with some differences here and there. Since I don't have access to a properly implemented FTGMAC100 though, I can't really test it and so I don't feel comfortable claiming compatibility, even though I reused a lot of FTGMAC100 driver code.
---
drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/ast_nic.c | 584 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ast_nic.h | 198 +++++++++++++++++ 4 files changed, 791 insertions(+) create mode 100644 drivers/net/ast_nic.c create mode 100644 drivers/net/ast_nic.h
drivers/net/Kconfig +8 -0
@@ -208,4 +208,12 @@ config GMAC_ROCKCHIP This driver provides Rockchip SoCs network support based on the Synopsys Designware driver. +config AST_NIC + bool "Support Aspeed ast2500/ast2400 NIC" + depends on DM_ETH + help + This driver provides support for ast2500/ast2400 network devices. + It uses Driver Model and so can support multiple devices on the same SoC. + The device itself is basically a variation of Faraday FTGMAC100. + endif # NETDEVICES
drivers/net/Makefile +1 -0
@@ -78,3 +78,4 @@ obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o obj-$(CONFIG_VSC9953) += vsc9953.o obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o +obj-$(CONFIG_AST_NIC) += ast_nic.o
drivers/net/ast_nic.c new file +584 -0
584 lines not on this page · raw message
drivers/net/ast_nic.h new file +198 -0
198 lines not on this page · raw message
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [U-Boot] [PATCH 16/17] aspeed: Add AST2500/AST2400 compatible NIC Driver
Quoted 5 lines · Maxim Sloyko
The device that Aspeed uses is basically Faraday FTGMAC100, but with some differences here and there. Since I don't have access to a properly implemented FTGMAC100 though, I can't really test it and so I don't feel comfortable claiming compatibility, even though I reused a lot of FTGMAC100 driver code.
I think it would be better to attempt to integrate this driver with the FTGMAC driver and ask others on the list who have that HW to test your changes to ensure no regressions. I prefer we have fewer drivers to maintain.
I'll review what you've got here, and presumably the comments apply to either your changes or the FTGMAC driver.
Quoted 72 lines
Signed-off-by Maxim Sloyko <[email protected]>---
drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/ast_nic.c | 584 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ast_nic.h | 198 +++++++++++++++++ 4 files changed, 791 insertions(+) create mode 100644 drivers/net/ast_nic.c create mode 100644 drivers/net/ast_nic.hdrivers/net/Kconfig +8
-0@@ -208,4 +208,12 @@ config GMAC_ROCKCHIP This driver provides Rockchip SoCs network support based on the Synopsys Designware driver. +config AST_NIC + bool "Support Aspeed ast2500/ast2400 NIC" + depends on DM_ETH + help + This driver provides support for ast2500/ast2400 network devices. + It uses Driver Model and so can support multiple devices on the same SoC. + The device itself is basically a variation of Faraday FTGMAC100. + endif # NETDEVICESdrivers/net/Makefile +1
-0@@ -78,3 +78,4 @@ obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o obj-$(CONFIG_VSC9953) += vsc9953.o obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o +obj-$(CONFIG_AST_NIC) += ast_nic.odrivers/net/ast_nic.c new file +29
-0@@ -0,0 +1,584 @@ +/* +* (C) Copyright 2009 Faraday Technology +* Po-Yu Chuang <[email protected]> +* +* (C) Copyright 2010 Andes Technology +* Macpaul Lin <[email protected]> +* +* Copyright 2017 Google Inc +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +/* +* This device is basically Faraday FTGMAC100, with some differences, +* which do not seem to be very big, but are in very random places, like +* some registers removed and completely different ones put in their place. +*/ + +#include <common.h> +#include <dm.h> +#include <clk.h> +#if defined(CONFIG_MII ) || defined(CONFIG_CMD_MII ) +#include <miiphy.h> +#endif +#include <net.h> +#include <asm/io.h> +#include <linux/mii.h> +#include "ast_nic.h" +
drivers/net/ast_nic.c line 39
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+#define ETH_ZLEN 60 +#define RBSR_DEFAULT_VALUE 0x640 + +#define PKTBUFSTX 4 + +#define MAX_PHY_ADDR 32 + +struct ast_nic_xdes { +u32 des[4 ]; +}__aligned(16) ;
Can you use a constant for this, like ARCH_DMA_MINALIGN?
drivers/net/ast_nic.c line 42
Quoted 3 lines
drivers/net/ast_nic.c new file +3
-0+ +struct ast_nic_xdes ast_txdes[PKTBUFSTX ]; +struct ast_nic_xdes ast_rxdes[PKTBUFSRX ];
Any reason these are not static? Also, why globals instead of allocated?
Quoted 20 lines
drivers/net/ast_nic.c new file +20
-0+ +struct ast_nic_priv { +struct ast_nic_xdes *txdes; +struct ast_nic_xdes *rxdes; +struct ast_nic_regs *regs; +int tx_index; +int rx_index; +int phy_addr; +}; + +static int ast_nic_ofdata_to_platdata (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct eth_pdata *platdata =dev_get_platdata (dev); + + priv->regs =dev_get_addr_ptr (dev); + priv->txdes = ast_txdes; + priv->rxdes = ast_rxdes; + platdata->iobase = (phys_addr_t )priv->regs; +
drivers/net/ast_nic.c line 72
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+return 0 ; +} + +static void ast_nic_reset (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); + +setbits_le32 (&priv->regs->maccr,MAC_MACCR_SW_RST ); +while (readl (&priv->regs->maccr) &MAC_MACCR_SW_RST ) + ;
Use <wait_bit.h> and wait_for_bit()
Quoted 14 lines
drivers/net/ast_nic.c new file +14
-0+/* +* Only needed for ast2400, for ast2500 this is the no-op, +* because the register is marked read-only. +*/ +setbits_le32 (&priv->regs->fear0,MAC_FEAR_NEW_MD_IFACE ); +} + +static int ast_nic_phy_read (struct udevice *dev,int phy_addr, +int regnum,u16 *value) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +int phycr; +int i; +
drivers/net/ast_nic.c line 96
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+ phycr =MAC_PHYCR_FIRE |MAC_PHYCR_ST_22 |MAC_PHYCR_READ | + (phy_addr <<MAC_PHYCR_PHYAD_SHIFT ) | + (regnum <<MAC_PHYCR_REGAD_SHIFT ); + +writel (phycr, &priv->regs->phycr); + +for (i =0 ; i <10 ; i++) { + phycr =readl (&priv->regs->phycr); + +if ((phycr &MAC_PHYCR_FIRE ) ==0 ) {
Use wait_for_bit()
drivers/net/ast_nic.c line 109
Quoted 13 lines
drivers/net/ast_nic.c new file +13
-0+int data; + + data =readl (&priv->regs->phydata); + *value = (data &MAC_PHYDATA_MIIRDATA_MASK ) >> +MAC_PHYDATA_MIIRDATA_SHIFT ; + +return 0 ; + } + +mdelay (10 ); + } + +debug ("mdio read timed out\n" );
If you're going to print, better to include the phy addr that failed to respond.
Quoted 12 lines
drivers/net/ast_nic.c new file +12
-0+return -ETIMEDOUT ; +} + +static int ast_nic_phy_write (struct udevice *dev,int phy_addr, +int regnum,u16 value) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +int phycr; +int i; + + phycr = (value <<MAC_PHYDATA_MIIWDATA_SHIFT ) | + MAC_PHYCR_FIRE | MAC_PHYCR_ST_22 |
drivers/net/ast_nic.c line 131
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+MAC_PHYCR_WRITE | + (phy_addr <<MAC_PHYCR_PHYAD_SHIFT ) | + (regnum <<MAC_PHYCR_REGAD_SHIFT ); + +writel (phycr, &priv->regs->phycr); + +for (i =0 ; i <10 ; i++) { + phycr =readl (&priv->regs->phycr); + +if ((phycr &MAC_PHYCR_FIRE ) ==0 ) {
Use wait_for_bit()
drivers/net/ast_nic.c line 133
Quoted 2 lines
drivers/net/ast_nic.c new file +2
-0+debug ("(phycr & MAC_PHYCR_MIIWR) == 0: phy_addr: %x\n" , + phy_addr);
Seems this would be chatty. Any good reason to see every phy write?
drivers/net/ast_nic.c line 140
Quoted 7 lines
drivers/net/ast_nic.c new file +7
-0+return 0 ; + } + +mdelay (10 ); + } + +debug ("mdio write timed out\n" );
If you're going to print, better to include the phy addr that failed to respond.
Quoted 76 lines
drivers/net/ast_nic.c new file +76
-0+ +return -ETIMEDOUT ; +} + +#if defined(CONFIG_MII ) || defined(CONFIG_CMD_MII ) +static int ast_nic_reg_read (struct mii_dev *bus,int addr,int devad,int reg) +{ +struct udevice *dev =eth_get_dev_by_name (bus->name); +u16 value; + +ast_nic_phy_read (dev, addr, reg, &value); + +return value; +} + +static int ast_nic_reg_write (struct mii_dev *bus,int addr,int devad,int reg, +u16 value) +{ +struct udevice *dev =eth_get_dev_by_name (bus->name); + +return ast_nic_phy_write (dev, addr, reg, value); +} +#endif + +static int ast_nic_probe (struct udevice *dev) +{ +struct clk mac_clk; +struct clk d2pll_clk; +int ret; + +debug ("%s()\n" , __func__); + + ret =clk_get_by_index (dev,0 , &mac_clk); +if (ret) { +debug ("%s(): get_clk_by_index failed: %d\n" , __func__, ret); +return ret; + } + +clk_enable (&mac_clk); + + ret =clk_get_by_index (dev,1 , &d2pll_clk); +if (ret) { +debug ("%s(): get_clk_by_index failed: %d\n" , __func__, ret); +return ret; + } + +clk_enable (&d2pll_clk); + +#if defined(CONFIG_MII ) || defined(CONFIG_CMD_MII ) +struct mii_dev *mdiodev =mdio_alloc (); +if (!mdiodev) +return -ENOMEM ; +strncpy (mdiodev->name, dev->name,MDIO_NAME_LEN ); + mdiodev->read = ast_nic_reg_read; + mdiodev->write = ast_nic_reg_write; + + ret =mdio_register (mdiodev); +if (ret <0 ) +return ret; +#endif + +ast_nic_reset (dev); + +return 0 ; +} + +static int ast_nic_phy_reset (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +int i; +u16 status, adv; + + adv =ADVERTISE_CSMA |ADVERTISE_ALL ; + +ast_nic_phy_write (dev, priv->phy_addr,MII_ADVERTISE , adv); +
drivers/net/ast_nic.c line 226
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+printf ("%s: Starting autonegotiation...\n" , dev->name); + +ast_nic_phy_write (dev, priv->phy_addr, +MII_BMCR , (BMCR_ANENABLE |BMCR_ANRESTART )); + +for (i =0 ; i <1000 ; i++) { +ast_nic_phy_read (dev, priv->phy_addr,MII_BMSR , &status); + +if (status &BMSR_ANEGCOMPLETE ) +break ;
Use wait_for_bit()
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+mdelay (1 ); + } + +if (status &BMSR_ANEGCOMPLETE ) { +printf ("%s: Autonegotiation complete\n" , dev->name); + }else {
drivers/net/ast_nic.c line 242
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+printf ("%s: Autonegotiation timed out (status=0x%04x)\n" , + dev->name, status); +return -ETIMEDOUT ; + } + +return 0 ; +} + +static int ast_nic_phy_init (struct udevice *dev) +{
It seems this function should be replaced with phylib support.
drivers/net/ast_nic.c line 249
Quoted 7 lines
drivers/net/ast_nic.c new file +7
-0+struct ast_nic_priv *priv =dev_get_priv (dev); +int phy_addr; +u16 phy_id, status, adv, lpa, stat_ge; +int media, speed, duplex; +int i; + +/* Check if the PHY is up to snuff... */
I'm not sure how "up to snuff" is defined for a phy... so maybe remove this comment or reword it.
drivers/net/ast_nic.c line 254
Quoted 5 lines
drivers/net/ast_nic.c new file +5
-0+for (phy_addr =0 ; phy_addr <MAX_PHY_ADDR ; phy_addr++) { +ast_nic_phy_read (dev, phy_addr,MII_PHYSID1 , &phy_id); + +/* +* When it is unable to found PHY,
"found" -> "find the"
Quoted 14 lines
drivers/net/ast_nic.c new file +14
-0+* the interface usually return 0xffff or 0x0000 +*/ +if (phy_id !=0xffff && phy_id !=0x0 ) { +debug ("%s: found PHY at 0x%02x\n" , dev->name, phy_addr); + priv->phy_addr = phy_addr; +break ; + } + } + +if (phy_id ==0xffff || phy_id ==0x0 ) { +debug ("%s: no PHY present\n" , dev->name); +return -ENODEV ; + } +
drivers/net/ast_nic.c line 278
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+ast_nic_phy_read (dev, priv->phy_addr,MII_BMSR , &status); + +if (!(status &BMSR_LSTATUS )) { +/* Try to re-negotiate if we don't have link already. */ +ast_nic_phy_reset (dev); + +for (i =0 ; i <100000 /100 ; i++) { +ast_nic_phy_read (dev, priv->phy_addr, +MII_BMSR , &status); +if (status &BMSR_LSTATUS )
Use wait_for_bit()
Quoted 5 lines
drivers/net/ast_nic.c new file +5
-0+break ; +udelay (100 ); + } + } +
drivers/net/ast_nic.c line 293
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+if (!(status &BMSR_LSTATUS )) { +printf ("%s: link down\n" , dev->name); +return -ENOLINK ; + } + +/* 1000 Base-T Status Register */ +ast_nic_phy_read (dev, priv->phy_addr,MII_STAT1000 , &stat_ge); + + speed = (stat_ge & (LPA_1000FULL |LPA_1000HALF ) + ?1 :0 );
This variable should be named "speed_is_1000" since that's what it appears to mean.
drivers/net/ast_nic.c line 296
Quoted 3 lines
drivers/net/ast_nic.c new file +3
-0+ + duplex = ((stat_ge &LPA_1000FULL ) + ?1 :0 );
This variable should be named "full_duplex" since that's what it appears to mean.
drivers/net/ast_nic.c line 308
Quoted 12 lines
drivers/net/ast_nic.c new file +12
-0+ +if (speed) {/* Speed is 1000 */ +debug ("%s: link up, 1000bps %s-duplex\n" , + dev->name, duplex ?"full" :"half" ); +return 0 ; + } + +ast_nic_phy_read (dev, priv->phy_addr,MII_ADVERTISE , &adv); +ast_nic_phy_read (dev, priv->phy_addr,MII_LPA , &lpa); + + media =mii_nway_result (lpa & adv); + speed = (media & (ADVERTISE_100FULL |ADVERTISE_100HALF ) ?1 :0 );
Name this "speed_is_100".
Quoted 487 lines
drivers/net/ast_nic.c new file +276
-0+ duplex = (media &ADVERTISE_FULL ) ?1 :0 ; + +debug ("%s: link up, %sMbps %s-duplex\n" , + dev->name, speed ?"100" :"10" , duplex ?"full" :"half" ); + +return 0 ; +} + +static int ast_nic_update_link_speed (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +u16 stat_fe; +u16 stat_ge; +u32 maccr; + +/* 1000 Base-T Status Register */ +ast_nic_phy_read (dev, priv->phy_addr,MII_STAT1000 , &stat_ge); +ast_nic_phy_read (dev, priv->phy_addr,MII_BMSR , &stat_fe); + +if (!(stat_fe &BMSR_LSTATUS ))/* link status up? */ +return -EIO ; + +/* read MAC control register and clear related bits */ + maccr =readl (&priv->regs->maccr) & + ~(MAC_MACCR_GIGA_MODE | +MAC_MACCR_FAST_MODE | +MAC_MACCR_FULLDUP ); + +if (stat_ge &LPA_1000FULL ) { +/* set gmac for 1000BaseTX and Full Duplex */ + maccr |=MAC_MACCR_GIGA_MODE |MAC_MACCR_FULLDUP ; + } + +if (stat_ge &LPA_1000HALF ) { +/* set gmac for 1000BaseTX and Half Duplex */ + maccr |=MAC_MACCR_GIGA_MODE ; + } + +if (stat_fe &BMSR_100FULL ) { +/* set MII for 100BaseTX and Full Duplex */ + maccr |=MAC_MACCR_FAST_MODE |MAC_MACCR_FULLDUP ; + } + +if (stat_fe &BMSR_10FULL ) { +/* set MII for 10BaseT and Full Duplex */ + maccr |=MAC_MACCR_FULLDUP ; + } + +if (stat_fe &BMSR_100HALF ) { +/* set MII for 100BaseTX and Half Duplex */ + maccr |=MAC_MACCR_FAST_MODE ; + } + +if (stat_fe &BMSR_10HALF ) { +/* set MII for 10BaseT and Half Duplex */ +/* we have already clear these bits, do nothing */ + ; + } + +/* update MII config into maccr */ +writel (maccr, &priv->regs->maccr); + +return 0 ; +} + +static int ast_nic_start (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct ast_nic_xdes *txdes = priv->txdes; +struct ast_nic_xdes *rxdes = priv->rxdes; +u32 maccr; +int i; + +debug ("%s()\n" , __func__); + +ast_nic_reset (dev); + +/* disable all interrupts */ +writel (0 , &priv->regs->ier); + +/* initialize descriptors */ + priv->tx_index =0 ; + priv->rx_index =0 ; + + txdes[PKTBUFSTX -1 ].des[0 ] =cpu_to_le32 (MAC_TXDES0_EDOTR ); + rxdes[PKTBUFSRX -1 ].des[0 ] =cpu_to_le32 (MAC_RXDES0_EDORR ); + +for (i =0 ; i <PKTBUFSTX ; i++) { +/* TXBUF_BADR */ + txdes[i].des[3 ] =0 ; + txdes[i].des[1 ] =0 ; + } + +for (i =0 ; i <PKTBUFSRX ; i++) { +/* RXBUF_BADR */ + rxdes[i].des[3 ] = (u32 )net_rx_packets[i]; + + rxdes[i].des[0 ] &= ~MAC_RXDES0_RXPKT_RDY ; + } + +/* transmit ring */ +writel ((u32 )txdes, &priv->regs->txr_badr); + +/* receive ring */ +writel ((u32 )rxdes, &priv->regs->rxr_badr); + +/* poll receive descriptor automatically */ +writel ((1 <<MAC_APTC_RXPOLL_CNT_SHIFT ), &priv->regs->aptc); + +/* config receive buffer size register */ +writel (RBSR_DEFAULT_VALUE , &priv->regs->rbsr); + +/* enable transmitter, receiver */ + maccr =MAC_MACCR_TXMAC_EN | +MAC_MACCR_RXMAC_EN | +MAC_MACCR_TXDMA_EN | +MAC_MACCR_RXDMA_EN | +MAC_MACCR_FULLDUP | +MAC_MACCR_CRC_APD | +MAC_MACCR_RX_RUNT | +MAC_MACCR_RX_BROADPKT ; + +writel (maccr, &priv->regs->maccr); + +ast_nic_phy_init (dev); + +return ast_nic_update_link_speed (dev); +} + +static void ast_nic_stop (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); + +debug ("%s()\n" , __func__); + +clrbits_le32 (&priv->regs->maccr, +MAC_MACCR_TXDMA_EN |MAC_MACCR_RXDMA_EN | +MAC_MACCR_TXMAC_EN |MAC_MACCR_RXMAC_EN ); +} + +static int ast_nic_send (struct udevice *dev,void *packet,int length) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct ast_nic_xdes *curr_des = &priv->txdes[priv->tx_index]; +unsigned long start; +unsigned long now; +unsigned long diff_time; + +if (curr_des->des[0 ] &MAC_TXDES0_TXDMA_OWN ) { +debug ("%s(): no TX descriptor available\n" , __func__); +return -EIO ; + } + +debug ("%s(%x, %x)\n" , __func__, (int )packet, length); + + length = (length <ETH_ZLEN ) ?ETH_ZLEN : length; + +/* initiate a transmit sequence */ + curr_des->des[3 ] = (u32 ) packet;/* TXBUF_BADR */ + + curr_des->des[0 ] &=MAC_TXDES0_EDOTR ; + + curr_des->des[0 ] |= (MAC_TXDES0_FTS | +MAC_TXDES0_LTS | + ((length <<MAC_TXDES0_TXBUF_SIZE_SHIFT ) & +MAC_TXDES0_TXBUF_SIZE_MASK ) | +MAC_TXDES0_TXDMA_OWN ); + +/* start transmit */ +writel (1 , &priv->regs->txpd); +invalidate_dcache_range ((u32 ) curr_des, + (u32 ) curr_des +sizeof (*curr_des)); + +/* wait for transfer to succeed */ + start =get_timer (0 ); + +while (curr_des->des[0 ] &MAC_TXDES0_TXDMA_OWN ) { + now =get_timer (0 ); +if (now < start) + now +=0xffffffff ; + diff_time = now - start; +if (diff_time >=5000 ) { +debug ("%s(): timed out\n" , __func__); +return -ETIMEDOUT ; + } + } + +debug ("%s(): packet sent\n" , __func__); + + priv->tx_index = (priv->tx_index +1 ) %PKTBUFSTX ; + +return 0 ; +} + +static int ast_nic_recv (struct udevice *dev,int flags,uchar **packetp) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct ast_nic_xdes *curr_des; +unsigned short rxlen; + + curr_des = &priv->rxdes[priv->rx_index]; + +invalidate_dcache_range ((u32 ) curr_des, + (u32 ) curr_des +sizeof (*curr_des)); + +if (!(curr_des->des[0 ] &MAC_RXDES0_RXPKT_RDY )) +return -ENOMSG ; + +if (curr_des->des[0 ] & (MAC_RXDES0_RX_ERR | +MAC_RXDES0_CRC_ERR | +MAC_RXDES0_FTL | +MAC_RXDES0_RUNT |MAC_RXDES0_RX_ODD_NB )) { +return -EIO ; + } + + rxlen = + (curr_des->des[0 ] >>MAC_RXDES0_VDBC_SHIFT ) &MAC_RXDES0_VDBC_MASK ; + +debug ("%s(): RX buffer %d, %x received\n" , + __func__, priv->rx_index, rxlen); + +invalidate_dcache_range ((u32 ) curr_des->des[3 ], + (u32 ) curr_des->des[3 ] + rxlen); + +/* pass the packet up to the protocol layers. */ +net_process_received_packet ((void *)curr_des->des[3 ], rxlen); + + curr_des->des[0 ] &= ~MAC_RXDES0_RXPKT_RDY ; + + priv->rx_index = (priv->rx_index +1 ) %PKTBUFSRX ; + +return 0 ; +} + +static int ast_nic_write_hwaddr (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct eth_pdata *platdata =dev_get_platdata (dev); +u32 madr, ladr; + +debug ("%s(%pM)\n" , __func__, platdata->enetaddr); + + madr = platdata->enetaddr[0 ] <<8 | platdata->enetaddr[1 ]; + ladr = platdata->enetaddr[2 ] <<24 | platdata->enetaddr[3 ] <<16 + | platdata->enetaddr[4 ] <<8 | platdata->enetaddr[5 ]; + +writel (madr, &priv->regs->mac_madr); +writel (ladr, &priv->regs->mac_ladr); + +return 0 ; +} + +static const struct eth_ops ast_nic_ops = { + .start = ast_nic_start, + .send = ast_nic_send, + .recv = ast_nic_recv, + .stop = ast_nic_stop, + .write_hwaddr = ast_nic_write_hwaddr, +}; + +static const struct udevice_id ast_nic_ids[] = { + { .compatible ="aspeed,ast2500-nic" }, + { .compatible ="aspeed,ast2400-nic" }, + { } +}; + +U_BOOT_DRIVER (ast_nic) = { + .name ="ast_nic" , + .id =UCLASS_ETH , + .of_match = ast_nic_ids, + .probe = ast_nic_probe, + .ops = &ast_nic_ops, + .ofdata_to_platdata = ast_nic_ofdata_to_platdata, + .priv_auto_alloc_size =sizeof (struct ast_nic_priv ), + .platdata_auto_alloc_size =sizeof (struct eth_pdata ), +};drivers/net/ast_nic.h new file +198
-1@@ -0,0 +1,198 @@ +/* +* (C) Copyright 2010 Faraday Technology +* Po-Yu Chuang <[email protected]> +* +* (C) Copyright 2010 Andes Technology +* Macpaul Lin <[email protected]> +* +* Copyright 2017 Google Inc +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef __AST_NIC_H +#define __AST_NIC_H + +struct ast_nic_regs { +u32 isr;/* 0x00 */ +u32 ier;/* 0x04 */ +u32 mac_madr;/* 0x08 */ +u32 mac_ladr;/* 0x0c */ +u32 maht0;/* 0x10 */ +u32 maht1;/* 0x14 */ +u32 txpd;/* 0x18 */ +u32 rxpd;/* 0x1c */ +u32 txr_badr;/* 0x20 */ +u32 rxr_badr;/* 0x24 */ +u32 hptxpd;/* 0x28 */ +u32 hptxpd_badr;/* 0x2c */ +u32 itc;/* 0x30 */ +u32 aptc;/* 0x34 */ +u32 dblac;/* 0x38 */ +u32 dmafifos;/* 0x3c */ +u32 fear0;/* 0x40 */ +u32 fear1;/* 0x44 */ +u32 tpafcr;/* 0x48 */ +u32 rbsr;/* 0x4c */ +u32 maccr;/* 0x50 */ +u32 macsr;/* 0x54 */ +u32 tm;/* 0x58 */ +u32 physts;/* 0x5c */ +u32 phycr;/* 0x60 */ +u32 phydata;/* 0x64 */ +u32 fcr;/* 0x68 */ +u32 bpr;/* 0x6c */ +u32 wolcr;/* 0x70 */ +u32 wolsr;/* 0x74 */ +u32 wfbm1m;/* 0x78 */ +u32 wfbm1l;/* 0x7c */ +u32 wfbm2m;/* 0x80 */ +u32 wfbm2l;/* 0x84 */ +u32 wfbm3m;/* 0x88 */ +u32 wfbm3l;/* 0x8c */ +u32 nptxr_ptr;/* 0x90 */ +u32 hptxr_ptr;/* 0x94 */ +u32 rxr_ptr;/* 0x98 */ +u32 resv3;/* 0x9c */ +u32 tx;/* 0xa0 */ +u32 tx_mcol_scol;/* 0xa4 */ +u32 tx_ecol_fail;/* 0xa8 */ +u32 tx_lcol_und;/* 0xac */ +u32 rx;/* 0xb0 */ +u32 rx_bc;/* 0xb4 */ +u32 rx_mc;/* 0xb8 */ +u32 rx_pf_aep;/* 0xbc */ +u32 rx_runt;/* 0xc0 */ +u32 rx_crcer_ftl;/* 0xc4 */ +u32 rx_col_lost;/* 0xc8 */ +}; + +/* +* Interrupt status register & interrupt enable register +*/ +#define MAC_INT_RPKT_BUF (1 << 0) +#define MAC_INT_RPKT_FIFO (1 << 1) +#define MAC_INT_NO_RXBUF (1 << 2) +#define MAC_INT_RPKT_LOST (1 << 3) +#define MAC_INT_XPKT_ETH (1 << 4) +#define MAC_INT_XPKT_FIFO (1 << 5) +#define MAC_INT_NO_NPTXBUF (1 << 6) +#define MAC_INT_XPKT_LOST (1 << 7) +#define MAC_INT_AHB_ERR (1 << 8) +#define MAC_INT_PHYSTS_CHG (1 << 9) +#define MAC_INT_NO_HPTXBUF (1 << 10) +#define MAC_INT_PHY_CHG (1 << 28) +#define MAC_INT_PHY_TIMEOUT (1 << 29) +#define MAC_INT_FLAG_ACK (1 << 30) +#define MAC_INT_FLAG_REQ (1 << 31) + +/* +* MAC control register +*/ +#define MAC_MACCR_TXDMA_EN (1 << 0) +#define MAC_MACCR_RXDMA_EN (1 << 1) +#define MAC_MACCR_TXMAC_EN (1 << 2) +#define MAC_MACCR_RXMAC_EN (1 << 3) +#define MAC_MACCR_RM_VLAN (1 << 4) +#define MAC_MACCR_HPTXR_EN (1 << 5) +#define MAC_MACCR_LOOP_EN (1 << 6) +#define MAC_MACCR_ENRX_IN_HALFTX (1 << 7) +#define MAC_MACCR_FULLDUP (1 << 8) +#define MAC_MACCR_GIGA_MODE (1 << 9) +#define MAC_MACCR_CRC_APD (1 << 10) +#define MAC_MACCR_LOW_SEN (1 << 11) +#define MAC_MACCR_RX_RUNT (1 << 12) +#define MAC_MACCR_JUMBO_LF (1 << 13) +#define MAC_MACCR_RX_ALL (1 << 14) +#define MAC_MACCR_HT_MULTI_EN (1 << 15) +#define MAC_MACCR_RX_MULTIPKT (1 << 16) +#define MAC_MACCR_RX_BROADPKT (1 << 17) +#define MAC_MACCR_DISCARD_CRCERR (1 << 18) +#define MAC_MACCR_FAST_MODE (1 << 19) +#define MAC_MACCR_SW_RST (1 << 31) + +/* +* Feature Enable Register +*/ +#define MAC_FEAR_NEW_MD_IFACE (1 << 31) +#define MAC_FEAR_LOOPBACK (1 << 30) + +/* +* Automatic polling timer control register +*/ +#define MAC_APTC_RXPOLL_CNT_SHIFT 0 +#define MAC_APTC_RXPOLL_CNT_MASK 0xf +#define MAC_APTC_RXPOLL_TIME_SEL (1 << 4) +#define MAC_APTC_TXPOLL_CNT_SHIFT 8 +#define MAC_APTC_TXPOLL_CNT_MASK (0xf << MAC_APTC_TXPOLL_CNT_SHIFT) +#define MAC_APTC_TXPOLL_TIME_SEL (1 << 12) + +/* +* Receive buffer size register +*/ +#define MAC_RBSR_SIZE_MASK 0x3fff + +/* +* PHY control register +*/ +#define MAC_PHYCR_FIRE (1 << 15) +#define MAC_PHYCR_ST_22 (1 << 12) +#define MAC_PHYCR_WRITE (1 << 10) +#define MAC_PHYCR_READ (2 << 10) +#define MAC_PHYCR_PHYAD_SHIFT 5 +#define MAC_PHYCR_PHYAD_MASK (0x1f << MAC_PHYCR_PHYAD_SHIFT) +#define MAC_PHYCR_REGAD_SHIFT 0 +#define MAC_PHYCR_REGAD_MASK (0x1f << MAC_PHYCR_REGAD_SHIFT) + +/* +* PHY data register +*/ +#define MAC_PHYDATA_MIIRDATA_SHIFT 0 +#define MAC_PHYDATA_MIIRDATA_MASK (0xffff << MAC_PHYDATA_MIIRDATA_SHIFT) +#define MAC_PHYDATA_MIIWDATA_SHIFT 16 +#define MAC_PHYDATA_MIIWDATA_MASK (0xffff << MAC_PHYDATA_MIIWDATA_SHIFT) + +#define MAC_TXDES0_TXBUF_SIZE_SHIFT 0 +#define MAC_TXDES0_TXBUF_SIZE_MASK 0x3fff +#define MAC_TXDES0_CRC_ERR (1 << 19) +#define MAC_TXDES0_LTS (1 << 28) +#define MAC_TXDES0_FTS (1 << 29) +#define MAC_TXDES0_EDOTR (1 << 30) +#define MAC_TXDES0_TXDMA_OWN (1 << 31) + +#define MAC_TXDES1_INS_VLANTAG (1 << 16) +#define MAC_TXDES1_LLC (1 << 22) +#define MAC_TXDES1_TX2FIC (1 << 30) +#define MAC_TXDES1_TXIC (1 << 31) + +#define MAC_RXDES0_VDBC_SHIFT 0 +#define MAC_RXDES0_VDBC_MASK 0x3fff +#define MAC_RXDES0_MULTICAST (1 << 16) +#define MAC_RXDES0_BROADCAST (1 << 17) +#define MAC_RXDES0_RX_ERR (1 << 18) +#define MAC_RXDES0_CRC_ERR (1 << 19) +#define MAC_RXDES0_FTL (1 << 20) +#define MAC_RXDES0_RUNT (1 << 21) +#define MAC_RXDES0_RX_ODD_NB (1 << 22) +#define MAC_RXDES0_FIFO_FULL (1 << 23) +#define MAC_RXDES0_PAUSE_OPCODE (1 << 24) +#define MAC_RXDES0_PAUSE_FRAME (1 << 25) +#define MAC_RXDES0_LRS (1 << 28) +#define MAC_RXDES0_FRS (1 << 29) +#define MAC_RXDES0_EDORR (1 << 30) +#define MAC_RXDES0_RXPKT_RDY (1 << 31) + +#define MAC_RXDES1_VLANTAG_CI 0xffff +#define MAC_RXDES1_PROT_MASK (0x3 << 20) +#define MAC_RXDES1_PROT_NONIP (0x0 << 20) +#define MAC_RXDES1_PROT_IP (0x1 << 20) +#define MAC_RXDES1_PROT_TCPIP (0x2 << 20) +#define MAC_RXDES1_PROT_UDPIP (0x3 << 20) +#define MAC_RXDES1_LLC (1 << 22) +#define MAC_RXDES1_DF (1 << 23) +#define MAC_RXDES1_VLANTAG_AVAIL (1 << 24) +#define MAC_RXDES1_TCP_CHKSUM_ERR (1 << 25) +#define MAC_RXDES1_UDP_CHKSUM_ERR (1 << 26) +#define MAC_RXDES1_IP_CHKSUM_ERR (1 << 27) + +#endif /* __AST_NIC_H */ --2.12.0.367.g23dc2f6d3c-goog
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
Re: [U-Boot] [PATCH 16/17] aspeed: Add AST2500/AST2400 compatible NIC Driver
Hi Joe,
Please see responses inline, simply ACK'ed comments will be addressed in the next version.
Quoted 11 lines · Joe Hershberger
Quoted 5 lines · Maxim Sloyko
The device that Aspeed uses is basically Faraday FTGMAC100, but with some differences here and there. Since I don't have access to a properly implemented FTGMAC100 though, I can't really test it and so I don't feel comfortable claiming compatibility, even though I reused a lot of FTGMAC100 driver code.
I think it would be better to attempt to integrate this driver with the FTGMAC driver and ask others on the list who have that HW to test your changes to ensure no regressions. I prefer we have fewer drivers to maintain.
One concern: this driver also performs its clock configuration, which I believe is very specific to the SoC, so to have that compatibility clock configuration needs to be externalized somehow. I don't know what is the best way to do it.
Quoted 80 lines
I'll review what you've got here, and presumably the comments apply to either your changes or the FTGMAC driver.
Quoted 76 lines
Signed-off-by Maxim Sloyko <[email protected]>---
drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/ast_nic.c | 584 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ast_nic.h | 198 +++++++++++++++++ 4 files changed, 791 insertions(+) create mode 100644 drivers/net/ast_nic.c create mode 100644 drivers/net/ast_nic.hdrivers/net/Kconfig +8
-0@@ -208,4 +208,12 @@ config GMAC_ROCKCHIP This driver provides Rockchip SoCs network support based on the Synopsys Designware driver. +config AST_NIC + bool "Support Aspeed ast2500/ast2400 NIC" + depends on DM_ETH + help + This driver provides support for ast2500/ast2400 network devices. + It uses Driver Model and so can support multiple devices on the same SoC. + The device itself is basically a variation of Faraday FTGMAC100. + endif # NETDEVICESdrivers/net/Makefile +1
-0@@ -78,3 +78,4 @@ obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o obj-$(CONFIG_VSC9953) += vsc9953.o obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o +obj-$(CONFIG_AST_NIC) += ast_nic.odrivers/net/ast_nic.c new file +33
-0@@ -0,0 +1,584 @@ +/* +* (C) Copyright 2009 Faraday Technology +* Po-Yu Chuang <[email protected]> +* +* (C) Copyright 2010 Andes Technology +* Macpaul Lin <[email protected]> +* +* Copyright 2017 Google Inc +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +/* +* This device is basically Faraday FTGMAC100, with some differences, +* which do not seem to be very big, but are in very random places, like +* some registers removed and completely different ones put in their place. +*/ + +#include <common.h> +#include <dm.h> +#include <clk.h> +#if defined(CONFIG_MII ) || defined(CONFIG_CMD_MII ) +#include <miiphy.h> +#endif +#include <net.h> +#include <asm/io.h> +#include <linux/mii.h> +#include "ast_nic.h" + +#define ETH_ZLEN 60 +#define RBSR_DEFAULT_VALUE 0x640 + +#define PKTBUFSTX 4
Quoted 8 lines
drivers/net/ast_nic.c line 39
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+ +#define MAX_PHY_ADDR 32 + +struct ast_nic_xdes { +u32 des[4 ]; +}__aligned(16) ;Can you use a constant for this, like
ARCH_DMA_MINALIGN?
Ack
Quoted 6 lines
drivers/net/ast_nic.c line 42
Quoted 4 lines
drivers/net/ast_nic.c new file +3
-0+ +struct ast_nic_xdes ast_txdes[PKTBUFSTX ]; +struct ast_nic_xdes ast_rxdes[PKTBUFSRX ];Any reason these are not static? Also, why globals instead of allocated?
These should be static, yes. The reason for globals is that I could not get them properly aligned, when I put them into ast_nic_priv structure.
Quoted 25 lines
Quoted 25 lines
drivers/net/ast_nic.c new file +24
-0+ +struct ast_nic_priv { +struct ast_nic_xdes *txdes; +struct ast_nic_xdes *rxdes; +struct ast_nic_regs *regs; +int tx_index; +int rx_index; +int phy_addr; +}; + +static int ast_nic_ofdata_to_platdata (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct eth_pdata *platdata =dev_get_platdata (dev); + + priv->regs =dev_get_addr_ptr (dev); + priv->txdes = ast_txdes; + priv->rxdes = ast_rxdes; + platdata->iobase = (phys_addr_t )priv->regs; + +return 0 ; +} + +static void ast_nic_reset (struct udevice *dev)
Quoted 8 lines
drivers/net/ast_nic.c line 72
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+{ +struct ast_nic_priv *priv =dev_get_priv (dev); + +setbits_le32 (&priv->regs->maccr,MAC_MACCR_SW_RST ); +while (readl (&priv->regs->maccr) &MAC_MACCR_SW_RST ) + ;Use <
wait_bit.h> andwait_for_bit()
Ack
Quoted 19 lines
Quoted 19 lines
drivers/net/ast_nic.c new file +18
-0+/* +* Only needed for ast2400, for ast2500 this is the no-op, +* because the register is marked read-only. +*/ +setbits_le32 (&priv->regs->fear0,MAC_FEAR_NEW_MD_IFACE ); +} + +static int ast_nic_phy_read (struct udevice *dev,int phy_addr, +int regnum,u16 *value) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +int phycr; +int i; + + phycr =MAC_PHYCR_FIRE |MAC_PHYCR_ST_22 |MAC_PHYCR_READ | + (phy_addr <<MAC_PHYCR_PHYAD_SHIFT ) | + (regnum <<MAC_PHYCR_REGAD_SHIFT ); +
Quoted 8 lines
drivers/net/ast_nic.c line 96
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+writel (phycr, &priv->regs->phycr); + +for (i =0 ; i <10 ; i++) { + phycr =readl (&priv->regs->phycr); + +if ((phycr &MAC_PHYCR_FIRE ) ==0 ) {Use
wait_for_bit()
Ack
Quoted 16 lines
Quoted 4 lines
drivers/net/ast_nic.c new file +3
-0+int data; + + data =readl (&priv->regs->phydata);drivers/net/ast_nic.c line 109
Quoted 10 lines
drivers/net/ast_nic.c new file +10
-0+ *value = (data &MAC_PHYDATA_MIIRDATA_MASK ) >> +MAC_PHYDATA_MIIRDATA_SHIFT ; + +return 0 ; + } + +mdelay (10 ); + } + +debug ("mdio read timed out\n" );If you're going to print, better to include the phy addr that failed to respond.
Ack
Quoted 17 lines
Quoted 17 lines
drivers/net/ast_nic.c new file +16
-0+return -ETIMEDOUT ; +} + +static int ast_nic_phy_write (struct udevice *dev,int phy_addr, +int regnum,u16 value) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +int phycr; +int i; + + phycr = (value <<MAC_PHYDATA_MIIWDATA_SHIFT ) | +MAC_PHYCR_FIRE |MAC_PHYCR_ST_22 | +MAC_PHYCR_WRITE | + (phy_addr <<MAC_PHYCR_PHYAD_SHIFT ) | + (regnum <<MAC_PHYCR_REGAD_SHIFT ); +
Quoted 8 lines
drivers/net/ast_nic.c line 96
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+writel (phycr, &priv->regs->phycr); + +for (i =0 ; i <10 ; i++) { + phycr =readl (&priv->regs->phycr); + +if ((phycr &MAC_PHYCR_FIRE ) ==0 ) {Use
wait_for_bit()
Ack
Quoted 5 lines
drivers/net/ast_nic.c line 133
Quoted 3 lines
drivers/net/ast_nic.c new file +2
-0+debug ("(phycr & MAC_PHYCR_MIIWR) == 0: phy_addr: %x\n" , + phy_addr);Seems this would be chatty. Any good reason to see every phy write?
This came directly from ftgmac100 driver. It's not very chatty though, as this is only for MII register writes.
Quoted 10 lines
drivers/net/ast_nic.c line 140
Quoted 8 lines
drivers/net/ast_nic.c new file +7
-0+return 0 ; + } + +mdelay (10 ); + } + +debug ("mdio write timed out\n" );If you're going to print, better to include the phy addr that failed to respond.
Ack
Quoted 81 lines
Quoted 81 lines
drivers/net/ast_nic.c new file +80
-0+ +return -ETIMEDOUT ; +} + +#if defined(CONFIG_MII ) || defined(CONFIG_CMD_MII ) +static int ast_nic_reg_read (struct mii_dev *bus,int addr,int devad,int reg) +{ +struct udevice *dev =eth_get_dev_by_name (bus->name); +u16 value; + +ast_nic_phy_read (dev, addr, reg, &value); + +return value; +} + +static int ast_nic_reg_write (struct mii_dev *bus,int addr,int devad,int reg, +u16 value) +{ +struct udevice *dev =eth_get_dev_by_name (bus->name); + +return ast_nic_phy_write (dev, addr, reg, value); +} +#endif + +static int ast_nic_probe (struct udevice *dev) +{ +struct clk mac_clk; +struct clk d2pll_clk; +int ret; + +debug ("%s()\n" , __func__); + + ret =clk_get_by_index (dev,0 , &mac_clk); +if (ret) { +debug ("%s(): get_clk_by_index failed: %d\n" , __func__, ret); +return ret; + } + +clk_enable (&mac_clk); + + ret =clk_get_by_index (dev,1 , &d2pll_clk); +if (ret) { +debug ("%s(): get_clk_by_index failed: %d\n" , __func__, ret); +return ret; + } + +clk_enable (&d2pll_clk); + +#if defined(CONFIG_MII ) || defined(CONFIG_CMD_MII ) +struct mii_dev *mdiodev =mdio_alloc (); +if (!mdiodev) +return -ENOMEM ; +strncpy (mdiodev->name, dev->name,MDIO_NAME_LEN ); + mdiodev->read = ast_nic_reg_read; + mdiodev->write = ast_nic_reg_write; + + ret =mdio_register (mdiodev); +if (ret <0 ) +return ret; +#endif + +ast_nic_reset (dev); + +return 0 ; +} + +static int ast_nic_phy_reset (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +int i; +u16 status, adv; + + adv =ADVERTISE_CSMA |ADVERTISE_ALL ; + +ast_nic_phy_write (dev, priv->phy_addr,MII_ADVERTISE , adv); + +printf ("%s: Starting autonegotiation...\n" , dev->name); + +ast_nic_phy_write (dev, priv->phy_addr, +MII_BMCR , (BMCR_ANENABLE |BMCR_ANRESTART ));
Quoted 8 lines
drivers/net/ast_nic.c line 226
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+ +for (i =0 ; i <1000 ; i++) { +ast_nic_phy_read (dev, priv->phy_addr,MII_BMSR , &status); + +if (status &BMSR_ANEGCOMPLETE ) +break ;Use
wait_for_bit()
Ack
Quoted 11 lines
Quoted 11 lines
drivers/net/ast_nic.c new file +10
-0+mdelay (1 ); + } + +if (status &BMSR_ANEGCOMPLETE ) { +printf ("%s: Autonegotiation complete\n" , dev->name); + }else { +printf ("%s: Autonegotiation timed out (status=0x%04x)\n" , + dev->name, status); +return -ETIMEDOUT ; + }
Quoted 8 lines
drivers/net/ast_nic.c line 242
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+ +return 0 ; +} + +static int ast_nic_phy_init (struct udevice *dev) +{It seems this function should be replaced with phylib support.
I'll look into that.
Quoted 11 lines
drivers/net/ast_nic.c line 249
Quoted 8 lines
drivers/net/ast_nic.c new file +7
-0+struct ast_nic_priv *priv =dev_get_priv (dev); +int phy_addr; +u16 phy_id, status, adv, lpa, stat_ge; +int media, speed, duplex; +int i; + +/* Check if the PHY is up to snuff... */ I'm not sure how "up to snuff" is defined for a phy... so maybe remove this comment or reword it.
Ack. This came directly from ftgmac100 driver
Quoted 8 lines
drivers/net/ast_nic.c line 254
Quoted 6 lines
drivers/net/ast_nic.c new file +5
-0+for (phy_addr =0 ; phy_addr <MAX_PHY_ADDR ; phy_addr++) { +ast_nic_phy_read (dev, phy_addr,MII_PHYSID1 , &phy_id); + +/* +* When it is unable to found PHY, "found" -> "find the"
Ack. Same here.
Quoted 19 lines
Quoted 19 lines
drivers/net/ast_nic.c new file +18
-0+* the interface usually return 0xffff or 0x0000 +*/ +if (phy_id !=0xffff && phy_id !=0x0 ) { +debug ("%s: found PHY at 0x%02x\n" , dev->name, phy_addr); + priv->phy_addr = phy_addr; +break ; + } + } + +if (phy_id ==0xffff || phy_id ==0x0 ) { +debug ("%s: no PHY present\n" , dev->name); +return -ENODEV ; + } + +ast_nic_phy_read (dev, priv->phy_addr,MII_BMSR , &status); + +if (!(status &BMSR_LSTATUS )) { +/* Try to re-negotiate if we don't have link already. */
Quoted 8 lines
drivers/net/ast_nic.c line 278
Quoted 6 lines
drivers/net/ast_nic.c new file +6
-0+ast_nic_phy_reset (dev); + +for (i =0 ; i <100000 /100 ; i++) { +ast_nic_phy_read (dev, priv->phy_addr, +MII_BMSR , &status); +if (status &BMSR_LSTATUS )Use
wait_for_bit()
Ack.
Quoted 11 lines
Quoted 11 lines
drivers/net/ast_nic.c new file +10
-0+break ; +udelay (100 ); + } + } + +if (!(status &BMSR_LSTATUS )) { +printf ("%s: link down\n" , dev->name); +return -ENOLINK ; + } +
Quoted 8 lines
drivers/net/ast_nic.c line 293
Quoted 5 lines
drivers/net/ast_nic.c new file +5
-0+/* 1000 Base-T Status Register */ +ast_nic_phy_read (dev, priv->phy_addr,MII_STAT1000 , &stat_ge); + + speed = (stat_ge & (LPA_1000FULL |LPA_1000HALF ) + ?1 :0 );This variable should be named "
speed_is_1000" since that's what it appears to mean.
Ack.
Quoted 7 lines
drivers/net/ast_nic.c line 296
Quoted 4 lines
drivers/net/ast_nic.c new file +3
-0+ + duplex = ((stat_ge &LPA_1000FULL ) + ?1 :0 );This variable should be named "
full_duplex" since that's what it appears to mean.
Ack.
Quoted 15 lines
drivers/net/ast_nic.c line 308
Quoted 13 lines
drivers/net/ast_nic.c new file +12
-0+ +if (speed) {/* Speed is 1000 */ +debug ("%s: link up, 1000bps %s-duplex\n" , + dev->name, duplex ?"full" :"half" ); +return 0 ; + } + +ast_nic_phy_read (dev, priv->phy_addr,MII_ADVERTISE , &adv); +ast_nic_phy_read (dev, priv->phy_addr,MII_LPA , &lpa); + + media =mii_nway_result (lpa & adv); + speed = (media & (ADVERTISE_100FULL |ADVERTISE_100HALF ) ?1 :0 );Name this "
speed_is_100".
Ack.
Quoted 488 lines
Quoted 488 lines
drivers/net/ast_nic.c new file +276
-0+ duplex = (media &ADVERTISE_FULL ) ?1 :0 ; + +debug ("%s: link up, %sMbps %s-duplex\n" , + dev->name, speed ?"100" :"10" , duplex ?"full" :"half" ); + +return 0 ; +} + +static int ast_nic_update_link_speed (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +u16 stat_fe; +u16 stat_ge; +u32 maccr; + +/* 1000 Base-T Status Register */ +ast_nic_phy_read (dev, priv->phy_addr,MII_STAT1000 , &stat_ge); +ast_nic_phy_read (dev, priv->phy_addr,MII_BMSR , &stat_fe); + +if (!(stat_fe &BMSR_LSTATUS ))/* link status up? */ +return -EIO ; + +/* read MAC control register and clear related bits */ + maccr =readl (&priv->regs->maccr) & + ~(MAC_MACCR_GIGA_MODE | +MAC_MACCR_FAST_MODE | +MAC_MACCR_FULLDUP ); + +if (stat_ge &LPA_1000FULL ) { +/* set gmac for 1000BaseTX and Full Duplex */ + maccr |=MAC_MACCR_GIGA_MODE |MAC_MACCR_FULLDUP ; + } + +if (stat_ge &LPA_1000HALF ) { +/* set gmac for 1000BaseTX and Half Duplex */ + maccr |=MAC_MACCR_GIGA_MODE ; + } + +if (stat_fe &BMSR_100FULL ) { +/* set MII for 100BaseTX and Full Duplex */ + maccr |=MAC_MACCR_FAST_MODE |MAC_MACCR_FULLDUP ; + } + +if (stat_fe &BMSR_10FULL ) { +/* set MII for 10BaseT and Full Duplex */ + maccr |=MAC_MACCR_FULLDUP ; + } + +if (stat_fe &BMSR_100HALF ) { +/* set MII for 100BaseTX and Half Duplex */ + maccr |=MAC_MACCR_FAST_MODE ; + } + +if (stat_fe &BMSR_10HALF ) { +/* set MII for 10BaseT and Half Duplex */ +/* we have already clear these bits, do nothing */ + ; + } + +/* update MII config into maccr */ +writel (maccr, &priv->regs->maccr); + +return 0 ; +} + +static int ast_nic_start (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct ast_nic_xdes *txdes = priv->txdes; +struct ast_nic_xdes *rxdes = priv->rxdes; +u32 maccr; +int i; + +debug ("%s()\n" , __func__); + +ast_nic_reset (dev); + +/* disable all interrupts */ +writel (0 , &priv->regs->ier); + +/* initialize descriptors */ + priv->tx_index =0 ; + priv->rx_index =0 ; + + txdes[PKTBUFSTX -1 ].des[0 ] =cpu_to_le32 (MAC_TXDES0_EDOTR ); + rxdes[PKTBUFSRX -1 ].des[0 ] =cpu_to_le32 (MAC_RXDES0_EDORR ); + +for (i =0 ; i <PKTBUFSTX ; i++) { +/* TXBUF_BADR */ + txdes[i].des[3 ] =0 ; + txdes[i].des[1 ] =0 ; + } + +for (i =0 ; i <PKTBUFSRX ; i++) { +/* RXBUF_BADR */ + rxdes[i].des[3 ] = (u32 )net_rx_packets[i]; + + rxdes[i].des[0 ] &= ~MAC_RXDES0_RXPKT_RDY ; + } + +/* transmit ring */ +writel ((u32 )txdes, &priv->regs->txr_badr); + +/* receive ring */ +writel ((u32 )rxdes, &priv->regs->rxr_badr); + +/* poll receive descriptor automatically */ +writel ((1 <<MAC_APTC_RXPOLL_CNT_SHIFT ), &priv->regs->aptc); + +/* config receive buffer size register */ +writel (RBSR_DEFAULT_VALUE , &priv->regs->rbsr); + +/* enable transmitter, receiver */ + maccr =MAC_MACCR_TXMAC_EN | +MAC_MACCR_RXMAC_EN | +MAC_MACCR_TXDMA_EN | +MAC_MACCR_RXDMA_EN | +MAC_MACCR_FULLDUP | +MAC_MACCR_CRC_APD | +MAC_MACCR_RX_RUNT | +MAC_MACCR_RX_BROADPKT ; + +writel (maccr, &priv->regs->maccr); + +ast_nic_phy_init (dev); + +return ast_nic_update_link_speed (dev); +} + +static void ast_nic_stop (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); + +debug ("%s()\n" , __func__); + +clrbits_le32 (&priv->regs->maccr, +MAC_MACCR_TXDMA_EN |MAC_MACCR_RXDMA_EN | +MAC_MACCR_TXMAC_EN |MAC_MACCR_RXMAC_EN ); +} + +static int ast_nic_send (struct udevice *dev,void *packet,int length) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct ast_nic_xdes *curr_des = &priv->txdes[priv->tx_index]; +unsigned long start; +unsigned long now; +unsigned long diff_time; + +if (curr_des->des[0 ] &MAC_TXDES0_TXDMA_OWN ) { +debug ("%s(): no TX descriptor available\n" , __func__); +return -EIO ; + } + +debug ("%s(%x, %x)\n" , __func__, (int )packet, length); + + length = (length <ETH_ZLEN ) ?ETH_ZLEN : length; + +/* initiate a transmit sequence */ + curr_des->des[3 ] = (u32 ) packet;/* TXBUF_BADR */ + + curr_des->des[0 ] &=MAC_TXDES0_EDOTR ; + + curr_des->des[0 ] |= (MAC_TXDES0_FTS | +MAC_TXDES0_LTS | + ((length <<MAC_TXDES0_TXBUF_SIZE_SHIFT ) & +MAC_TXDES0_TXBUF_SIZE_MASK ) | +MAC_TXDES0_TXDMA_OWN ); + +/* start transmit */ +writel (1 , &priv->regs->txpd); +invalidate_dcache_range ((u32 ) curr_des, + (u32 ) curr_des +sizeof (*curr_des)); + +/* wait for transfer to succeed */ + start =get_timer (0 ); + +while (curr_des->des[0 ] &MAC_TXDES0_TXDMA_OWN ) { + now =get_timer (0 ); +if (now < start) + now +=0xffffffff ; + diff_time = now - start; +if (diff_time >=5000 ) { +debug ("%s(): timed out\n" , __func__); +return -ETIMEDOUT ; + } + } + +debug ("%s(): packet sent\n" , __func__); + + priv->tx_index = (priv->tx_index +1 ) %PKTBUFSTX ; + +return 0 ; +} + +static int ast_nic_recv (struct udevice *dev,int flags,uchar **packetp) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct ast_nic_xdes *curr_des; +unsigned short rxlen; + + curr_des = &priv->rxdes[priv->rx_index]; + +invalidate_dcache_range ((u32 ) curr_des, + (u32 ) curr_des +sizeof (*curr_des)); + +if (!(curr_des->des[0 ] &MAC_RXDES0_RXPKT_RDY )) +return -ENOMSG ; + +if (curr_des->des[0 ] & (MAC_RXDES0_RX_ERR | +MAC_RXDES0_CRC_ERR | +MAC_RXDES0_FTL | +MAC_RXDES0_RUNT |MAC_RXDES0_RX_ODD_NB )) { +return -EIO ; + } + + rxlen = + (curr_des->des[0 ] >>MAC_RXDES0_VDBC_SHIFT ) &MAC_RXDES0_VDBC_MASK ; + +debug ("%s(): RX buffer %d, %x received\n" , + __func__, priv->rx_index, rxlen); + +invalidate_dcache_range ((u32 ) curr_des->des[3 ], + (u32 ) curr_des->des[3 ] + rxlen); + +/* pass the packet up to the protocol layers. */ +net_process_received_packet ((void *)curr_des->des[3 ], rxlen); + + curr_des->des[0 ] &= ~MAC_RXDES0_RXPKT_RDY ; + + priv->rx_index = (priv->rx_index +1 ) %PKTBUFSRX ; + +return 0 ; +} + +static int ast_nic_write_hwaddr (struct udevice *dev) +{ +struct ast_nic_priv *priv =dev_get_priv (dev); +struct eth_pdata *platdata =dev_get_platdata (dev); +u32 madr, ladr; + +debug ("%s(%pM)\n" , __func__, platdata->enetaddr); + + madr = platdata->enetaddr[0 ] <<8 | platdata->enetaddr[1 ]; + ladr = platdata->enetaddr[2 ] <<24 | platdata->enetaddr[3 ] <<16 + | platdata->enetaddr[4 ] <<8 | platdata->enetaddr[5 ]; + +writel (madr, &priv->regs->mac_madr); +writel (ladr, &priv->regs->mac_ladr); + +return 0 ; +} + +static const struct eth_ops ast_nic_ops = { + .start = ast_nic_start, + .send = ast_nic_send, + .recv = ast_nic_recv, + .stop = ast_nic_stop, + .write_hwaddr = ast_nic_write_hwaddr, +}; + +static const struct udevice_id ast_nic_ids[] = { + { .compatible ="aspeed,ast2500-nic" }, + { .compatible ="aspeed,ast2400-nic" }, + { } +}; + +U_BOOT_DRIVER (ast_nic) = { + .name ="ast_nic" , + .id =UCLASS_ETH , + .of_match = ast_nic_ids, + .probe = ast_nic_probe, + .ops = &ast_nic_ops, + .ofdata_to_platdata = ast_nic_ofdata_to_platdata, + .priv_auto_alloc_size =sizeof (struct ast_nic_priv ), + .platdata_auto_alloc_size =sizeof (struct eth_pdata ), +};drivers/net/ast_nic.h new file +198
-1@@ -0,0 +1,198 @@ +/* +* (C) Copyright 2010 Faraday Technology +* Po-Yu Chuang <[email protected]> +* +* (C) Copyright 2010 Andes Technology +* Macpaul Lin <[email protected]> +* +* Copyright 2017 Google Inc +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef __AST_NIC_H +#define __AST_NIC_H + +struct ast_nic_regs { +u32 isr;/* 0x00 */ +u32 ier;/* 0x04 */ +u32 mac_madr;/* 0x08 */ +u32 mac_ladr;/* 0x0c */ +u32 maht0;/* 0x10 */ +u32 maht1;/* 0x14 */ +u32 txpd;/* 0x18 */ +u32 rxpd;/* 0x1c */ +u32 txr_badr;/* 0x20 */ +u32 rxr_badr;/* 0x24 */ +u32 hptxpd;/* 0x28 */ +u32 hptxpd_badr;/* 0x2c */ +u32 itc;/* 0x30 */ +u32 aptc;/* 0x34 */ +u32 dblac;/* 0x38 */ +u32 dmafifos;/* 0x3c */ +u32 fear0;/* 0x40 */ +u32 fear1;/* 0x44 */ +u32 tpafcr;/* 0x48 */ +u32 rbsr;/* 0x4c */ +u32 maccr;/* 0x50 */ +u32 macsr;/* 0x54 */ +u32 tm;/* 0x58 */ +u32 physts;/* 0x5c */ +u32 phycr;/* 0x60 */ +u32 phydata;/* 0x64 */ +u32 fcr;/* 0x68 */ +u32 bpr;/* 0x6c */ +u32 wolcr;/* 0x70 */ +u32 wolsr;/* 0x74 */ +u32 wfbm1m;/* 0x78 */ +u32 wfbm1l;/* 0x7c */ +u32 wfbm2m;/* 0x80 */ +u32 wfbm2l;/* 0x84 */ +u32 wfbm3m;/* 0x88 */ +u32 wfbm3l;/* 0x8c */ +u32 nptxr_ptr;/* 0x90 */ +u32 hptxr_ptr;/* 0x94 */ +u32 rxr_ptr;/* 0x98 */ +u32 resv3;/* 0x9c */ +u32 tx;/* 0xa0 */ +u32 tx_mcol_scol;/* 0xa4 */ +u32 tx_ecol_fail;/* 0xa8 */ +u32 tx_lcol_und;/* 0xac */ +u32 rx;/* 0xb0 */ +u32 rx_bc;/* 0xb4 */ +u32 rx_mc;/* 0xb8 */ +u32 rx_pf_aep;/* 0xbc */ +u32 rx_runt;/* 0xc0 */ +u32 rx_crcer_ftl;/* 0xc4 */ +u32 rx_col_lost;/* 0xc8 */ +}; + +/* +* Interrupt status register & interrupt enable register +*/ +#define MAC_INT_RPKT_BUF (1 << 0) +#define MAC_INT_RPKT_FIFO (1 << 1) +#define MAC_INT_NO_RXBUF (1 << 2) +#define MAC_INT_RPKT_LOST (1 << 3) +#define MAC_INT_XPKT_ETH (1 << 4) +#define MAC_INT_XPKT_FIFO (1 << 5) +#define MAC_INT_NO_NPTXBUF (1 << 6) +#define MAC_INT_XPKT_LOST (1 << 7) +#define MAC_INT_AHB_ERR (1 << 8) +#define MAC_INT_PHYSTS_CHG (1 << 9) +#define MAC_INT_NO_HPTXBUF (1 << 10) +#define MAC_INT_PHY_CHG (1 << 28) +#define MAC_INT_PHY_TIMEOUT (1 << 29) +#define MAC_INT_FLAG_ACK (1 << 30) +#define MAC_INT_FLAG_REQ (1 << 31) + +/* +* MAC control register +*/ +#define MAC_MACCR_TXDMA_EN (1 << 0) +#define MAC_MACCR_RXDMA_EN (1 << 1) +#define MAC_MACCR_TXMAC_EN (1 << 2) +#define MAC_MACCR_RXMAC_EN (1 << 3) +#define MAC_MACCR_RM_VLAN (1 << 4) +#define MAC_MACCR_HPTXR_EN (1 << 5) +#define MAC_MACCR_LOOP_EN (1 << 6) +#define MAC_MACCR_ENRX_IN_HALFTX (1 << 7) +#define MAC_MACCR_FULLDUP (1 << 8) +#define MAC_MACCR_GIGA_MODE (1 << 9) +#define MAC_MACCR_CRC_APD (1 << 10) +#define MAC_MACCR_LOW_SEN (1 << 11) +#define MAC_MACCR_RX_RUNT (1 << 12) +#define MAC_MACCR_JUMBO_LF (1 << 13) +#define MAC_MACCR_RX_ALL (1 << 14) +#define MAC_MACCR_HT_MULTI_EN (1 << 15) +#define MAC_MACCR_RX_MULTIPKT (1 << 16) +#define MAC_MACCR_RX_BROADPKT (1 << 17) +#define MAC_MACCR_DISCARD_CRCERR (1 << 18) +#define MAC_MACCR_FAST_MODE (1 << 19) +#define MAC_MACCR_SW_RST (1 << 31) + +/* +* Feature Enable Register +*/ +#define MAC_FEAR_NEW_MD_IFACE (1 << 31) +#define MAC_FEAR_LOOPBACK (1 << 30) + +/* +* Automatic polling timer control register +*/ +#define MAC_APTC_RXPOLL_CNT_SHIFT 0 +#define MAC_APTC_RXPOLL_CNT_MASK 0xf +#define MAC_APTC_RXPOLL_TIME_SEL (1 << 4) +#define MAC_APTC_TXPOLL_CNT_SHIFT 8 +#define MAC_APTC_TXPOLL_CNT_MASK (0xf << MAC_APTC_TXPOLL_CNT_SHIFT) +#define MAC_APTC_TXPOLL_TIME_SEL (1 << 12) + +/* +* Receive buffer size register +*/ +#define MAC_RBSR_SIZE_MASK 0x3fff + +/* +* PHY control register +*/ +#define MAC_PHYCR_FIRE (1 << 15) +#define MAC_PHYCR_ST_22 (1 << 12) +#define MAC_PHYCR_WRITE (1 << 10) +#define MAC_PHYCR_READ (2 << 10) +#define MAC_PHYCR_PHYAD_SHIFT 5 +#define MAC_PHYCR_PHYAD_MASK (0x1f << MAC_PHYCR_PHYAD_SHIFT) +#define MAC_PHYCR_REGAD_SHIFT 0 +#define MAC_PHYCR_REGAD_MASK (0x1f << MAC_PHYCR_REGAD_SHIFT) + +/* +* PHY data register +*/ +#define MAC_PHYDATA_MIIRDATA_SHIFT 0 +#define MAC_PHYDATA_MIIRDATA_MASK (0xffff << MAC_PHYDATA_MIIRDATA_SHIFT) +#define MAC_PHYDATA_MIIWDATA_SHIFT 16 +#define MAC_PHYDATA_MIIWDATA_MASK (0xffff << MAC_PHYDATA_MIIWDATA_SHIFT) + +#define MAC_TXDES0_TXBUF_SIZE_SHIFT 0 +#define MAC_TXDES0_TXBUF_SIZE_MASK 0x3fff +#define MAC_TXDES0_CRC_ERR (1 << 19) +#define MAC_TXDES0_LTS (1 << 28) +#define MAC_TXDES0_FTS (1 << 29) +#define MAC_TXDES0_EDOTR (1 << 30) +#define MAC_TXDES0_TXDMA_OWN (1 << 31) + +#define MAC_TXDES1_INS_VLANTAG (1 << 16) +#define MAC_TXDES1_LLC (1 << 22) +#define MAC_TXDES1_TX2FIC (1 << 30) +#define MAC_TXDES1_TXIC (1 << 31) + +#define MAC_RXDES0_VDBC_SHIFT 0 +#define MAC_RXDES0_VDBC_MASK 0x3fff +#define MAC_RXDES0_MULTICAST (1 << 16) +#define MAC_RXDES0_BROADCAST (1 << 17) +#define MAC_RXDES0_RX_ERR (1 << 18) +#define MAC_RXDES0_CRC_ERR (1 << 19) +#define MAC_RXDES0_FTL (1 << 20) +#define MAC_RXDES0_RUNT (1 << 21) +#define MAC_RXDES0_RX_ODD_NB (1 << 22) +#define MAC_RXDES0_FIFO_FULL (1 << 23) +#define MAC_RXDES0_PAUSE_OPCODE (1 << 24) +#define MAC_RXDES0_PAUSE_FRAME (1 << 25) +#define MAC_RXDES0_LRS (1 << 28) +#define MAC_RXDES0_FRS (1 << 29) +#define MAC_RXDES0_EDORR (1 << 30) +#define MAC_RXDES0_RXPKT_RDY (1 << 31) + +#define MAC_RXDES1_VLANTAG_CI 0xffff +#define MAC_RXDES1_PROT_MASK (0x3 << 20) +#define MAC_RXDES1_PROT_NONIP (0x0 << 20) +#define MAC_RXDES1_PROT_IP (0x1 << 20) +#define MAC_RXDES1_PROT_TCPIP (0x2 << 20) +#define MAC_RXDES1_PROT_UDPIP (0x3 << 20) +#define MAC_RXDES1_LLC (1 << 22) +#define MAC_RXDES1_DF (1 << 23) +#define MAC_RXDES1_VLANTAG_AVAIL (1 << 24) +#define MAC_RXDES1_TCP_CHKSUM_ERR (1 << 25) +#define MAC_RXDES1_UDP_CHKSUM_ERR (1 << 26) +#define MAC_RXDES1_IP_CHKSUM_ERR (1 << 27) + +#endif /* __AST_NIC_H */ --2.12.0.367.g23dc2f6d3c-goog
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot
Signature · 1 line
Maxim Sloyko
Re: [U-Boot] [PATCH 16/17] aspeed: Add AST2500/AST2400 compatible NIC Driver
Hi Maxim,
Quoted 19 lines · Maxim Sloyko
Hi Joe,
Please see responses inline, simply ACK'ed comments will be addressed in the next version.
Quoted 11 lines · Joe Hershberger
Quoted 5 lines · Maxim Sloyko
The device that Aspeed uses is basically Faraday FTGMAC100, but with some differences here and there. Since I don't have access to a properly implemented FTGMAC100 though, I can't really test it and so I don't feel comfortable claiming compatibility, even though I reused a lot of FTGMAC100 driver code.
I think it would be better to attempt to integrate this driver with the FTGMAC driver and ask others on the list who have that HW to test your changes to ensure no regressions. I prefer we have fewer drivers to maintain.
Quoted 4 lines
One concern: this driver also performs its clock configuration, which I believe is very specific to the SoC, so to have that compatibility clock configuration needs to be externalized somehow. I don't know what is the best way to do it.
Generally the clock is defined by a DT property in the node, so this should work out OK.
Regards,
Simon
Re: [U-Boot] [PATCH 16/17] aspeed: Add AST2500/AST2400 compatible NIC Driver
Quoted 24 lines · Simon Glass
Hi Maxim,
Quoted 8 lines · Maxim Sloyko
Hi Joe,
Please see responses inline, simply ACK'ed comments will be addressed in the next version.
Quoted 1 line · Joe Hershberger
On Thu, Mar 16, 2017 at 4:36 PM, Maxim Sloyko <[email protected]>
Quoted 2 lines · wrote:
Quoted 2 lines
Quoted 2 lines
The device that Aspeed uses is basically Faraday FTGMAC100, but with some differences here and there. Since I don't have access to a
properly
Quoted 9 lines
Quoted 8 lines
Quoted 3 lines
implemented FTGMAC100 though, I can't really test it and so I don't feel comfortable claiming compatibility, even though I reused a lot of FTGMAC100 driver code.
I think it would be better to attempt to integrate this driver with the FTGMAC driver and ask others on the list who have that HW to test your changes to ensure no regressions. I prefer we have fewer drivers to maintain.
Quoted 8 lines
Quoted 4 lines
One concern: this driver also performs its clock configuration, which I believe is very specific to the SoC, so to have that compatibility clock configuration needs to be externalized somehow. I don't know what is the best way to do it.
Generally the clock is defined by a DT property in the node, so this should work out OK.
Well, this device on this SoC needs two different clocks configured, one for all devices and one device specific. The device speed is also hardware strapped, so it reads the unrelated register to figure out which rate to enable. Not to mention, it's still unclear how it's going to be done in Linux, so somewhere else in this review Tom actually suggested to go non-DT way with this.
Anyway, I'm going to drop this driver from this series and work this out separately, just to keep things moving, because it looks like it raises the largest number of concerns.
Quoted 4 lines
Regards,
Simon
Signature · 1 line
*M*axim *S*loyko
PATCH 17/17 aspeed: Network Driver configuration for EVB
In reply to Maxim SloykoEnable Network Driver along with network related commands -- ping, dhcp, mii -- in ast2500 Eval Board's defconfig.
Add MAC devices' configuration to Eval Board Device Tree.
---
--- arch/arm/dts/ast2500-evb.dts | 14 ++++++++++++++ configs/evb-ast2500_defconfig | 7 +++++++ 2 files changed, 21 insertions(+)
arch/arm/dts/ast2500-evb.dts +14 -0
@@ -36,3 +36,17 @@ u-boot,dm-pre-reloc; status = "okay"; }; + +&mac0 { + compatible = "aspeed,ast2500-nic"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mac1link_default>, <&pinctrl_mdio1_default>; +}; + +&mac1 { + compatible = "aspeed,ast2500-nic"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mac2link_default>, <&pinctrl_mdio2_default>; +};
configs/evb-ast2500_defconfig +7 -0
@@ -21,3 +21,10 @@ CONFIG_PINCTRL=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_ASPEED=y CONFIG_CMD_I2C=y +CONFIG_DM_ETH=y +CONFIG_AST_NIC=y +CONFIG_CMD_NET=y +CONFIG_CMD_PING=y +CONFIG_CMD_DHCP=y +CONFIG_MII=y +CONFIG_CMD_MII=y
Signature · 1 line
2.12.0.367.g23dc2f6d3c-goog
Re: [PATCH 17/17] aspeed: Network Driver configuration for EVB
Quoted 7 lines · Maxim Sloyko
Enable Network Driver along with network related commands -- ping, dhcp, mii -- in ast2500 Eval Board's defconfig.
Add MAC devices' configuration to Eval Board Device Tree.
Signed-off-by Maxim Sloyko <[email protected]>
Quoted 7 lines
---
--- arch/arm/dts/ast2500-evb.dts | 14 ++++++++++++++ configs/evb-ast2500_defconfig | 7 +++++++ 2 files changed, 21 insertions(+)
Does this come from Linux? It should mention the version or commit.