在Amlogic S905X5M Android14 平台上移植MAE0621 联芸1000M 以太网IC

在添加联芸MAE0621A之前,先确认哪些补丁是必须需要添加的,然后参考AML 现有的驱动架构参照支持的PHY realtek rtl8211f 来进行MAE0621A 相关驱动的移植:

common/common14-5.15/common$ git diff drivers/net/phy/phy_device.c
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 523436690ade..c50c529acfee 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -841,6 +841,15 @@ static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
 {
        int phy_reg;

+//#ifdef CONFIG_AMLOGIC_MAXIO
+        /*
+         *An MDIO connects to multiple PHYs requiring write before read.
+         *This operation does not affect one MDIO connected to a single PHY
+         *MII_PHYSID2 is a read-only register and writine to it has no effect
+         */
+       printk("=======mae0621=======mdiobus_write MII_PHYSID2.\n");
+        mdiobus_write(bus,addr,MII_PHYSID2,0);
+//#endif
        /* Grab the bits from PHYIR1, and put them in the upper half */
        phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
        if (phy_reg < 0) {




/common_drivers$ git diff drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index deddb0dbc..8cfd572f8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7538,7 +7538,10 @@ static void stmmac_reset_queues_param(struct stmmac_priv *priv)
                netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, queue));
        }
 }
-
+//#ifdef CONFIG_AMLOGIC_MAXIO
+#define MAXIO_PHY_MAE0621A_Q2C_ID 0x7b744411
+#define MAXIO_PHY_MAE0621A_Q3C_ID 0x7b744412
+//#endif
 /**
  * stmmac_resume - resume callback
  * @dev: device pointer
@@ -7603,6 +7606,15 @@ int stmmac_resume(struct device *dev)

        stmmac_free_tx_skbufs(priv);
        stmmac_clear_descriptors(priv);
+//#ifdef CONFIG_AMLOGIC_MAXIO
+       if (ndev->phydev->drv->config_init) {
+               if (ndev->phydev->phy_id == MAXIO_PHY_MAE0621A_Q2C_ID || ndev->phydev->phy_id == MAXIO_PHY_MAE0621A_Q3C_ID)
+               {
+                       ndev->phydev->drv->config_init(ndev->phydev);
+                       printk("################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@the chipid is maxio mae0621a.\n");
+               }
+       }
+//#endif

 #if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
        ret = stmmac_hw_setup(ndev, false);

以上2个补丁是联芸这颗PHY 需要添加的补丁,下面相关的补丁是参考SDK 内核驱动框架做的相关移植修改


common/common14-5.15/common/common_drivers$ git diff arch/arm64/configs/amlogic_gki.fragment
diff --git a/arch/arm64/configs/amlogic_gki.fragment b/arch/arm64/configs/amlogic_gki.fragment
index 831247335..4c9cc0f87 100644
--- a/arch/arm64/configs/amlogic_gki.fragment
+++ b/arch/arm64/configs/amlogic_gki.fragment
@@ -280,7 +280,7 @@ CONFIG_AMLOGIC_INPUT=m
 CONFIG_AMLOGIC_GPIO_KEY=y
 CONFIG_AMLOGIC_ADC_KEYPADS=y
 CONFIG_AMLOGIC_MESON_IR=y
 # amlogic-i2c.ko
 CONFIG_AMLOGIC_I2C_MESON=m
@@ -470,7 +470,7 @@ CONFIG_DWMAC_SUNXI=n
 CONFIG_DWMAC_SUN8I=n
 CONFIG_DWMAC_GENERIC=n
 CONFIG_AMLOGIC_REALTEK=m
-
+CONFIG_AMLOGIC_MAXIO=m
 # aml_dvb_extern.ko
 CONFIG_AMLOGIC_DVB_CONFIG=m
 CONFIG_AMLOGIC_DVB_EXTERN=y

common/common14-5.15/common/common_drivers$ git diff modules.bzl
diff --git a/modules.bzl b/modules.bzl
index 658306474..600cf0127 100644
--- a/modules.bzl
+++ b/modules.bzl
@@ -91,6 +91,7 @@ AMLOGIC_COMMON_MODULES = [
     "common_drivers/drivers/net/mdio/amlogic-mdio-g12a.ko",
     "common_drivers/drivers/net/phy/amlogic-inphy.ko",
     "common_drivers/drivers/net/phy/amlogic-realtek.ko",
+    "common_drivers/drivers/net/phy/amlogic-maxio.ko",
     "common_drivers/drivers/pci/controller/amlogic-pcie.ko",
     "common_drivers/drivers/pm/amlogic-pm.ko",
     "common_drivers/drivers/power/amlogic-power.ko",


common/common14-5.15/common/common_drivers$ git diff drivers/net/phy/Kconfig
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index f01db636a..91436dc04 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -9,3 +9,8 @@ config AMLOGIC_REALTEK
        tristate "Amlogic realtek PHY"
        help
          Currently has a driver for the Amlogic realtek PHY
+
+config AMLOGIC_MAXIO
+       tristate "Amlogic maxio PHY"
+       help
+         Currently has a driver for the Amlogic Maxio PHY




common/common14-5.15/common/common_drivers$ git diff drivers/net/phy/Makefile
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bb1e2775d..d2b759c83 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -13,3 +13,10 @@ PR_FMT_DEFINE_RTL = "-Dpr_fmt(fmt)= \"[$(PR_FMT_RTL)]: \" fmt"
 CFLAGS_realtek.o += $(PR_FMT_DEFINE_RTL)
 obj-$(CONFIG_AMLOGIC_REALTEK) += $(RTL_MODULE_NAME).o
 $(RTL_MODULE_NAME)-y += realtek.o
+
+MAXIO_MODULE_NAME = amlogic-maxio
+PR_FMT_MAXIO = $(subst amlogic-,,$(MAXIO_MODULE_NAME))
+PR_FMT_DEFINE_MAXIO = "-Dpr_fmt(fmt)= \"[$(PR_FMT_MAXIO)]: \" fmt"
+CFLAGS_maxio.o += $(PR_FMT_DEFINE_MAXIO)
+obj-$(CONFIG_AMLOGIC_MAXIO) += $(MAXIO_MODULE_NAME).o
+$(MAXIO_MODULE_NAME)-y += maxio.o



common/common14-5.15/common/common_drivers$ cat drivers/net/phy/maxio.c
// SPDX-License-Identifier: GPL-2.0+
/*
 * drivers/net/phy/maxio.c
 *
 * Driver for maxio PHYs
 *
 * Author: zhao yang <yang_zhao@maxio-tech.com>
 *
 * Copyright (c) 2021 maxio technology, Inc.
 *
 * 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.
 *
 */
