ngswfx

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx  发布于  2016-05-09 19:53:56
采纳率 0%
55个问答
23173

雄迈板子,3535芯片,网络芯片是AR8035,kernel驱动怎么弄

 
本帖最后由 ngswfx 于 2016-5-23 18:25 编辑

越搞越糊涂了,对PHY硬件连接百思不得其姐。


不是内部已经集成了网络了吗,怎么又搞个8035,通常这种情况下,怎么弄驱动呀。

主要是这个3535是BGA,想测量连接的哪条腿都没法量。不像3520,万用表就搞定了。


是不是在kernel里面,开启MII PHY方式,调试驱动呀? 哪位大侠指点一下,我感觉我在走弯路。




//////////////////////////////////////////////////////////////////最新的动作是,直接将U-boot里面所有网络东西都禁用,仅仅在kernel里面配置网络相关的参数。
//初步计划是彻底放弃Uboot网络支持,使其能支持u盘自动升级即可。但3535 kernel网络AR8035一定要搞过去,因为自我感觉已经到了关键结点了。就差2\3个参数了。流程基本都走通了。



2016_5_11
//////////////////终于搞定了,主要是牵扯的调节项太多,没搞过驱动这种东西,一上来就搞,网上资料没有能照着模仿的,研究了3天,编译刷了1500多次kernel:lol ,没有相关文档,自己摸索,任何一个有用的log信息,都对这次编程解决问题过程,提供很大帮助。

最后主要卡在menuconfig中,那个STMMAC    (0x7) STMMAC MDIO INTERFACE ,设置成6不行,必须7才行。不知道啥意思,这个是今天黔驴技穷了,估计是配置寄存器没对,想想干脆用雄迈Uboot,然后进入kernel后,啥寄存器我都不动,尝试。

突然发现雄迈uboot,log中,有一个PHY mode=7的信息。


然后这个板子,最开始估计连接的是MAC1端口,其实连接的是MAC0。主要在menuconfig中,将PHY ID配置成2即可。

另外AT303X.c文件中的,#define AT803X_DEVICE_ADDR                      0x03,不用管,保持3即可。开始总觉得这个是不是应该为2,其实不是,就是3。

////////////////////////////////////////////////////////////////////////////////////////////////////////////

附件当中,是at303x.c文件,以及Kconfig,Makefile文件,可以使-*-   PHY Device support and infrastructure  ---> 中出现 ar3035选择项。

注意:at303x.c文件被我改的很乱,需要自己清空printk ,有些代码还需要整理。

/////////////////////////////
home/ngs/Hi3535_SDK_V1.0.2.0/osdrv/kernel/linux-3.4.y/drivers/net/ethernet/stmmac,这里面的东西应该无需调整,可以直接使用。

/home/ngs/Hi3535_SDK_V1.0.2.0/osdrv/kernel/linux-3.4.y/drivers/net/phy              ,目录里面就是用那3个文件,覆盖就行了。

然后就是配置menuconfig。我选定了PHY DMA 等选项,是在3535的小型化配置文件基础上修改的。
#cp arch/arm/configs/hi3535_mini_defconfig .config

////////////////////////////////////////////我的百纳币太少太丢人,只能挣些小钱了,呵呵。


顺便吐槽一下,又爱又恨的海丝。

static int stmmac_syscfg_init(struct platform_device *pdev)  函数里面有一句代码,差点让我吐血。

pr_info("Set system config register 0x200300ec with value 0x003f003f\n");

//这次搞驱动过程中,打印出了这个log信息,这个很明显,已经写入寄存器值,我还挺高兴,结果一看源代码,无语了.......这种信息能随便打印吗:lol

我又掉进坑里了。  而且这个地址寄存器值到底啥意思,我现在也没搞懂,只知道,如果writl直接写这个寄存器,系统就崩溃。代码中得到的寄存器地址,和这个0x200300ec完全不是一回事,差得老远了。不知所谓。


//////////////////////////////////////////////////2016_5_21 调整修改phy.c中void phy_state_machine(struct work_struct *work),使断线检测以及换交换机100M 1000M正常
case PHY_RUNNING:
                       
                        printk("PHY_RUNNING phydev->irq:%d\n",phydev->irq);
                        ///////////////////////////////////////////////////////////ngs add for 8035
                        err = genphy_update_link(phydev);
                        if (err)
                                break;
                        if (!phydev->link) {
                                phydev->state = PHY_NOLINK;
                                printk("PHY_RUNNING found link off\n");
                                netif_carrier_off(phydev->attached_dev);
                                phydev->adjust_link(phydev->attached_dev);
                        }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
易百纳技术社区文件: at803x.c.tar.gz
下载
我来回答
回答43个
时间排序
认可量排序

david

33个粉丝

368

问答

253

专栏

229

资料

david 2016-05-09 20:21:49
认可0
8035 是千兆的phy吧

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-09 21:13:38
认可0
本帖最后由 ngswfx 于 2016-5-9 21:18 编辑

对,这个板子就是要用千兆,所以采用8035的,我搞这个板子做解码

现在就是不知道,这个8035和3535怎么连接的,还是用的那2个端口其中一个吧?

我在kernel里面强制开启STMMAC,系统可以找到eth1(eth0找不到),也可以配置IP,(由于没有实际连接,当然无法访问)


