diff --git a/MAINTAINERS b/MAINTAINERS index a9b5255c518a..b2e35c79bcca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13495,3 +13495,8 @@ F: drivers/amlogic/i2c/aml_slave.h F: drivers/amlogic/i2c/Kconfig F: drivers/amlogic/i2c/Makefile +AMLOGIC internal phy driver for ethernet +M: Yizhou Jiang #include "mesongxl.dtsi" +#include +#include / { model = "Amlogic"; amlogic-dt-id = "gxl_p212_1g"; @@ -115,6 +117,26 @@ support-sysrq = <0>; /* 0 not support , 1 support */ }; + ethmac: ethernet@0xc9410000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xc9410000 0x0 0x10000 + 0x0 0xc8834540 0x0 0x8 + 0x0 0xc8834558 0x0 0xc>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + rst_pin-gpios = <&gpio GPIOZ_14 0>; + GPIOZ4_pin-gpios = <&gpio GPIOZ_4 0>; + GPIOZ5_pin-gpios = <&gpio GPIOZ_5 0>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + cali_val = <0x20000>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH>; + clock-names = "ethclk81"; + internal_phy=<1>; + }; + dwc3: dwc3@c9000000 { compatible = "synopsys, dwc3"; reg = <0x0 0xc9000000 0x0 0x100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index b6833b1232d5..988a8f0e34b0 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -18,6 +18,8 @@ /dts-v1/; #include +#include +#include #include "mesongxl.dtsi" / { model = "Amlogic"; @@ -114,6 +116,25 @@ pinctrl-0 = <&ao_uart_pins>; support-sysrq = <0>; /* 0 not support , 1 support */ }; + ethmac: ethernet@0xc9410000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xc9410000 0x0 0x10000 + 0x0 0xc8834540 0x0 0x8 + 0x0 0xc8834558 0x0 0xc>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + rst_pin-gpios = <&gpio GPIOZ_14 0>; + GPIOZ4_pin-gpios = <&gpio GPIOZ_4 0>; + GPIOZ5_pin-gpios = <&gpio GPIOZ_5 0>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + cali_val = <0x20000>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH>; + clock-names = "ethclk81"; + internal_phy=<1>; + }; dwc3: dwc3@c9000000 { compatible = "synopsys, dwc3"; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts index 024ed9848745..eb79ede0975d 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts @@ -19,6 +19,8 @@ #include #include "mesongxm.dtsi" +#include +#include / { model = "Amlogic"; amlogic-dt-id = "gxm_q200_2g"; @@ -110,6 +112,26 @@ support-sysrq = <0>; /* 0 not support , 1 support */ }; + ethmac: ethernet@0xc9410000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xc9410000 0x0 0x10000 + 0x0 0xc8834540 0x0 0x8 + 0x0 0xc8834558 0x0 0xc>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + rst_pin-gpios = <&gpio GPIOZ_14 0>; + GPIOZ4_pin-gpios = <&gpio GPIOZ_4 0>; + GPIOZ5_pin-gpios = <&gpio GPIOZ_5 0>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + cali_val = <0x20000>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH>; + clock-names = "ethclk81"; + internal_phy=<1>; + }; + dwc3: dwc3@c9000000 { compatible = "synopsys, dwc3"; reg = <0x0 0xc9000000 0x0 0x100000>; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index 854a99c70226..c853f0846206 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -456,7 +456,7 @@ #interrupt-cells = <2>; }; - eth_pins:eth_pins { + external_eth_pins:external_eth_pins { mux { groups = "eth_mdio", "eth_mdc", diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 2078c2fb3e75..c9a71c9b9d5e 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -508,7 +508,7 @@ #interrupt-cells = <2>; }; - eth_pins:eth_pins { + external_eth_pins:external_eth_pins { mux { groups = "eth_mdio", "eth_mdc", diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 6daea92a8240..17fb25e74211 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -184,6 +184,7 @@ CONFIG_AMLOGIC_ADC_KEYPADS=y CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_EFUSE=y CONFIG_AMLOGIC_REBOOT=y +CONFIG_AMLOGIC_INTERNAL_PHY=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -210,6 +211,8 @@ CONFIG_DM_VERITY=y CONFIG_NETDEVICES=y CONFIG_TUN=y CONFIG_STMMAC_ETH=y +CONFIG_DWMAC_MESON=y +CONFIG_AMLOGIC_ETH_PRIVE=y CONFIG_ICPLUS_PHY=y CONFIG_REALTEK_PHY=y CONFIG_PPP=y diff --git a/drivers/amlogic/Kconfig b/drivers/amlogic/Kconfig index 1738e3996230..ef6a2b1b4fc9 100644 --- a/drivers/amlogic/Kconfig +++ b/drivers/amlogic/Kconfig @@ -42,5 +42,8 @@ source "drivers/amlogic/input/Kconfig" source "drivers/amlogic/efuse/Kconfig" source "drivers/amlogic/reboot/Kconfig" + +source "drivers/amlogic/ethernet/phy/Kconfig" + endmenu endif diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile index 5b9483e41e7f..4af866fe53ca 100644 --- a/drivers/amlogic/Makefile +++ b/drivers/amlogic/Makefile @@ -38,3 +38,6 @@ obj-$(CONFIG_AMLOGIC_INPUT) += input/ obj-$(CONFIG_AMLOGIC_EFUSE) += efuse/ obj-$(CONFIG_AMLOGIC_REBOOT) += reboot/ + +obj-$(CONFIG_AMLOGIC_INTERNAL_PHY) += ethernet/phy/ + diff --git a/drivers/amlogic/ethernet/phy/Kconfig b/drivers/amlogic/ethernet/phy/Kconfig new file mode 100644 index 000000000000..3915b96e46be --- /dev/null +++ b/drivers/amlogic/ethernet/phy/Kconfig @@ -0,0 +1,12 @@ +# +# PHY Layer Configuration +# + +config AMLOGIC_INTERNAL_PHY + tristate "Drivers for amlogic internal phy" + ---help--- + Currently supports the amlogic internal phy. + This module implements the amlogic internal phy, + modify the dts file to switch internal external phy. + + if in doube, ask yizhou. diff --git a/drivers/amlogic/ethernet/phy/Makefile b/drivers/amlogic/ethernet/phy/Makefile new file mode 100644 index 000000000000..0bbc970b3a61 --- /dev/null +++ b/drivers/amlogic/ethernet/phy/Makefile @@ -0,0 +1,3 @@ +# Makefile for amlogic PHY drivers + +obj-$(CONFIG_AMLOGIC_INTERNAL_PHY) += amlogic.o diff --git a/drivers/amlogic/ethernet/phy/amlogic.c b/drivers/amlogic/ethernet/phy/amlogic.c new file mode 100644 index 000000000000..b9348cebe83e --- /dev/null +++ b/drivers/amlogic/ethernet/phy/amlogic.c @@ -0,0 +1,268 @@ +/* + * drivers/amlogic/ethernet/phy/amlogic.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMI_ADDR_TSTWRITE 23 + +MODULE_DESCRIPTION("amlogic internal ethernet phy driver"); +MODULE_AUTHOR("Yizhou Jiang"); +MODULE_LICENSE("GPL"); +void set_a3_config(struct phy_device *phydev) +{ + int value = 0; + + phy_write(phydev, 0x17, 0xa900); + phy_write(phydev, 0x14, 0x4414); + phy_write(phydev, 0x14, 0x8680); + value = phy_read(phydev, 0x15); +} + +void internal_wol_init(struct phy_device *phydev) +{ + int val; + unsigned char *mac_addr; + + mac_addr = phydev->attached_dev->dev_addr; + /*chose wol register bank*/ + val = phy_read(phydev, 0x14); + val |= 0x800; + val &= ~0x1000; + phy_write(phydev, 0x14, val);/*write data to wol register bank*/ + /*write mac address*/ + phy_write(phydev, SMI_ADDR_TSTWRITE, mac_addr[0] | mac_addr[1] << 8); + phy_write(phydev, 0x14, 0x4800 | 0x00); + phy_write(phydev, SMI_ADDR_TSTWRITE, mac_addr[2] | mac_addr[3] << 8); + phy_write(phydev, 0x14, 0x4800 | 0x01); + phy_write(phydev, SMI_ADDR_TSTWRITE, mac_addr[4] | mac_addr[5] << 8); + phy_write(phydev, 0x14, 0x4800 | 0x02); + /*enable wol*/ + phy_write(phydev, SMI_ADDR_TSTWRITE, 0x9); + phy_write(phydev, 0x14, 0x4800 | 0x03); + /*enable interrupt*/ + phy_write(phydev, 0x1E, 0xe00); +} + +void internal_config(struct phy_device *phydev) +{ + int value; + /*set reg27[12] = 1*/ + value = phy_read(phydev, 0x1b); + phy_write(phydev, 0x1b, value | 0x1000); + phy_write(phydev, 0x11, 0x0080); + /*Enable Analog and DSP register Bank access by*/ + phy_write(phydev, 0x14, 0x0000); + phy_write(phydev, 0x14, 0x0400); + phy_write(phydev, 0x14, 0x0000); + phy_write(phydev, 0x14, 0x0400); + /*Write Analog register 23*/ + phy_write(phydev, 0x17, 0x8E0D); + phy_write(phydev, 0x14, 0x4417); + /*Enable fractional PLL*/ + phy_write(phydev, 0x17, 0x0005); + phy_write(phydev, 0x14, 0x5C1B); + /*Programme fraction FR_PLL_DIV1*/ + phy_write(phydev, 0x17, 0x029A); + phy_write(phydev, 0x14, 0x5C1D); + /*programme fraction FR_PLL_DiV1*/ + phy_write(phydev, 0x17, 0xAAAA); + phy_write(phydev, 0x14, 0x5C1C); + phy_write(phydev, 0x17, 0x000c); + phy_write(phydev, 0x14, 0x4418); + phy_write(phydev, 0x17, 0x1A0C); + phy_write(phydev, 0x14, 0x4417); /* A6_CONFIG */ + phy_write(phydev, 0x17, 0x6400); + phy_write(phydev, 0x14, 0x441A); /* A8_CONFIG */ + pr_info("internal phy init\n"); +} + +void reset_internal_phy(struct phy_device *phydev) +{ + int value; + /*get value of bit 15:8*/ + /*if get 1, means power down reset or warm reset*/ + if (phydev->drv->features & 0xff00) { + pr_info("power down and up\n"); + value = phy_read(phydev, MII_BMCR); + phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); + msleep(50); + value = phy_read(phydev, MII_BMCR); + phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); + msleep(50); + } + + phy_write(phydev, MII_BMCR, BMCR_RESET); + msleep(50); + internal_config(phydev); + pr_info("reset phy\n"); +} + +static int internal_phy_read_status(struct phy_device *phydev) +{ + int err; + int reg31 = 0; + int wol_reg12; + int linkup = 0; + int val; + static int reg12_error_count; + /* Update the link, but return if there was an error */ + /* Bit 15: READ*/ + /*Bit 14: Write*/ + /*Bit 12:11: BANK_SEL (0: DSP, 1: WOL, 3: BIST)*/ + /*Bit 10: Test Mode*/ + /*Bit 9:5: Read Address*/ + /*Bit 4:0: Write Address*/ + /*read wol bank reg12*/ + val = ((1 << 15) | (1 << 11) | (1 << 10) | (12 << 5)); + phy_write(phydev, 0x14, val); + wol_reg12 = phy_read(phydev, 0x15); + if (phydev->link) { + if ((wol_reg12 & 0x1000)) + reg12_error_count = 0; + if (!(wol_reg12 & 0x1000)) { + reg12_error_count++; + pr_info("wol_reg12[12]==0, error\n"); + } + if (reg12_error_count >= (phydev->drv->features & 0xff)) { + reg12_error_count = 0; + reset_internal_phy(phydev); + } + } else { + reg12_error_count = 0; + } + linkup = phydev->link; + err = genphy_update_link(phydev); + if (err) + return err; + + phydev->lp_advertising = 0; + + if (phydev->autoneg == AUTONEG_ENABLE) { + /*read internal phy reg 0x1f*/ + reg31 = phy_read(phydev, 0x1f); + /*bit 12 auto negotiation done*/ + if (reg31 | 0x1000) { + phydev->pause = 0; + phydev->asym_pause = 0; + phydev->speed = SPEED_10; + phydev->duplex = DUPLEX_HALF; + /*bit 4:2 speed indication*/ + reg31 &= 0x1c; + /*value 001: 10M/half*/ + if (reg31 == 0x4) { + phydev->speed = SPEED_10; + phydev->duplex = DUPLEX_HALF; + } + /*value 101: 10M/full*/ + if (reg31 == 0x14) { + phydev->speed = SPEED_10; + phydev->duplex = DUPLEX_FULL; + } + /*value 010: 100M/half*/ + if (reg31 == 0x8) { + phydev->speed = SPEED_100; + phydev->duplex = DUPLEX_HALF; + } + /*value 110: 100M/full*/ + if (reg31 == 0x18) { + phydev->speed = SPEED_100; + phydev->duplex = DUPLEX_FULL; + } + } + } else { + int bmcr = phy_read(phydev, MII_BMCR); + + if (bmcr < 0) + return bmcr; + + if (bmcr & BMCR_FULLDPLX) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = DUPLEX_HALF; + + if (bmcr & BMCR_SPEED1000) + phydev->speed = SPEED_1000; + else if (bmcr & BMCR_SPEED100) + phydev->speed = SPEED_100; + else + phydev->speed = SPEED_10; + + phydev->pause = 0; + phydev->asym_pause = 0; + } + /*every time link up, set a3 config*/ + if ((linkup == 0) && (phydev->link == 1)) { + if (phydev->speed == SPEED_100) + set_a3_config(phydev); + } + + return 0; +} + +static int internal_config_init(struct phy_device *phydev) +{ + /*internal_wol_init(phydev);*/ + internal_config(phydev); + return genphy_config_init(phydev); +} + +static int internal_phy_resume(struct phy_device *phydev) +{ + int rc; + + rc = genphy_resume(phydev); + phy_init_hw(phydev); + return rc; +} + +static struct phy_driver amlogic_internal_driver[] = { { + .phy_id = 0x01814400, + .name = "amlogic internal phy", + .phy_id_mask = 0x0fffffff, + .config_init = internal_config_init, + /*1 means power down reset, 0 means marm reset*/ + /*bit 0-7,value f:count_sec=15*/ + .features = 0x10f, + .config_aneg = genphy_config_aneg, + .read_status = internal_phy_read_status, + .suspend = genphy_suspend, + .resume = internal_phy_resume, +} }; + +module_phy_driver(amlogic_internal_driver); + +static struct mdio_device_id __maybe_unused amlogic_tbl[] = { + { 0x01814400, 0xfffffff0 }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, amlogic_tbl); diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 4b78168a5f3c..09e2c0a3e2b9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -60,8 +60,8 @@ config DWMAC_LPC18XX config DWMAC_MESON tristate "Amlogic Meson dwmac support" - default ARCH_MESON - depends on OF && COMMON_CLK && (ARCH_MESON || COMPILE_TEST) + default n + depends on OF && COMMON_CLK help Support for Ethernet controller on Amlogic Meson SoCs. @@ -69,6 +69,17 @@ config DWMAC_MESON the stmmac device driver. This driver is used for Meson6, Meson8, Meson8b and GXBB SoCs. +config AMLOGIC_ETH_PRIVE + tristate "Amlogic private ethernet code" + default n + depends on OF + help + Support for Ethernet controller on Amlogic Meson SoCs. + + This selects the Amlogic Meson SoC glue layer support for + the stmmac device driver. This driver is used for amlogic + private driver. + config DWMAC_ROCKCHIP tristate "Rockchip dwmac support" default ARCH_ROCKCHIP diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index 7fdd1760a74c..79bcaac2e36d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -18,7 +18,11 @@ #include #include #include - +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +#include +#include "dwmac1000.h" +#include "dwmac_dma.h" +#endif #include "stmmac_platform.h" #define ETHMAC_SPEED_100 BIT(1) @@ -47,6 +51,106 @@ static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed) writel(val, dwmac->reg); } +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +#define ETH_REG2_REVERSED BIT(28) +#define INTERNAL_PHY_ID 0x110181 +#define PHY_ENABLE BIT(31) +#define USE_PHY_IP BIT(30) +#define CLK_IN_EN BIT(29) +#define USE_PHY_MDI BIT(26) +#define LED_POLARITY BIT(23) +#define ETH_REG3_19_RESVERD (0x9 << 16) +#define CFG_PHY_ADDR (0x8 << 8) +#define CFG_MODE (0x7 << 4) +#define CFG_EN_HIGH BIT(3) +#define ETH_REG3_2_RESERVED 0x7 +static void __iomem *network_interface_setup(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct gpio_desc *gdesc; + struct gpio_desc *gdesc_z4; + struct gpio_desc *gdesc_z5; + struct pinctrl *pin_ctl; + struct resource *res; + u32 mc_val, cali_val, internal_phy; + void __iomem *addr = NULL; + void __iomem *PREG_ETH_REG0; + void __iomem *PREG_ETH_REG1; + void __iomem *PREG_ETH_REG2; + void __iomem *PREG_ETH_REG3; + void __iomem *PREG_ETH_REG4; + + /*map reg0 and reg 1 addr.*/ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + addr = devm_ioremap_resource(dev, res); + PREG_ETH_REG0 = addr; + PREG_ETH_REG1 = addr + 4; + pr_debug("REG0:REG1 = %p :%p\n", PREG_ETH_REG0, PREG_ETH_REG1); + + if (!of_property_read_u32(np, "internal_phy", &internal_phy)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + addr = devm_ioremap_resource(dev, res); + PREG_ETH_REG2 = addr; + PREG_ETH_REG3 = addr + 4; + PREG_ETH_REG4 = addr + 8; + if (internal_phy == 1) { + pr_debug("internal phy\n"); + /* Get mec mode & ting value set it in cbus2050 */ + if (of_property_read_u32(np, "mc_val_internal_phy", + &mc_val)) { + } else { + writel(mc_val, addr); + } + writel(ETH_REG2_REVERSED | INTERNAL_PHY_ID, + PREG_ETH_REG2); + writel(PHY_ENABLE | USE_PHY_IP | CLK_IN_EN | + USE_PHY_MDI | LED_POLARITY | + ETH_REG3_19_RESVERD | CFG_PHY_ADDR | + CFG_MODE | CFG_EN_HIGH | + ETH_REG3_2_RESERVED, PREG_ETH_REG3); + pin_ctl = devm_pinctrl_get_select + (&pdev->dev, "internal_eth_pins"); + } else { + /* Get mec mode & ting value set it in cbus2050 */ + if (of_property_read_u32(np, "mc_val_external_phy", + &mc_val)) + writel(mc_val, addr); + if (!of_property_read_u32(np, "cali_val", &cali_val)) + writel(cali_val, addr + 4); + writel(ETH_REG2_REVERSED | INTERNAL_PHY_ID, + PREG_ETH_REG2); + writel(CLK_IN_EN | ETH_REG3_19_RESVERD | + CFG_PHY_ADDR | CFG_MODE | CFG_EN_HIGH | + ETH_REG3_2_RESERVED, PREG_ETH_REG3); + /* pull reset pin for resetting phy */ + gdesc = gpiod_get(&pdev->dev, "rst_pin", + GPIOD_FLAGS_BIT_DIR_OUT); + gdesc_z4 = gpiod_get(&pdev->dev, "GPIOZ4_pin", + GPIOD_FLAGS_BIT_DIR_OUT); + gdesc_z5 = gpiod_get(&pdev->dev, "GPIOZ5_pin", + GPIOD_FLAGS_BIT_DIR_OUT); + if (!IS_ERR(gdesc) && !IS_ERR(gdesc_z4)) { + gpiod_direction_output(gdesc_z4, 0); + gpiod_direction_output(gdesc_z5, 0); + gpiod_direction_output(gdesc, 0); + mdelay(20); + gpiod_direction_output(gdesc, 1); + mdelay(100); + gpiod_put(gdesc_z4); + gpiod_put(gdesc_z5); + pr_debug("Ethernet: gpio reset ok\n"); + } + pin_ctl = devm_pinctrl_get_select + (&pdev->dev, "external_eth_pins"); + } + } else { + pin_ctl = devm_pinctrl_get_select(&pdev->dev, "eth_pins"); + } + pr_debug("Ethernet: pinmux setup ok\n"); + return addr; +} +#endif static int meson6_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; @@ -78,6 +182,14 @@ static int meson6_dwmac_probe(struct platform_device *pdev) plat_dat->bsp_priv = dwmac; plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; +#ifdef CONFIG_AMLOGIC_ETH_PRIVE + network_interface_setup(pdev); /* Custom initialisation (if needed) */ + if (plat_dat->init) { + ret = plat_dat->init(pdev, plat_dat->bsp_priv); + if (ret) + return ret; + } +#endif ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) @@ -93,6 +205,9 @@ err_remove_config_dt: static const struct of_device_id meson6_dwmac_match[] = { { .compatible = "amlogic,meson6-dwmac" }, +#ifdef CONFIG_AMLOGIC_ETH_PRIVE + { .compatible = "amlogic, gxbb-eth-dwmac" }, +#endif { } }; MODULE_DEVICE_TABLE(of, meson6_dwmac_match); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 4d2a759b8465..006e6fe7877e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -22,8 +22,11 @@ #ifndef __STMMAC_H__ #define __STMMAC_H__ - +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +#define STMMAC_RESOURCE_NAME "ethclk81" +#else #define STMMAC_RESOURCE_NAME "stmmaceth" +#endif #define DRV_MODULE_VERSION "Jan_2016" #include diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index ac3d39c69509..0e3b34b7216f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -268,7 +268,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) if (of_device_is_compatible(np, "st,spear600-gmac") || of_device_is_compatible(np, "snps,dwmac-3.50a") || of_device_is_compatible(np, "snps,dwmac-3.70a") || - of_device_is_compatible(np, "snps,dwmac")) { + of_device_is_compatible(np, "snps,dwmac") || +#ifdef CONFIG_AMLOGIC_ETH_PRIVE + of_device_is_compatible(np, "amlogic, gxbb-eth-dwmac") +#endif + ) { /* Note that the max-frame-size parameter as defined in the * ePAPR v1.1 spec is defined as max-frame-size, it's * actually used as the IEEE definition of MAC Client diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index c4ceb082e970..2f61dfcf5747 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -526,9 +526,12 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45) r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids); if (r) return ERR_PTR(r); - /* If the phy_id is mostly Fs, there is no device there */ +#ifdef CONFIG_AMLOGIC_ETH_PRIVE + if (phy_id == 0 || ((phy_id & 0x1fffffff) == 0x1fffffff)) +#else if ((phy_id & 0x1fffffff) == 0x1fffffff) +#endif return ERR_PTR(-ENODEV); return phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);