ethernet: initial add the MAC and PHY driver

PD#131267: eth: initial add the MAC and PHY driver

1.internal eth phy supported
2.external eth phy supported
3.internal external phy can be switched by modify dts file

Change-Id: Id5e17b7fe0bef31ccf1c56d86764ef4bcb610a46
Signed-off-by: Yizhou Jiang <yizhou.jiang@amlogic.com>
Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
This commit is contained in:
Yizhou Jiang
2017-02-20 17:01:07 +08:00
committed by Jianxin Pan
parent f4f9e5f344
commit 467f3a6a87
17 changed files with 506 additions and 8 deletions

View File

@@ -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 <yizhou.jiang@amlogic.com
F: drivers/amlogic/ethernet/*

View File

@@ -19,6 +19,8 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "mesongxl.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/gxl.h>
/ {
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>;

View File

@@ -18,6 +18,8 @@
/dts-v1/;
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/gxl.h>
#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";

View File

@@ -19,6 +19,8 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "mesongxm.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/gxl.h>
/ {
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>;

View File

@@ -456,7 +456,7 @@
#interrupt-cells = <2>;
};
eth_pins:eth_pins {
external_eth_pins:external_eth_pins {
mux {
groups = "eth_mdio",
"eth_mdc",

View File

@@ -508,7 +508,7 @@
#interrupt-cells = <2>;
};
eth_pins:eth_pins {
external_eth_pins:external_eth_pins {
mux {
groups = "eth_mdio",
"eth_mdc",

View File

@@ -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

View File

@@ -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

View File

@@ -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/

View File

@@ -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.

View File

@@ -0,0 +1,3 @@
# Makefile for amlogic PHY drivers
obj-$(CONFIG_AMLOGIC_INTERNAL_PHY) += amlogic.o

View File

@@ -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 <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#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);

View File

@@ -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

View File

@@ -18,7 +18,11 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/stmmac.h>
#ifdef CONFIG_AMLOGIC_ETH_PRIVE
#include <linux/gpio/consumer.h>
#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);

View File

@@ -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 <linux/clk.h>

View File

@@ -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

View File

@@ -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);