我只能猜测,eth0那个端口连接了8035。这种方式怎么搞驱动。

我从3536的SDK里面,已经找到了at803X.c,也就是基于PHY方式的驱动。接着就不知道该怎么搞了。在kernel menu config中,启用PHY,kernel启动找不到。

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-05-10 08:22:51
认可0
海思网络部分物理上看一般是MAC连接PHY(就是8035)再连接网络变压器再到RJ45

从数据通路上看, MAC是海思芯片内部的模块,通过MDIO来设置PHY(读写PHY的寄存器), 通过MII/RMII/RGMII接口(3535都支持)来和PHY交换网络数据

通常情况下, 海思的linux网络驱动基本都是好的,要修改的一般就是PHY地址和使用MII/RMII/RGMII接口中的哪一种,这个在linux config时应该都可以选

另外, 要注意一下管脚复用, 一般uboot配网络时应该都把复用关系改好了,只要后面不要再改变就好了

3535有两个MAC, 两套PHY接口, 一套MDIO接口(有点像I2C, 可以读写多个PHY)

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-10 09:55:53
认可0
本帖最后由 ngswfx 于 2016-5-10 10:45 编辑

[quote][url=forum.php?mod=redirect&goto=findpost&pid=29815&ptid=11266]zhuangweiye 发表于 2016-5-10 08:22[/url]
海思网络部分物理上看一般是MAC连接PHY(就是8035)再连接网络变压器再到RJ45

从数据通路上看, MAC是海思 ...[/quote]

多谢解答,我昨晚上搞了很久,尝试修改menuconfig一些地方,基本上的思路是摸清了一些,和您说的基本吻合了。

目前我将menuconfig中ethernet 中STMMAC,驱动开启,进入系统后,已经可以搜索到AT803X的PHY设备,显示的设备PHY ID和8035驱动中的一致,都是004dd072

0x000000000000-0x000000040000 : "boot"
0x000000040000-0x0000004e0000 : "kernel"
0x0000004e0000-0x000000fe0000 : "rootfs"
Fixed MDIO Bus: probed
atheros_init in
phy_driver_register ok
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky <[email]maxk@qualcomm.com[/email]>
STMMAC driver:
        platform registration...
        done!
Set system config register 0x200300ec with value 0x003f003f            //这应该也是一个关键动作。
        done!
        DWMAC1000 - user ID: 0x10, Synopsys ID: 0x36
        Enhanced descriptor structure
MACADDR in get is 0:0:0:0:0:0
        no valid MAC address for MAC 0;please, use ifconfig or nwhwconfig!
stmmac_external_phy_reset in
stmmac_rst_phy_use_gpio in                 //这里好像没对,怎么配置起GPIO了
        eth0 - (dev. name: stmmaceth - id: 0, IRQ #59
        IO base addr: 0xfe0a0000)        //由于硬件连接很可能是第二个MAC口,所以我在Menuconfig里面直接将MAC0的ID号,改成2了,这里的IObase还不太对。应该再+0x4000.


//////////////////////////////////////////////////////////////////下面面我在各个相关函数进入时加入了printk
mdio_clk_init in
STMMAC MII Bus: probed
eth0: PHY ID 004dd072 at 2 IRQ -6 (1:02) active                      //这里的active很关键,但看了源代码才发现IRQ -6中的-,可不是分隔符号,就是-6,这里就错了。
stmmac_reset: RESET COMPLETE!

**************************************************
*  TNK driver built on May 10 2016 at 06:34:36
*  TNK driver mode is BYPASS
**************************************************
stmmac: Rx Checksum Offload Engine supported
TCP: cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
NET: Registered protocol family 15
registered taskstats version 1
VFS: Mounted root (jffs2 filesystem) on device 31:2.
Freeing init memory: 156K

            _ _ _ _ _ _ _ _ _ _ _ _
            \  _  _   _  _ _ ___
            / /__/ \ |_/
           / __   /  -  _ ___
          / /  / /  / /
  _ _ _ _/ /  /  \_/  \_ ______
___________\___\__________________

/////////////////////////////////////////////////////////////////////////进入系统后 IPconfig配置网络
# ifconfig eth0 hw ether 20:30:40:00:02:32
# ifconfig eth0 192.168.2.18 netmask 255.255.0.0
at803x_config_init in
at803x_config_init 100M
at803x_config_init 1000M
at803x_set_wol_mac_addr in
at803x_set_wol_mac_addr 30:2000        //仅仅确认MAC信息是否一致,仅仅显示了部分
phy_start_machine
MACADDR in set is 20:30:40:0:2:32
PHY_start
# PHY_UP
phy_start_aneg
PHY_AN
PHY_NOLINK
reset_mac_interface_dual in
ngs PHY: 1:02 - Link is Up - 100/Full
route add default gw 192.168.2.1
#
//////////////////////////////////////////////////////////////////////////问题就来了,网络表面成功了,其实PHY连接没对
//正常网络不停修改MAC,不会出错了,这个不行,也就是硬件PHY部分数据交互部分还是异常
//比较确信用的是MAC第二个口的依据是:目前这种配置,如果IPConfig开启网络,能够自动侦测到网络开启,显示PHY: 1:02 - Link is Up - 100/Full。但是断网不行,无任何状态显示。
//下面的MAC地址修改,只有将ipconfig eth0 down,再次UP,才能正确配置一次


