From 5c5b7af071ac3a429a40162dce9b777bc37a7fc9 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Thu, 28 Mar 2024 17:56:26 +0800 Subject: [PATCH] uboot-sunxi: add ac200/ac300 with internal eth phy support --- .../500-add-h6-internal-eth-phy-support.patch | 189 ++++++++++++++++ ...501-fix-int-phy-eth-h3-h6-with-ac300.patch | 209 ++++++++++++++++++ 2 files changed, 398 insertions(+) create mode 100644 package/boot/uboot-sunxi/patches/500-add-h6-internal-eth-phy-support.patch create mode 100644 package/boot/uboot-sunxi/patches/501-fix-int-phy-eth-h3-h6-with-ac300.patch diff --git a/package/boot/uboot-sunxi/patches/500-add-h6-internal-eth-phy-support.patch b/package/boot/uboot-sunxi/patches/500-add-h6-internal-eth-phy-support.patch new file mode 100644 index 000000000..d16f85b52 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/500-add-h6-internal-eth-phy-support.patch @@ -0,0 +1,189 @@ +--- a/arch/arm/dts/sun50i-h616.dtsi ++++ b/arch/arm/dts/sun50i-h616.dtsi +@@ -209,6 +209,14 @@ + bias-pull-up; + }; + ++ /omit-if-no-ref/ ++ rmii_pins: rmii-pins { ++ pins = "PA0", "PA1", "PA2", "PA3", "PA4", ++ "PA5", "PA6", "PA7", "PA8", "PA9"; ++ function = "emac1"; ++ drive-strength = <40>; ++ }; ++ + /omit-if-no-ref/ + spi0_pins: spi0-pins { + pins = "PC0", "PC2", "PC4"; +@@ -504,6 +512,25 @@ + }; + }; + ++ emac1: ethernet@5030000 { ++ compatible = "allwinner,sun50i-h616-emac1"; ++ syscon = <&syscon 1>; ++ reg = <0x05030000 0x10000>; ++ interrupts = ; ++ interrupt-names = "macirq"; ++ resets = <&ccu RST_BUS_EMAC1>; ++ reset-names = "stmmaceth"; ++ clocks = <&ccu CLK_BUS_EMAC1>; ++ clock-names = "stmmaceth"; ++ status = "disabled"; ++ ++ mdio1: mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ + usbotg: usb@5100000 { + compatible = "allwinner,sun50i-h616-musb", + "allwinner,sun8i-h3-musb"; +--- a/arch/arm/include/asm/arch-sunxi/i2c.h ++++ b/arch/arm/include/asm/arch-sunxi/i2c.h +@@ -13,6 +13,9 @@ + #ifdef CONFIG_I2C1_ENABLE + #define CFG_I2C_MVTWSI_BASE1 SUNXI_TWI1_BASE + #endif ++#ifdef CONFIG_I2C3_ENABLE ++#define CONFIG_I2C_MVTWSI_BASE3 SUNXI_TWI3_BASE ++#endif + #ifdef CONFIG_R_I2C_ENABLE + #define CFG_I2C_MVTWSI_BASE2 SUNXI_R_TWI_BASE + #endif +--- a/arch/arm/mach-sunxi/Kconfig ++++ b/arch/arm/mach-sunxi/Kconfig +@@ -771,6 +771,15 @@ config I2C1_ENABLE + ---help--- + See I2C0_ENABLE help text. + ++if MACH_SUN50I_H616 ++config I2C3_ENABLE ++ bool "Enable I2C/TWI controller 3" ++ default n ++ select CMD_I2C ++ ---help--- ++ See I2C0_ENABLE help text. ++endif ++ + if SUNXI_GEN_SUN6I || SUN50I_GEN_H6 + config R_I2C_ENABLE + bool "Enable the PRCM I2C/TWI controller" +--- a/arch/arm/mach-sunxi/board.c ++++ b/arch/arm/mach-sunxi/board.c +@@ -460,6 +460,7 @@ void board_init_f(ulong dummy) + /* Needed early by sunxi_board_init if PMU is enabled */ + i2c_init_board(); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); ++ i2c_set_bus_num(0); + #endif + sunxi_board_init(); + } +--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c ++++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c +@@ -46,6 +46,10 @@ void clock_init_safe(void) + * DRAM initialization code. + */ + writel(MBUS_CLK_SRC_PLL6X2 | MBUS_CLK_M(3), &ccm->mbus_cfg); ++ ++ writel(0x10001, 0x030017ac); ++ writel(0x50, 0x0300a028); ++ writel(0x20, 0x0300a040); + } + #endif + +--- a/board/sunxi/board.c ++++ b/board/sunxi/board.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -107,6 +108,17 @@ void i2c_init_board(void) + #endif + #endif + ++#ifdef CONFIG_I2C3_ENABLE ++#if defined(CONFIG_MACH_SUN50I_H616) ++ sunxi_gpio_set_cfgpin(SUNXI_GPA(10), 2); ++ sunxi_gpio_set_cfgpin(SUNXI_GPA(11), 2); ++ sunxi_gpio_set_cfgpin(SUNXI_GPA(12), 2); ++ sunxi_gpio_set_pull(SUNXI_GPA(10), SUNXI_GPIO_PULL_UP); ++ sunxi_gpio_set_pull(SUNXI_GPA(11), SUNXI_GPIO_PULL_UP); ++ clock_twi_onoff(3, 1); ++#endif ++#endif ++ + #ifdef CONFIG_R_I2C_ENABLE + #ifdef CONFIG_MACH_SUN50I + clock_twi_onoff(5, 1); +@@ -572,6 +584,7 @@ static void sunxi_spl_store_dram_size(phys_addr_t dram_size) + void sunxi_board_init(void) + { + int power_failed = 0; ++ u8 data[2]; + + #ifdef CONFIG_LED_STATUS + if (IS_ENABLED(CONFIG_SPL_DRIVERS_MISC)) +@@ -666,6 +679,23 @@ void sunxi_board_init(void) + clock_set_pll1(get_board_sys_clk()); + else + printf("Failed to set core voltage! Can't set CPU frequency\n"); ++ ++ i2c_set_bus_num(1); ++ data[0] = 0; ++ data[1] = 0; ++ i2c_write(0x10, 0xfe, 1, data, 2); ++ i2c_write(0x10, 2, 1, data, 2); ++ data[1] = 1; ++ i2c_write(0x10, 2, 1, data, 2); ++ data[1] = 0xf; ++ i2c_write(0x10, 0x16, 1, data, 2); ++ data[1] = 3; ++ i2c_write(0x10, 0x14, 1, data, 2); ++ data[1] = 0x60; ++ i2c_write(0x10, 0xfe, 1, data, 2); ++ data[0] = 0x08; ++ data[1] = 0x14; ++ i2c_write(0x10, 0, 1, data, 2); + } + #endif /* CONFIG_SPL_BUILD */ + +--- a/drivers/net/sun8i_emac.c ++++ b/drivers/net/sun8i_emac.c +@@ -909,6 +909,11 @@ static const struct emac_variant emac_variant_h6 = { + .support_rmii = true, + }; + ++static const struct emac_variant emac_variant_h616_1 = { ++ .syscon_offset = 0x34, ++ .support_rmii = true, ++}; ++ + static const struct udevice_id sun8i_emac_eth_ids[] = { + { .compatible = "allwinner,sun8i-a83t-emac", + .data = (ulong)&emac_variant_a83t }, +@@ -920,6 +925,8 @@ static const struct udevice_id sun8i_emac_eth_ids[] = { + .data = (ulong)&emac_variant_a64 }, + { .compatible = "allwinner,sun50i-h6-emac", + .data = (ulong)&emac_variant_h6 }, ++ { .compatible = "allwinner,sun50i-h616-emac1", ++ .data = (ulong)&emac_variant_h616_1 }, + { } + }; + +--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c ++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c +@@ -710,6 +710,7 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h6_r_pinctrl_desc = + + static const struct sunxi_pinctrl_function sun50i_h616_pinctrl_functions[] = { + { "emac0", 2 }, /* PI0-PI16 */ ++ { "emac1", 2 }, /* PA0-PA9 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "mmc0", 2 }, /* PF0-PF5 */ diff --git a/package/boot/uboot-sunxi/patches/501-fix-int-phy-eth-h3-h6-with-ac300.patch b/package/boot/uboot-sunxi/patches/501-fix-int-phy-eth-h3-h6-with-ac300.patch new file mode 100644 index 000000000..43abaec1f --- /dev/null +++ b/package/boot/uboot-sunxi/patches/501-fix-int-phy-eth-h3-h6-with-ac300.patch @@ -0,0 +1,209 @@ +--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c ++++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c +@@ -55,6 +55,7 @@ + writel(MBUS_CLK_SRC_PLL6X2 | MBUS_CLK_M(3), &ccm->mbus_cfg); + + writel(0x10001, 0x030017ac); ++ writel(0x80004, 0x0300a104); + writel(0x50, 0x0300a028); + writel(0x20, 0x0300a040); + } +--- a/board/sunxi/board.c ++++ b/board/sunxi/board.c +@@ -574,10 +574,13 @@ + spl->dram_size = dram_size >> 20; + } + ++#define sunxi_ac300_key (1<<8) ++ + void sunxi_board_init(void) + { + int power_failed = 0; + u8 data[2]; ++ int val; + + #ifdef CONFIG_LED_STATUS + if (IS_ENABLED(CONFIG_SPL_DRIVERS_MISC)) +@@ -667,25 +670,31 @@ + */ + if (!power_failed) + clock_set_pll1(get_board_sys_clk()); +- else +- printf("Failed to set core voltage! Can't set CPU frequency\n"); ++ else { ++ clock_set_pll1(792000000); ++ printf("Failed to set core voltage! set CPU 792000000hz frequency\n"); ++ } + +- i2c_set_bus_num(1); +- data[0] = 0; +- data[1] = 0; +- i2c_write(0x10, 0xfe, 1, data, 2); +- i2c_write(0x10, 2, 1, data, 2); +- data[1] = 1; +- i2c_write(0x10, 2, 1, data, 2); +- data[1] = 0xf; +- i2c_write(0x10, 0x16, 1, data, 2); +- data[1] = 3; +- i2c_write(0x10, 0x14, 1, data, 2); +- data[1] = 0x60; +- i2c_write(0x10, 0xfe, 1, data, 2); +- data[0] = 0x08; +- data[1] = 0x14; +- i2c_write(0x10, 0, 1, data, 2); ++ val=readl(0x300622c); ++ if((val&sunxi_ac300_key)==0) ++ { ++ i2c_set_bus_num(1); ++ data[0] = 0; ++ data[1] = 0; ++ i2c_write(0x10, 0xfe, 1, data, 2); ++ i2c_write(0x10, 2, 1, data, 2); ++ data[1] = 1; ++ i2c_write(0x10, 2, 1, data, 2); ++ data[1] = 0xf; ++ i2c_write(0x10, 0x16, 1, data, 2); ++ data[1] = 3; ++ i2c_write(0x10, 0x14, 1, data, 2); ++ data[1] = 0x60; ++ i2c_write(0x10, 0xfe, 1, data, 2); ++ data[0] = 0x08; ++ data[1] = 0x14; ++ i2c_write(0x10, 0, 1, data, 2); ++ } + } + #endif /* CONFIG_SPL_BUILD */ + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -384,10 +385,79 @@ + return 0; + } + ++static void disable_intelligent_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0100); /* switch to page 1 */ ++ value = phy_read(phydev, MDIO_DEVAD_NONE, 0x17); /* read address 0 0x17 register */ ++ value &= ~(1 << 3); /* reg 0x17 bit 3, set 0 to disable IEEE */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x17, value); ++ phy_write(phydev, MDIO_DEVAD_NONE,0x1f, 0x0000); /* switch to page 0 */ ++} ++ ++static void disable_802_3az_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x3c); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x1 << 14 | 0x7); ++ value = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); ++ value &= ~(0x1 << 1); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x3c); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x1 << 14 | 0x7); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0xe, value); ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0200); /* switch to page 2 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x18, 0x0000); ++} ++ ++static void ephy_config_default(struct phy_device *phydev) ++{ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0100); /* Switch to Page 1 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x12, 0x4824); /* Disable APS */ ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0200); /* Switch to Page 2 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x18, 0x0000); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0600); /* Switch to Page 6 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x14, 0x708b); /* PHYAFE TX optimization */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x13, 0xF000); /* PHYAFE RX optimization */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1530); ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0800); /* Switch to Page 6 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x18, 0x00bc); /* PHYAFE TRX optimization */ ++} ++ ++static void __maybe_unused ephy_config_fixed(struct phy_device *phydev) ++{ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0100); /*switch to Page 1 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x12, 0x4824); /*Disable APS */ ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0200); /*switch to Page 2 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x18, 0x0000); /*PHYAFE TRX optimization */ ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0600); /*switch to Page 6 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x14, 0x7809); /*PHYAFE TX optimization */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x13, 0xf000); /*PHYAFE RX optimization */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x5523); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x3533); ++ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0800); /*switch to Page 8 */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x0844); /*disable auto offset */ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x18, 0x00bc); /*PHYAFE TRX optimization */ ++ ++} ++ ++#define sunxi_ac300_key (1<<8) ++ + int genphy_config(struct phy_device *phydev) + { + int val; + u32 features; ++ u16 sid_value; + + features = (SUPPORTED_TP | SUPPORTED_MII + | SUPPORTED_AUI | SUPPORTED_FIBRE | +@@ -432,6 +502,42 @@ + + genphy_config_aneg(phydev); + ++ val=readl(0x300622c); ++ sid_value=0xffff&val; ++ if(val&sunxi_ac300_key) ++ { ++ /*add quirk for h313/H616 emac1 ephy bb version bug*/ ++ /*printf("apply fix for AC300 ephy bb version bug ...\n");*/ ++ phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x1f83); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x1fb7); ++ phy_write(phydev, MDIO_DEVAD_NONE, 5, 0xa81f); ++ phy_write(phydev, MDIO_DEVAD_NONE, 6, 0); ++ udelay(500000); ++ ++ val=phy_read(phydev, MDIO_DEVAD_NONE, 6); ++ val&=~(0x0f<<12); ++ val|=(0x0f&(0x03+sid_value))<<12; ++ phy_write(phydev,MDIO_DEVAD_NONE, 6,val); ++ ++ if(sid_value&0x200) { ++ /*printf("using AC300 emac1 ephy fixed config ...\n");*/ ++ ephy_config_fixed(phydev); ++ } ++ else { ++ /*printf("using AC300 emac1 ephy default config ...\n");*/ ++ ephy_config_default(phydev); ++ } ++ ++ disable_intelligent_ieee(phydev); ++ ++ disable_802_3az_ieee(phydev); ++ phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x0000); ++ ++ val=phy_read(phydev, MDIO_DEVAD_NONE, 6); ++ val|=(0x1<<11); ++ phy_write(phydev,MDIO_DEVAD_NONE, 6,val); ++ /*add end*/ ++ } + return 0; + } +