#include <linux/bitops.h>
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/timer.h>
#include <linux/netdevice.h>

#define MAXIO_PHY_VER                                   "v1.7.6.1"
#define MAXIO_PAGE_SELECT                           0x1f
#define MAXIO_MAE0621A_CLK_MODE_REG      0x02

int maxio_read_paged(struct phy_device *phydev, int page, u32 regnum)
{
        int ret = 0, oldpage;

        oldpage = phy_read(phydev, MAXIO_PAGE_SELECT);
        if (oldpage >= 0) {
        phy_write(phydev, MAXIO_PAGE_SELECT, page);
            ret = phy_read(phydev, regnum);
    }
        phy_write(phydev, MAXIO_PAGE_SELECT, oldpage);

        return ret;
}


int maxio_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
{
        int ret = 0, oldpage;

        oldpage = phy_read(phydev, MAXIO_PAGE_SELECT);
        if (oldpage >= 0) {
        phy_write(phydev, MAXIO_PAGE_SELECT, page);
                ret = phy_write(phydev, regnum, val);
    }
        phy_write(phydev, MAXIO_PAGE_SELECT, oldpage);

        return ret;
}

static int maxio_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
{
        int ret = 0, oldpage;
        oldpage = phy_read(phydev, MAXIO_PAGE_SELECT);

        if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {// eee info
                phy_write(phydev, MAXIO_PAGE_SELECT ,0);
                phy_write(phydev, 0xd, MDIO_MMD_AN);
                phy_write(phydev, 0xe, MDIO_AN_EEE_ADV);
                phy_write(phydev, 0xd, 0x4000 | MDIO_MMD_AN);
                ret = phy_read(phydev, 0x0e);
        } else {
                ret = -EOPNOTSUPP;
        }
        phy_write(phydev, MAXIO_PAGE_SELECT, oldpage);

        return ret;
}

static int maxio_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, u16 val)
{
        int ret = 0, oldpage;
        oldpage = phy_read(phydev, MAXIO_PAGE_SELECT);

        if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { // eee info
                phy_write(phydev, MAXIO_PAGE_SELECT ,0);
                ret |= phy_write(phydev, 0xd, MDIO_MMD_AN);
                ret |= phy_write(phydev, 0xe, MDIO_AN_EEE_ADV);
                ret |= phy_write(phydev, 0xd, 0x4000 | MDIO_MMD_AN);
                ret |= phy_write(phydev, 0xe, val);
        msleep(100);
        ret |= genphy_restart_aneg(phydev);

        } else {
                ret = -EOPNOTSUPP;
        }
        phy_write(phydev, MAXIO_PAGE_SELECT, oldpage);

        return ret;
}