# ifconfig eth0 hw ether 20:30:40:00:02:32
ifconfig: SIOCSIFHWADDR: Device or resource busy
# ifconfig eth0 hw ether 20:30:40:00:02:33
ifconfig: SIOCSIFHWADDR: Device or resource busy

/////////////////////////////////////////////////////////////////////////使用ping命令阻塞在那里,不动,其他设备也无法ping通这个设备。

# ifconfig                                
eth0      Link encap:Ethernet  HWaddr 20:30:40:00:02:32  
          inet addr:192.168.2.18  Bcast:192.168.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:547 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:81540 (79.6 KiB)  TX bytes:0 (0.0 B)
          Interrupt:59
///////////////////////////////////////////////////////////           

我现在主要怀疑几个关键点: 不确定。仅仅猜测

1、 IO base addr: 0xfe0a0000)  问题,需要强制使用第二个MAC口的地址,再加上0x4000
2、#define AT803X_DEVICE_ADDR                        0x03               //这个是在AT803X里面的定义,这个值可能需要修改,感觉这个值应该和硬件某些脚上拉下拉有关(还没搞懂)。
3、怀疑MAC没有正确写入PHY芯片。
4、MDIO配置等命令错误


//////目前我仿照3536的处理方法,在tnk_hi3535.c添加了void stmmac_external_phy_reset(int port_id, void *syscfg_addr);函数实现。并在stmmac_main中,加入这个函数。log流程显示,已经进入去配置了(日志里面的 stmmac_external_phy_reset in)。
#define SYSCTL_BASE                0x20030000
#define TOE_CLK_SRST                0x000000c8
#define TOE_MAC_INTERFACE        0x000000ec

#define TOE_CLK_DEF_100M        0x00000800

#define TOE_MAX_CON_NUM                0x000000ff
#define TOE_DEFAULT_CLK_100M        100000000
#define TOE_DEFAULT_CLK_150M        150000000
#define TOE_DEFAULT_CLK_250M        250000000

//////////////////////////////////////////////////////////////////////////////////////////下面这几个还没有参考文档确认,抄的3536的,stmmac_external_phy_reset流程中要用到。
#define MUXCTL_BASE                IO_ADDRESS(0x120f0000)
#define MUXCTL_REG16_OFFSET        (0x040)
#define MUXCTL_REG34_OFFSET        (0x088)
#define MUXCTL_PHY_MASK                0x3

#define TOE_CLK_EXT_PHY0_RST_BIT                13
#define TOE_CLK_EXT_PHY1_RST_BIT                14
///////////////////////////////////////////////////////////////////////////////////////////////////

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-10 10:22:26
认可0
本帖最后由 ngswfx 于 2016-5-10 10:25 编辑

//////////////////////////////////////////////////AT803X.c代码,为了方便流程检查,也放上来
////////////////////////////////////////////////配合上面的启动log,可以看出ifconfig执行开启网络时,已经进入了at803x_config_init以及at803x_set_wol_mac_addr

#include
#include
#include
#include
#include

#define AT803X_INTR_ENABLE                        0x12
#define AT803X_INTR_STATUS                        0x13
#define AT803X_WOL_ENABLE                        0x01
#define AT803X_DEVICE_ADDR                        0x03
//#define AT803X_DEVICE_ADDR                        0x00   //ngs

#define AT803X_LOC_MAC_ADDR_0_15_OFFSET                0x804C
#define AT803X_LOC_MAC_ADDR_16_31_OFFSET        0x804B
#define AT803X_LOC_MAC_ADDR_32_47_OFFSET        0x804A
#define AT803X_MMD_ACCESS_CONTROL                0x0D
#define AT803X_MMD_ACCESS_CONTROL_DATA                0x0E
#define AT803X_FUNC_DATA                        0x4003

MODULE_DESCRIPTION("Atheros 803x PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");

static void at803x_set_wol_mac_addr(struct phy_device *phydev)
{
        printk(" at803x_set_wol_mac_addr in\n");
        struct net_device *ndev = phydev->attached_dev;
        const u8 *mac;
        unsigned int i, offsets[] = {
                AT803X_LOC_MAC_ADDR_32_47_OFFSET,
                AT803X_LOC_MAC_ADDR_16_31_OFFSET,
                AT803X_LOC_MAC_ADDR_0_15_OFFSET,
        };

        if (!ndev){
                printk(" at803x_set_wol_mac_addr ndev error \n");
                return;
        }

        mac = (const u8 *) ndev->dev_addr;
        printk("at803x_set_wol_mac_addr %x:%x \n", mac[1],(mac[0] << 8));
       
        if (!is_valid_ether_addr(mac)){
                printk(" at803x_set_wol_mac_addr mac error \n");
                return;
        }
        unsigned int j;
        //for(j=0;j<16;j++)
        {
                for (i = 0; i < 3; i++) {
                        phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,AT803X_DEVICE_ADDR);
                        //phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,j);
                        phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,offsets);
                        phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,AT803X_FUNC_DATA);
                        phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
                }
        }
}

