uboot-sunxi: add ac200/ac300 with internal eth phy support

This commit is contained in:
coolsnowwolf 2024-03-28 17:56:26 +08:00
parent 3f061d4220
commit 5c5b7af071
2 changed files with 398 additions and 0 deletions

View File

@ -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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ 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 <dm.h>
#include <env.h>
#include <hang.h>
+#include <i2c.h>
#include <image.h>
#include <init.h>
#include <log.h>
@@ -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 */

View File

@ -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 <command.h>
#include <miiphy.h>
#include <phy.h>
+#include <asm/io.h>
#include <errno.h>
#include <asm/global_data.h>
#include <dm/of_extra.h>
@@ -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;
}