int maxio_adcc_check(struct phy_device *phydev)
{
        int ret = 0;
        int adcvalue;
        u32 regval;
        int i;

        maxio_write_paged(phydev, 0xd96, 0x2, 0x1fff );
        maxio_write_paged(phydev, 0xd96, 0x2, 0x1000 );

        for(i = 0; i < 4;i++)
        {
                regval = 0xf908 + i * 0x100;
                maxio_write_paged(phydev, 0xd8f, 0xb, regval );
                adcvalue = maxio_read_paged(phydev, 0xd92, 0xb);
                if(adcvalue & 0x1ff)
                {
                         continue;
                }
                else
                {
                        ret = -1;
                        break;
                }
        }

        return ret;
}


int maxio_self_check(struct phy_device *phydev,int checknum)
{
        int ret = 0;
        int i;

        for(i = 0;i < checknum; i++)
        {
                ret = maxio_adcc_check(phydev);
                if(0 == ret)
                {
                        printk("MAE0621A READY\n");
                        break;
                }
                else
                {
                        maxio_write_paged(phydev, 0x0, 0x0, 0x1940 );
                        phy_write(phydev, MAXIO_PAGE_SELECT, 0x0);
                        msleep(10);
                        maxio_write_paged(phydev, 0x0, 0x0, 0x1140 );
                        maxio_write_paged(phydev, 0x0, 0x0, 0x9140 );
                }
        }

        maxio_write_paged(phydev, 0xd96, 0x2, 0xfff );
        maxio_write_paged(phydev, 0x0, 0x0, 0x9140 );
        phy_write(phydev, MAXIO_PAGE_SELECT, 0x0);

        return ret;
}
static int maxio_mae0621a_config_aneg(struct phy_device *phydev)
{
        return genphy_config_aneg(phydev);
}

static int maxio_mae0621a_config_init(struct phy_device *phydev)
{
        int ret = 0;
        u32 broken = 0;

        printk("##########MAXIO_PHY_VER: %s \n",MAXIO_PHY_VER);

        //mdc set
        ret = maxio_write_paged(phydev, 0xda0, 0x10, 0xf13);

        //crystal
        ret |= maxio_write_paged(phydev, 0xd92, 0x02, 0x200a);
        printk("---------------maxio_mae0621a_config_init clkmode(crystal) PHY_ID: 0x%x\n", phydev->phy_id);

        //disable eee
        printk("-------------eee value: 0x%x \n",maxio_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV));
        maxio_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
        printk("---------------eee value: 0x%x \n",maxio_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV));
        broken |= MDIO_EEE_100TX;
        broken |= MDIO_EEE_1000T;
        phydev->eee_broken_modes = broken;

        //enable auto_speed_down
        ret |= maxio_write_paged(phydev, 0xd8f, 0x0, 0x300 );

        //adjust ANE
        ret |= maxio_write_paged(phydev, 0xd90, 0x2, 0x1555);
        ret |= maxio_write_paged(phydev, 0xd90, 0x5, 0x2b15);
        ret |= maxio_write_paged(phydev, 0xd96, 0x13, 0x7bc );
        ret |= maxio_write_paged(phydev, 0xd8f, 0x8, 0x2500 );
        ret |= maxio_write_paged(phydev, 0xd91, 0x6, 0x6880 );
        ret |= maxio_write_paged(phydev, 0xd92, 0x14, 0xa);
        ret |= maxio_write_paged(phydev, 0xd91, 0x7, 0x5b00);
        //clkout 125MHZ
        ret |= maxio_write_paged(phydev, 0xa43, 0x19, 0x823);

        phy_write(phydev, MAXIO_PAGE_SELECT, 0x0);
        ret |= maxio_self_check(phydev,50);

        msleep(100);

        return 0;
}

static int maxio_mae0621a_resume(struct phy_device *phydev)
{
        int ret = genphy_resume(phydev);
        //soft reset
        ret |= phy_write(phydev, MII_BMCR, BMCR_RESET | phy_read(phydev, MII_BMCR));
        msleep(20);

        return ret;
}

static int maxio_mae0621a_suspend(struct phy_device *phydev)
{
    int ret = genphy_suspend(phydev);
        //back to 0 page
    ret |= phy_write(phydev, MAXIO_PAGE_SELECT ,0);

        return ret;
}

static int maxio_mae0621a_status(struct phy_device *phydev)
{
        return genphy_read_status(phydev);
}