static int at803x_config_init(struct phy_device *phydev)
{
        printk(" at803x_config_init in\n");
        int val;
        u32 features;
        int status;

        features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
                   SUPPORTED_FIBRE | SUPPORTED_BNC;

        val = phy_read(phydev, MII_BMSR);
        if (val < 0){
                printk(" at803x_config_init error val<0\n");
                return val;
        }

        if (val & BMSR_ANEGCAPABLE)
                features |= SUPPORTED_Autoneg;
        if (val & BMSR_100FULL){
                features |= SUPPORTED_100baseT_Full;
                printk(" at803x_config_init 100M\n");
        }
        if (val & BMSR_100HALF)
                features |= SUPPORTED_100baseT_Half;
        if (val & BMSR_10FULL)
                features |= SUPPORTED_10baseT_Full;
        if (val & BMSR_10HALF)
                features |= SUPPORTED_10baseT_Half;

        if (val & BMSR_ESTATEN) {
                val = phy_read(phydev, MII_ESTATUS);
                if (val < 0){
                        printk(" at803x_config_init error 2 val<0\n");
                        return val;
                }

                if (val & ESTATUS_1000_TFULL){
                        features |= SUPPORTED_1000baseT_Full;
                        printk(" at803x_config_init 1000M\n");
                }
                if (val & ESTATUS_1000_THALF)
                        features |= SUPPORTED_1000baseT_Half;
        }


        features |= SUPPORTED_10baseT_Full;

        phydev->supported = features;
        phydev->advertising = features;

        /* enable WOL */
        at803x_set_wol_mac_addr(phydev);
        status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE);
        status = phy_read(phydev, AT803X_INTR_STATUS);

        return 0;
}

/* ATHEROS 8035 */
static struct phy_driver at8035_driver = {
        .phy_id                = 0x004dd072,
        .name                = "Atheros 8035 ethernet",
        .phy_id_mask        = 0xffffffef,
        .config_init        = at803x_config_init,
        .features        = PHY_GBIT_FEATURES,
        .flags                = PHY_HAS_INTERRUPT,
        .config_aneg        = &genphy_config_aneg,
        .read_status        = &genphy_read_status,
        .driver                = {
                .owner = THIS_MODULE,
        },
};

/* ATHEROS 8030 */
static struct phy_driver at8030_driver = {
        .phy_id                = 0x004dd076,
        .name                = "Atheros 8030 ethernet",
        .phy_id_mask        = 0xffffffef,
        .config_init        = at803x_config_init,
        .features        = PHY_GBIT_FEATURES,
        .flags                = PHY_HAS_INTERRUPT,
        .config_aneg        = &genphy_config_aneg,
        .read_status        = &genphy_read_status,
        .driver                = {
                .owner = THIS_MODULE,
        },
};

static int __init atheros_init(void)
{
printk(" atheros_init in\n");
        int ret;

        ret = phy_driver_register(&at8035_driver);
        if (ret){
                printk("phy_driver_register error\n");
                goto err1;
        }

        ret = phy_driver_register(&at8030_driver);
        if (ret)
         goto err2;
        printk("phy_driver_register ok\n");
        return 0;

err2:
        phy_driver_unregister(&at8035_driver);
err1:
        return ret;
}

static void __exit atheros_exit(void)
{
        printk(" atheros_exit in\n");
        phy_driver_unregister(&at8035_driver);
        phy_driver_unregister(&at8030_driver);
}

module_init(atheros_init);
module_exit(atheros_exit);

static struct mdio_device_id __maybe_unused atheros_tbl[] = {
        { 0x004dd076, 0xffffffef },
        { 0x004dd072, 0xffffffef },
        { }
};

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-10 10:32:10
认可0
本帖最后由 ngswfx 于 2016-5-11 19:00 编辑

[quote][url=forum.php?mod=redirect&goto=findpost&pid=29815&ptid=11266]zhuangweiye 发表于 2016-5-10 08:22[/url]
海思网络部分物理上看一般是MAC连接PHY(就是8035)再连接网络变压器再到RJ45

从数据通路上看, MAC是海思 ...[/quote]

现在能基本预估的结论是:
1、这个雄迈板子应该连接的第2个MAC口,因为在2个都开启情况下,第二个口能配置IP,并且能侦测出网线插入动作(ifconfig开启前都不插网线,开启后等很久,没有任何提示(其实内部持续提示PHY_NOLINK),只要一插入,提示PHY: 1:02 - Link is Up - 100/Full)。
2、既然是千兆,应该用的RGMII连接方式。模式应为为6,代码帮助解释,也说默认为6。其实这就是最大的问题,后来成成功后,证明必须为7,而且端口也不是第二个MAC,仅仅因为第二个MAC设置的PHY ID=2,所以有反应.

///////////////////////////////////////////////////////最新的动作是,直接将U-boot里面所有网络东西都禁用,仅仅在kernel里面配置网络相关的参数。

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-05-10 11:22:29
认可0
本帖最后由 zhuangweiye 于 2016-5-10 11:27 编辑

来个网络通的log

[10:58:59:206] STMMAC driver:
[10:58:59:417]         platform registration...
[10:58:59:418]         done!
[10:58:59:418]         done!
[10:58:59:418]         DWMAC1000 - user ID: 0x10, Synopsys ID: 0x36
[10:58:59:419] MACADDR in get is 0:32:ff:ff:ff:ff
[10:58:59:420] stmmac_associate_phy: phy 0 mode=6
[10:58:59:420]         eth0 - (dev. name: stmmaceth - id: 0, IRQ #59
[10:58:59:421]         IO base addr: 0xfe0a0000)
[10:58:59:421] STMMAC MII Bus: probed
[10:58:59:421] eth0: PHY ID 004dd072 at 2 IRQ -6 (0:02) active        //004dd072这个ID是不是和楼主的一样:lol  这个2表示的是PHY地址, 好像也和楼主的一样
[10:58:59:422]         DWMAC1000 - user ID: 0x10, Synopsys ID: 0x36



楼主看样子是PHY地址没设对

关于PHY地址的问题

就是AR8035支持有3个管脚来设PHY地址,可以量一下就知道了,当然也可以偷懒,反正linux起来的时候会去扫描所有的PHY地址,并把符合的PHY找出来(上面有下划线的部分),里面有PHY ID和PHY地址


ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-10 12:02:08
认可0
看来IRQ -6不是问题

有了你这个log我就不用瞎怀疑很多东西了:lol

rafael_wl

0个粉丝

12

问答

0

专栏

7

资料

rafael_wl 2016-05-10 15:37:51
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=29831&ptid=11266]ngswfx 发表于 2016-5-10 12:02[/url]
看来IRQ -6不是问题

有了你这个log我就不用瞎怀疑很多东西了[/quote]

目录下有这个么?
Linux/drivers/net/phy/at803x.c
我下面没有