static int maxio_mae0621a_probe(struct phy_device *phydev)
{
        //crystal
        maxio_write_paged(phydev, 0xd92, 0x02, 0x200a);
        printk("#################maxio_mae0621a_probe clkmode(crystal) PHY_ID: 0x%x\n", phydev->phy_id);
        phy_write(phydev, MAXIO_PAGE_SELECT, 0x0);
        mdelay(100);
        return 0;
}

static int maxio_mae0621aq3ci_config_init(struct phy_device *phydev)
{
        int ret = 0;

        printk("MAXIO_PHY_VER: %s \n",MAXIO_PHY_VER);

        //MDC set
        ret = maxio_write_paged(phydev, 0xdab, 0x17, 0xf13);

        //auto speed down enable
        ret |= maxio_write_paged(phydev, 0xd8f, 0x10, 0x300);

        //adjust ANE
        ret |= maxio_write_paged(phydev, 0xd96, 0x15, 0xc08a);
        ret |= maxio_write_paged(phydev, 0xda4, 0x12, 0x7bc);
        ret |= maxio_write_paged(phydev, 0xd8f, 0x16, 0x2500);

        ret |= maxio_write_paged(phydev, 0xd90, 0x16, 0x1555);
        ret |= maxio_write_paged(phydev, 0xd92, 0x11, 0x2b15);

        ret |= maxio_write_paged(phydev, 0xd96, 0x16, 0x4010);
        ret |= maxio_write_paged(phydev, 0xda5, 0x11, 0x4a12);
        ret |= maxio_write_paged(phydev, 0xda5, 0x12, 0x4a12);
        ret |= maxio_write_paged(phydev, 0xda8, 0x11, 0x175);
        ret |= maxio_write_paged(phydev, 0xd99, 0x16, 0xa);
        ret |= maxio_write_paged(phydev, 0xd95, 0x13, 0x5b00);


        //clkout 125MHZ
        ret |= maxio_write_paged(phydev, 0xa43, 0x19, 0x823);

        //soft reset
        ret |= maxio_write_paged(phydev, 0x0, 0x0, 0x9140);

        //back to 0 page
        ret |= phy_write(phydev, MAXIO_PAGE_SELECT, 0);

        return 0;
}

static int maxio_mae0621aq3ci_resume(struct phy_device *phydev)
{
        int ret = 0;

        ret = genphy_resume(phydev);
        ret |= maxio_write_paged(phydev, 0xdaa, 0x17, 0x1001 );
        //led set
        ret |= maxio_write_paged(phydev, 0xdab, 0x15, 0x0 );
        ret |= phy_write(phydev, MAXIO_PAGE_SELECT, 0);

        return ret;
}

static int maxio_mae0621aq3ci_suspend(struct phy_device *phydev)
{
        int ret = 0;

        ret = maxio_write_paged(phydev, 0xdaa, 0x17, 0x1011 );
        //led set
        ret |= maxio_write_paged(phydev, 0xdab, 0x15, 0x5550 );
        ret |= phy_write(phydev, MAXIO_PAGE_SELECT, 0);
    ret |= genphy_suspend(phydev);
    ret |= phy_write(phydev, MAXIO_PAGE_SELECT ,0);

        return ret;
}

static struct phy_driver maxio_nc_drvs[] = {
    {
        .phy_id         = 0x7b744411,
                .phy_id_mask    = 0x7fffffff,
        .name       = "MAE0621A-Q2C Gigabit Ethernet",
                .features       = PHY_GBIT_FEATURES,
        .probe          = maxio_mae0621a_probe,
                .config_init    = maxio_mae0621a_config_init,
        .config_aneg    = maxio_mae0621a_config_aneg,
        .read_status    = maxio_mae0621a_status,
        .suspend    = maxio_mae0621a_suspend,
        .resume     = maxio_mae0621a_resume,
     },
     {
        .phy_id         = 0x7b744412,
                .phy_id_mask    = 0x7fffffff,
        .name       = "MAE0621A/B-Q3C(I) Gigabit Ethernet",
                .features       = PHY_GBIT_FEATURES,
                .config_init    = maxio_mae0621aq3ci_config_init,
        .suspend    = maxio_mae0621aq3ci_suspend,
        .resume     = maxio_mae0621aq3ci_resume,
     },
};

module_phy_driver(maxio_nc_drvs);
static struct mdio_device_id __maybe_unused maxio_nc_tbl[] = {
        { 0x7b744411, 0x7fffffff },
        { 0x7b744412, 0x7fffffff },
        { }
};

MODULE_DEVICE_TABLE(mdio, maxio_nc_tbl);


MODULE_DESCRIPTION("Maxio PHY driver");
MODULE_AUTHOR("Zhao Yang");
MODULE_LICENSE("GPL");


至此驱动移植完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Keep Coding...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值