[code]  1 /*
  2  * drivers/net/phy/at803x.c
  3  *
  4  * Driver for Atheros 803x PHY
  5  *
  6  * Author: Matus Ujhelyi
  7  *
  8  * This program is free software; you can redistribute  it and/or modify it
  9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13
14 #include
15 #include
16 #include
17 #include
18 #include
19 #include
20 #include
21
22 #define AT803X_INTR_ENABLE                      0x12
23 #define AT803X_INTR_ENABLE_AUTONEG_ERR          BIT(15)
24 #define AT803X_INTR_ENABLE_SPEED_CHANGED        BIT(14)
25 #define AT803X_INTR_ENABLE_DUPLEX_CHANGED       BIT(13)
26 #define AT803X_INTR_ENABLE_PAGE_RECEIVED        BIT(12)
27 #define AT803X_INTR_ENABLE_LINK_FAIL            BIT(11)
28 #define AT803X_INTR_ENABLE_LINK_SUCCESS         BIT(10)
29 #define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE  BIT(5)
30 #define AT803X_INTR_ENABLE_POLARITY_CHANGED     BIT(1)
31 #define AT803X_INTR_ENABLE_WOL                  BIT(0)
32
33 #define AT803X_INTR_STATUS                      0x13
34
35 #define AT803X_SMART_SPEED                      0x14
36 #define AT803X_LED_CONTROL                      0x18
37
38 #define AT803X_DEVICE_ADDR                      0x03
39 #define AT803X_LOC_MAC_ADDR_0_15_OFFSET         0x804C
40 #define AT803X_LOC_MAC_ADDR_16_31_OFFSET        0x804B
41 #define AT803X_LOC_MAC_ADDR_32_47_OFFSET        0x804A
42 #define AT803X_MMD_ACCESS_CONTROL               0x0D
43 #define AT803X_MMD_ACCESS_CONTROL_DATA          0x0E
44 #define AT803X_FUNC_DATA                        0x4003
45
46 #define AT803X_DEBUG_ADDR                       0x1D
47 #define AT803X_DEBUG_DATA                       0x1E
48
49 #define AT803X_DEBUG_REG_0                      0x00
50 #define AT803X_DEBUG_RX_CLK_DLY_EN              BIT(15)
51
52 #define AT803X_DEBUG_REG_5                      0x05
53 #define AT803X_DEBUG_TX_CLK_DLY_EN              BIT(8)
54
55 #define ATH8030_PHY_ID 0x004dd076
56 #define ATH8031_PHY_ID 0x004dd074
57 #define ATH8035_PHY_ID 0x004dd072
58
59 MODULE_DESCRIPTION("Atheros 803x PHY driver");
60 MODULE_AUTHOR("Matus Ujhelyi");
61 MODULE_LICENSE("GPL");
62
63 struct at803x_priv {
64         bool phy_reset:1;
65         struct gpio_desc *gpiod_reset;
66 };
67
68 struct at803x_context {
69         u16 bmcr;
70         u16 advertise;
71         u16 control1000;
72         u16 int_enable;
73         u16 smart_speed;
74         u16 led_control;
75 };
76
77 static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
78 {
79         int ret;
80
81         ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
82         if (ret < 0)
83                 return ret;
84
85         return phy_read(phydev, AT803X_DEBUG_DATA);
86 }
87
88 static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
89                                  u16 clear, u16 set)
90 {
91         u16 val;
92         int ret;
93
94         ret = at803x_debug_reg_read(phydev, reg);
95         if (ret < 0)
96                 return ret;
97
98         val = ret & 0xffff;
99         val &= ~clear;
100         val |= set;
101
102         return phy_write(phydev, AT803X_DEBUG_DATA, val);
103 }
104
105 static inline int at803x_enable_rx_delay(struct phy_device *phydev)
106 {
107         return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0,
108                                         AT803X_DEBUG_RX_CLK_DLY_EN);
109 }
110
111 static inline int at803x_enable_tx_delay(struct phy_device *phydev)
112 {
113         return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0,
114                                         AT803X_DEBUG_TX_CLK_DLY_EN);
115 }
116
117 /* save relevant PHY registers to private copy */
118 static void at803x_context_save(struct phy_device *phydev,
119                                 struct at803x_context *context)
120 {
121         context->bmcr = phy_read(phydev, MII_BMCR);
122         context->advertise = phy_read(phydev, MII_ADVERTISE);
123         context->control1000 = phy_read(phydev, MII_CTRL1000);
124         context->int_enable = phy_read(phydev, AT803X_INTR_ENABLE);
125         context->smart_speed = phy_read(phydev, AT803X_SMART_SPEED);
126         context->led_control = phy_read(phydev, AT803X_LED_CONTROL);
127 }
128
129 /* restore relevant PHY registers from private copy */
130 static void at803x_context_restore(struct phy_device *phydev,
131                                    const struct at803x_context *context)
132 {
133         phy_write(phydev, MII_BMCR, context->bmcr);
134         phy_write(phydev, MII_ADVERTISE, context->advertise);
135         phy_write(phydev, MII_CTRL1000, context->control1000);
136         phy_write(phydev, AT803X_INTR_ENABLE, context->int_enable);
137         phy_write(phydev, AT803X_SMART_SPEED, context->smart_speed);
138         phy_write(phydev, AT803X_LED_CONTROL, context->led_control);
139 }
140
141 static int at803x_set_wol(struct phy_device *phydev,
142                           struct ethtool_wolinfo *wol)
143 {
144         struct net_device *ndev = phydev->attached_dev;
145         const u8 *mac;
146         int ret;
147         u32 value;
148         unsigned int i, offsets[] = {
149                 AT803X_LOC_MAC_ADDR_32_47_OFFSET,
150                 AT803X_LOC_MAC_ADDR_16_31_OFFSET,
151                 AT803X_LOC_MAC_ADDR_0_15_OFFSET,
152         };
153
154         if (!ndev)
155                 return -ENODEV;
156
157         if (wol->wolopts & WAKE_MAGIC) {
158                 mac = (const u8 *) ndev->dev_addr;
159
160                 if (!is_valid_ether_addr(mac))
161                         return -EFAULT;
162
163                 for (i = 0; i < 3; i++) {
164                         phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
165                                   AT803X_DEVICE_ADDR);
166                         phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
167                                   offsets);
168                         phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
169                                   AT803X_FUNC_DATA);
170                         phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
171                                   mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
172                 }
173
174                 value = phy_read(phydev, AT803X_INTR_ENABLE);
175                 value |= AT803X_INTR_ENABLE_WOL;
176                 ret = phy_write(phydev, AT803X_INTR_ENABLE, value);
177                 if (ret)
178                         return ret;
179                 value = phy_read(phydev, AT803X_INTR_STATUS);
180         } else {
181                 value = phy_read(phydev, AT803X_INTR_ENABLE);
182                 value &= (~AT803X_INTR_ENABLE_WOL);
183                 ret = phy_write(phydev, AT803X_INTR_ENABLE, value);
184                 if (ret)
185                         return ret;
186                 value = phy_read(phydev, AT803X_INTR_STATUS);
187         }
188
189         return ret;
190 }
191
192 static void at803x_get_wol(struct phy_device *phydev,
193                            struct ethtool_wolinfo *wol)
194 {
195         u32 value;
196
197         wol->supported = WAKE_MAGIC;
198         wol->wolopts = 0;
199
200         value = phy_read(phydev, AT803X_INTR_ENABLE);
201         if (value & AT803X_INTR_ENABLE_WOL)
202                 wol->wolopts |= WAKE_MAGIC;
203 }
204
205 static int at803x_suspend(struct phy_device *phydev)
206 {
207         int value;
208         int wol_enabled;
209
210         mutex_lock(&phydev->lock);
211
212         value = phy_read(phydev, AT803X_INTR_ENABLE);
213         wol_enabled = value & AT803X_INTR_ENABLE_WOL;
214
215         value = phy_read(phydev, MII_BMCR);
216
217         if (wol_enabled)
218                 value |= BMCR_ISOLATE;
219         else
220                 value |= BMCR_PDOWN;
221
222         phy_write(phydev, MII_BMCR, value);
223
224         mutex_unlock(&phydev->lock);
225
226         return 0;
227 }
228
229 static int at803x_resume(struct phy_device *phydev)
230 {
231         int value;
232
233         mutex_lock(&phydev->lock);
234
235         value = phy_read(phydev, MII_BMCR);
236         value &= ~(BMCR_PDOWN | BMCR_ISOLATE);
237         phy_write(phydev, MII_BMCR, value);
238
239         mutex_unlock(&phydev->lock);
240
241         return 0;
242 }
243
244 static int at803x_probe(struct phy_device *phydev)
245 {
246         struct device *dev = &phydev->mdio.dev;
247         struct at803x_priv *priv;
248         struct gpio_desc *gpiod_reset;
249
250         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
251         if (!priv)
252                 return -ENOMEM;
253
254         gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
255         if (IS_ERR(gpiod_reset))
256                 return PTR_ERR(gpiod_reset);
257
258         priv->gpiod_reset = gpiod_reset;
259
260         phydev->priv = priv;
261
262         return 0;
263 }
264
265 static int at803x_config_init(struct phy_device *phydev)
266 {
267         int ret;
268
269         ret = genphy_config_init(phydev);
270         if (ret < 0)
271                 return ret;
272
273         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
274                         phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
275                 ret = at803x_enable_rx_delay(phydev);
276                 if (ret < 0)
277                         return ret;
278         }
279
280         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
281                         phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
282                 ret = at803x_enable_tx_delay(phydev);
283                 if (ret < 0)
284                         return ret;
285         }
286
287         return 0;
288 }
289
290 static int at803x_ack_interrupt(struct phy_device *phydev)
291 {
292         int err;
293
294         err = phy_read(phydev, AT803X_INTR_STATUS);
295
296         return (err < 0) ? err : 0;
297 }
298
299 static int at803x_config_intr(struct phy_device *phydev)
300 {
301         int err;
302         int value;
303
304         value = phy_read(phydev, AT803X_INTR_ENABLE);
305
306         if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
307                 value |= AT803X_INTR_ENABLE_AUTONEG_ERR;
308                 value |= AT803X_INTR_ENABLE_SPEED_CHANGED;
309                 value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
310                 value |= AT803X_INTR_ENABLE_LINK_FAIL;
311                 value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
312
313                 err = phy_write(phydev, AT803X_INTR_ENABLE, value);
314         }
315         else
316                 err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
317
318         return err;
319 }
320
321 static void at803x_link_change_notify(struct phy_device *phydev)
322 {
323         struct at803x_priv *priv = phydev->priv;
324
325         /*
326          * Conduct a hardware reset for AT8030 every time a link loss is
327          * signalled. This is necessary to circumvent a hardware bug that
328          * occurs when the cable is unplugged while TX packets are pending
329          * in the FIFO. In such cases, the FIFO enters an error mode it
330          * cannot recover from by software.
331          */
332         if (phydev->drv->phy_id == ATH8030_PHY_ID) {
333                 if (phydev->state == PHY_NOLINK) {
334                         if (priv->gpiod_reset && !priv->phy_reset) {
335                                 struct at803x_context context;
336
337                                 at803x_context_save(phydev, &context);
338
339                                 gpiod_set_value(priv->gpiod_reset, 0);
340                                 msleep(1);
341                                 gpiod_set_value(priv->gpiod_reset, 1);
342                                 msleep(1);
343
344                                 at803x_context_restore(phydev, &context);
345
346                                 phydev_dbg(phydev, "%s(): phy was reset\n",
347                                            __func__);
348                                 priv->phy_reset = true;
349                         }
350                 } else {
351                         priv->phy_reset = false;
352                 }
353         }
354 }
355
356 static struct phy_driver at803x_driver[] = {
357 {
358         /* ATHEROS 8035 */
359         .phy_id                 = ATH8035_PHY_ID,
360         .name                   = "Atheros 8035 ethernet",
361         .phy_id_mask            = 0xffffffef,
362         .probe                  = at803x_probe,
363         .config_init            = at803x_config_init,
364         .link_change_notify     = at803x_link_change_notify,
365         .set_wol                = at803x_set_wol,
366         .get_wol                = at803x_get_wol,
367         .suspend                = at803x_suspend,
368         .resume                 = at803x_resume,
369         .features               = PHY_GBIT_FEATURES,
370         .flags                  = PHY_HAS_INTERRUPT,
371         .config_aneg            = genphy_config_aneg,
372         .read_status            = genphy_read_status,
373         .ack_interrupt          = at803x_ack_interrupt,
374         .config_intr            = at803x_config_intr,
375 }, {
376         /* ATHEROS 8030 */
377         .phy_id                 = ATH8030_PHY_ID,
378         .name                   = "Atheros 8030 ethernet",
379         .phy_id_mask            = 0xffffffef,
380         .probe                  = at803x_probe,
381         .config_init            = at803x_config_init,
382         .link_change_notify     = at803x_link_change_notify,
383         .set_wol                = at803x_set_wol,
384         .get_wol                = at803x_get_wol,
385         .suspend                = at803x_suspend,
386         .resume                 = at803x_resume,
387         .features               = PHY_BASIC_FEATURES,
388         .flags                  = PHY_HAS_INTERRUPT,
389         .config_aneg            = genphy_config_aneg,
390         .read_status            = genphy_read_status,
391         .ack_interrupt          = at803x_ack_interrupt,
392         .config_intr            = at803x_config_intr,
393 }, {
394         /* ATHEROS 8031 */
395         .phy_id                 = ATH8031_PHY_ID,
396         .name                   = "Atheros 8031 ethernet",
397         .phy_id_mask            = 0xffffffef,
398         .probe                  = at803x_probe,
399         .config_init            = at803x_config_init,
400         .link_change_notify     = at803x_link_change_notify,
401         .set_wol                = at803x_set_wol,
402         .get_wol                = at803x_get_wol,
403         .suspend                = at803x_suspend,
404         .resume                 = at803x_resume,
405         .features               = PHY_GBIT_FEATURES,
406         .flags                  = PHY_HAS_INTERRUPT,
407         .config_aneg            = genphy_config_aneg,
408         .read_status            = genphy_read_status,
409         .ack_interrupt          = &at803x_ack_interrupt,
410         .config_intr            = &at803x_config_intr,
411 } };
412
413 module_phy_driver(at803x_driver);
414
415 static struct mdio_device_id __maybe_unused atheros_tbl[] = {
416         { ATH8030_PHY_ID, 0xffffffef },
417         { ATH8031_PHY_ID, 0xffffffef },
418         { ATH8035_PHY_ID, 0xffffffef },
419         { }
420 };
421
422 MODULE_DEVICE_TABLE(mdio, atheros_tbl);[/code]

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-10 17:29:22
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=29841&ptid=11266]rafael_wl 发表于 2016-5-10 15:37[/url]
目录下有这个么?
Linux/drivers/net/phy/at803x.c
我下面没有[/quote]

你的这个文件版本太高了,要用3536里面的改吧,你这个是linxu 4.5里面的,牵扯修改的地方太多。

3535默认SDK没有这个at303x.c文件。

真一百啦

0个粉丝

0

问答

0

专栏

0

资料

真一百啦 2016-06-17 17:55:02
认可0
楼主,我想请教下,我也是网卡似乎可以用了,就是ping不通,请问最后楼主怎么解决的

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-06-17 18:22:08
认可0
根据我调试8035的经验,已经做了3535以及3536,现在都基本正常。
//////一定找2个交换机,1个百兆一个千兆,ping的时候,都试一下。

///主要就是PHY的地址,这个只要对了,就是驱动代码了,3536里面的代码还需要改一下,才能用。

注意这2句:
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||                       
  phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
                ret = at803x_enable_rx_delay(phydev);
                 if (ret < 0)
                        return ret;
         }     
   if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
                         phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
                ret = at803x_enable_tx_delay(phydev);
                if (ret < 0)
                        return ret;
         }
////你可以直接开启deley 不去判断phydev->interface  ,上面代码好像要求interface 为6或者7才执行。
//我发现这2行,如果在3535上不执行,ping不通。3536我做的时候,强制都执行了。如下:
ret = at803x_enable_rx_delay(phydev);
ret = at803x_enable_tx_delay(phydev);

rafael_wl

0个粉丝

12

问答

0

专栏

7

资料

rafael_wl 2016-06-18 10:50:03
认可0
目前很多phy在linux都有驱动代码了,其实最主要的还是phy地址,mii通了基本就能用了

真一百啦

0个粉丝

0

问答

0

专栏

0

资料

真一百啦 2016-06-20 08:58:13
认可0
我是3521A做主控芯片,也是AR8035,直接用它的内核源码,只是修改内核配置就修改了PHY地址,然而现在PING不通同网段的,看来还得再纠结下了

fb362203

0个粉丝

24

问答

0

专栏

0

资料

fb362203 2016-10-14 13:44:35
认可0
雄迈的板子怎么没有海思的标准sdk?你的板子有么

blacktulip7

0个粉丝

3

问答

0

专栏

0

资料

blacktulip7 2016-10-14 15:36:47
认可0
其实PHY这一部分分两步
1.先把MDIO搞通,拔插网线可以显示link up,link down;如果这一步没出来就是mdio没搞对或者PHY寄存器没设对;记得mdio里面有一个scan的函数,可以获取PHY的ID,先把这个搞对,再确认下寄存器
2.上面那步搞好了后就差不多,选择下接口,MII,RMII,还是RGMII;
当然了,海思的内核里面有些小bug有时候挺误导人的,phy那部分的代码可以看下。

fb362203

0个粉丝

24

问答

0

专栏

0

资料

fb362203 2016-10-18 21:48:48
认可0
哥们。你用的是熊买的板子的话,那问你一个问题,怎么把雄迈的程序干掉啊。我串口登录后台, 一直显示

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
ctrl+c干不掉,又不能对其进行其他操作输入什么的。你知道么?求助,感激不尽啊

ngswfx

1个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-10-21 23:45:22
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=39729&ptid=11266]fb362203 发表于 2016-10-18 21:48[/url]
哥们。你用的是熊买的板子的话,那问你一个问题,怎么把雄迈的程序干掉啊。我串口登录后台, 一直显示

S ...[/quote]

雄迈板子,进入kernel后,串口就做它用了,板子上不是有485嘛,串口用来弄485了,所以就用不成了。

你可以试试用telnet访问的方式,我也不知道登录密码。

我是直接从uboot截获接管以后,整个系统全刷了。从uboot-kernel-rootfs

fb362203

0个粉丝

24

问答

0

专栏

0

资料

fb362203 2016-10-24 09:11:27
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=39968&ptid=11266]ngswfx 发表于 2016-10-21 23:45[/url]
雄迈板子,进入kernel后,串口就做它用了,板子上不是有485嘛,串口用来弄485了,所以就用不成了。

你 ...[/quote]

哦哦,好的,回家试试telnet先吧

fb362203

0个粉丝

24

问答

0

专栏

0

资料

fb362203 2016-10-24 22:04:25
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=39968&ptid=11266]ngswfx 发表于 2016-10-21 23:45[/url]
雄迈板子,进入kernel后,串口就做它用了,板子上不是有485嘛,串口用来弄485了,所以就用不成了。

你 ...[/quote]

telnet说23端口没打开,应该是没有开telnet服务器。求教怎么用雄迈板子烧写系统,没有中断输入,不知道怎么烧写系统
加载中···
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区