Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
67887903
U
U-Boot.Mirror
项目概览
OS
/
U-Boot.Mirror
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
U-Boot.Mirror
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
67887903
编写于
5月 07, 2020
作者:
T
Tom Rini
浏览文件
操作
浏览文件
下载
差异文件
Merge branch '2020-05-07-atheros-phy-improvements'
上级
69bf66ad
8737c65f
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
345 addition
and
53 deletion
+345
-53
doc/device-tree-bindings/net/phy/atheros.txt
doc/device-tree-bindings/net/phy/atheros.txt
+35
-0
drivers/net/phy/atheros.c
drivers/net/phy/atheros.c
+297
-53
include/dt-bindings/net/qca-ar803x.h
include/dt-bindings/net/qca-ar803x.h
+13
-0
未找到文件。
doc/device-tree-bindings/net/phy/atheros.txt
0 → 100644
浏览文件 @
67887903
* Qualcomm Atheros PHY Device Tree binding
Required properties:
- reg: PHY address
Optional properties:
- qca,clk-out-frequency: Clock frequency of the CLK_25M pin in Hz.
Either 25000000, 50000000, 62500000 or 125000000.
- qca,clk-out-strength: Clock output buffer driver strength.
Supported values are defined in dt-bindings/net/qca-ar803x.h
- qca,keep-pll-enabled: Keep the PLL running if no link is present.
Don't go into hibernation mode.
Only supported on the AR8031/AR8033.
- vddio-supply: RGMII I/O voltage regulator
Only supported on the AR8031/AR8033.
Optional subnodes:
- vddio-regulator: Initial data for the VDDIO regulator, as covered
doc/device-tree-bindings/regulator/regulator.txt
Example:
#include <dt-bindings/net/qca-ar803x.h>
ethernet-phy@0 {
reg = <0>;
qca-clk-out-frequency = <125000000>;
qca,keep-pll-enabled;
vddio-supply = <&vddio>;
vddio: vddio-regulator {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
};
drivers/net/phy/atheros.c
浏览文件 @
67887903
...
...
@@ -4,85 +4,329 @@
*
* Copyright 2011, 2013 Freescale Semiconductor, Inc.
* author Andy Fleming
* Copyright (c) 2019 Michael Walle <michael@walle.cc>
*/
#include <common.h>
#include <phy.h>
#include <dm/device_compat.h>
#include <linux/bitfield.h>
#include <dt-bindings/net/qca-ar803x.h>
#define AR803x_PHY_DEBUG_ADDR_REG 0x1d
#define AR803x_PHY_DEBUG_DATA_REG 0x1e
/* Debug registers */
#define AR803x_DEBUG_REG_0 0x0
#define AR803x_RGMII_RX_CLK_DLY BIT(15)
#define AR803x_DEBUG_REG_5 0x5
#define AR803x_RGMII_TX_CLK_DLY
0x100
#define AR803x_RGMII_TX_CLK_DLY
BIT(8)
#define AR803x_DEBUG_REG_0 0x0
#define AR803x_RGMII_RX_CLK_DLY 0x8000
#define AR803x_DEBUG_REG_1F 0x1f
#define AR803x_PLL_ON BIT(2)
#define AR803x_RGMII_1V8 BIT(3)
/* CLK_25M register is at MMD 7, address 0x8016 */
#define AR803x_CLK_25M_SEL_REG 0x8016
#define AR803x_CLK_25M_MASK GENMASK(4, 2)
#define AR803x_CLK_25M_25MHZ_XTAL 0
#define AR803x_CLK_25M_25MHZ_DSP 1
#define AR803x_CLK_25M_50MHZ_PLL 2
#define AR803x_CLK_25M_50MHZ_DSP 3
#define AR803x_CLK_25M_62_5MHZ_PLL 4
#define AR803x_CLK_25M_62_5MHZ_DSP 5
#define AR803x_CLK_25M_125MHZ_PLL 6
#define AR803x_CLK_25M_125MHZ_DSP 7
#define AR8035_CLK_25M_MASK GENMASK(4, 3)
#define AR803x_CLK_25M_DR_MASK GENMASK(8, 7)
#define AR803x_CLK_25M_DR_FULL 0
#define AR803x_CLK_25M_DR_HALF 1
#define AR803x_CLK_25M_DR_QUARTER 2
#define AR8021_PHY_ID 0x004dd040
#define AR8031_PHY_ID 0x004dd074
#define AR8035_PHY_ID 0x004dd072
struct
ar803x_priv
{
int
flags
;
#define AR803x_FLAG_KEEP_PLL_ENABLED BIT(0)
/* don't turn off internal PLL */
#define AR803x_FLAG_RGMII_1V8 BIT(1)
/* use 1.8V RGMII I/O voltage */
u16
clk_25m_reg
;
u16
clk_25m_mask
;
};
static
int
ar803x_debug_reg_read
(
struct
phy_device
*
phydev
,
u16
reg
)
{
int
ret
;
ret
=
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
AR803x_PHY_DEBUG_ADDR_REG
,
reg
);
if
(
ret
<
0
)
return
ret
;
return
phy_read
(
phydev
,
MDIO_DEVAD_NONE
,
AR803x_PHY_DEBUG_DATA_REG
);
}
static
int
ar803x_debug_reg_mask
(
struct
phy_device
*
phydev
,
u16
reg
,
u16
clear
,
u16
set
)
{
int
val
;
val
=
ar803x_debug_reg_read
(
phydev
,
reg
);
if
(
val
<
0
)
return
val
;
val
&=
0xffff
;
val
&=
~
clear
;
val
|=
set
;
return
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
AR803x_PHY_DEBUG_DATA_REG
,
val
);
}
static
int
ar803x_enable_rx_delay
(
struct
phy_device
*
phydev
,
bool
on
)
{
u16
clear
=
0
,
set
=
0
;
if
(
on
)
set
=
AR803x_RGMII_RX_CLK_DLY
;
else
clear
=
AR803x_RGMII_RX_CLK_DLY
;
return
ar803x_debug_reg_mask
(
phydev
,
AR803x_DEBUG_REG_0
,
clear
,
set
);
}
static
int
ar803x_enable_tx_delay
(
struct
phy_device
*
phydev
,
bool
on
)
{
u16
clear
=
0
,
set
=
0
;
if
(
on
)
set
=
AR803x_RGMII_TX_CLK_DLY
;
else
clear
=
AR803x_RGMII_TX_CLK_DLY
;
return
ar803x_debug_reg_mask
(
phydev
,
AR803x_DEBUG_REG_5
,
clear
,
set
);
}
static
int
ar8021_config
(
struct
phy_device
*
phydev
)
{
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x00
,
0x1200
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1d
,
0x05
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1e
,
0x3D47
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
MII_BMCR
,
BMCR_ANENABLE
|
BMCR_ANRESTART
);
ar803x_enable_tx_delay
(
phydev
,
true
);
phydev
->
supported
=
phydev
->
drv
->
features
;
return
0
;
}
static
int
ar803
1
_config
(
struct
phy_device
*
phydev
)
static
int
ar803
x_delay
_config
(
struct
phy_device
*
phydev
)
{
int
ret
;
if
(
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_TXID
||
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_ID
)
{
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
AR803x_PHY_DEBUG_ADDR_REG
,
AR803x_DEBUG_REG_5
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
AR803x_PHY_DEBUG_DATA_REG
,
AR803x_RGMII_TX_CLK_DLY
);
}
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_ID
)
ret
=
ar803x_enable_tx_delay
(
phydev
,
true
);
else
ret
=
ar803x_enable_tx_delay
(
phydev
,
false
);
if
(
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_RXID
||
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_ID
)
{
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
AR803x_PHY_DEBUG_ADDR_REG
,
AR803x_DEBUG_REG_0
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
AR803x_PHY_DEBUG_DATA_REG
,
AR803x_RGMII_RX_CLK_DLY
);
}
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_ID
)
ret
=
ar803x_enable_rx_delay
(
phydev
,
true
);
else
ret
=
ar803x_enable_rx_delay
(
phydev
,
false
);
phydev
->
supported
=
phydev
->
drv
->
features
;
return
ret
;
}
genphy_config_aneg
(
phydev
);
genphy_restart_aneg
(
phydev
);
static
int
ar803x_regs_config
(
struct
phy_device
*
phydev
)
{
struct
ar803x_priv
*
priv
=
phydev
->
priv
;
u16
set
=
0
,
clear
=
0
;
int
val
;
int
ret
;
/* no configuration available */
if
(
!
priv
)
return
0
;
/*
* Only supported on the AR8031, AR8035 has strappings for the PLL mode
* as well as the RGMII voltage.
*/
if
(
phydev
->
drv
->
uid
==
AR8031_PHY_ID
)
{
if
(
priv
->
flags
&
AR803x_FLAG_KEEP_PLL_ENABLED
)
set
|=
AR803x_PLL_ON
;
else
clear
|=
AR803x_PLL_ON
;
if
(
priv
->
flags
&
AR803x_FLAG_RGMII_1V8
)
set
|=
AR803x_RGMII_1V8
;
else
clear
|=
AR803x_RGMII_1V8
;
ret
=
ar803x_debug_reg_mask
(
phydev
,
AR803x_DEBUG_REG_1F
,
clear
,
set
);
if
(
ret
<
0
)
return
ret
;
}
/* save the write access if the mask is empty */
if
(
priv
->
clk_25m_mask
)
{
val
=
phy_read_mmd
(
phydev
,
MDIO_MMD_AN
,
AR803x_CLK_25M_SEL_REG
);
if
(
val
<
0
)
return
val
;
val
&=
~
priv
->
clk_25m_mask
;
val
|=
priv
->
clk_25m_reg
;
ret
=
phy_write_mmd
(
phydev
,
MDIO_MMD_AN
,
AR803x_CLK_25M_SEL_REG
,
val
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
static
int
ar803
5_config
(
struct
phy_device
*
phydev
)
static
int
ar803
x_of_init
(
struct
phy_device
*
phydev
)
{
int
regval
;
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0xd
,
0x0007
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0xe
,
0x8016
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0xd
,
0x4007
);
regval
=
phy_read
(
phydev
,
MDIO_DEVAD_NONE
,
0xe
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0xe
,
(
regval
|
0x0018
));
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1d
,
0x05
);
regval
=
phy_read
(
phydev
,
MDIO_DEVAD_NONE
,
0x1e
);
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1e
,
(
regval
|
0x0100
));
if
((
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_ID
)
||
(
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_TXID
))
{
/* select debug reg 5 */
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1D
,
0x5
);
/* enable tx delay */
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1E
,
0x0100
);
#if defined(CONFIG_DM_ETH)
struct
ar803x_priv
*
priv
;
ofnode
node
,
vddio_reg_node
;
u32
strength
,
freq
,
min_uV
,
max_uV
;
int
sel
;
node
=
phy_get_ofnode
(
phydev
);
if
(
!
ofnode_valid
(
node
))
return
-
EINVAL
;
priv
=
malloc
(
sizeof
(
*
priv
));
if
(
!
priv
)
return
-
ENOMEM
;
memset
(
priv
,
0
,
sizeof
(
*
priv
));
phydev
->
priv
=
priv
;
debug
(
"%s: found PHY node: %s
\n
"
,
__func__
,
ofnode_get_name
(
node
));
if
(
ofnode_read_bool
(
node
,
"qca,keep-pll-enabled"
))
priv
->
flags
|=
AR803x_FLAG_KEEP_PLL_ENABLED
;
/*
* We can't use the regulator framework because the regulator is
* a subnode of the PHY. So just read the two properties we are
* interested in.
*/
vddio_reg_node
=
ofnode_find_subnode
(
node
,
"vddio-regulator"
);
if
(
ofnode_valid
(
vddio_reg_node
))
{
min_uV
=
ofnode_read_u32_default
(
vddio_reg_node
,
"regulator-min-microvolt"
,
0
);
max_uV
=
ofnode_read_u32_default
(
vddio_reg_node
,
"regulator-max-microvolt"
,
0
);
if
(
min_uV
!=
max_uV
)
{
free
(
priv
);
return
-
EINVAL
;
}
switch
(
min_uV
)
{
case
1500000
:
break
;
case
1800000
:
priv
->
flags
|=
AR803x_FLAG_RGMII_1V8
;
break
;
default:
free
(
priv
);
return
-
EINVAL
;
}
}
/*
* Get the CLK_25M frequency from the device tree. Only XTAL and PLL
* sources are supported right now. There is also the possibilty to use
* the DSP as frequency reference, this is used for synchronous
* ethernet.
*/
if
(
!
ofnode_read_u32
(
node
,
"qca,clk-out-frequency"
,
&
freq
))
{
switch
(
freq
)
{
case
25000000
:
sel
=
AR803x_CLK_25M_25MHZ_XTAL
;
break
;
case
50000000
:
sel
=
AR803x_CLK_25M_50MHZ_PLL
;
break
;
case
62500000
:
sel
=
AR803x_CLK_25M_62_5MHZ_PLL
;
break
;
case
125000000
:
sel
=
AR803x_CLK_25M_125MHZ_PLL
;
break
;
default:
dev_err
(
phydev
->
dev
,
"invalid qca,clk-out-frequency
\n
"
);
free
(
priv
);
return
-
EINVAL
;
}
priv
->
clk_25m_mask
|=
AR803x_CLK_25M_MASK
;
priv
->
clk_25m_reg
|=
FIELD_PREP
(
AR803x_CLK_25M_MASK
,
sel
);
/*
* Fixup for the AR8035 which only has two bits. The two
* remaining bits map to the same frequencies.
*/
if
(
phydev
->
drv
->
uid
==
AR8035_PHY_ID
)
{
u16
clear
=
AR803x_CLK_25M_MASK
&
AR8035_CLK_25M_MASK
;
if
((
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_ID
)
||
(
phydev
->
interface
==
PHY_INTERFACE_MODE_RGMII_RXID
))
{
/* select debug reg 0 */
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1D
,
0x0
);
/* enable rx delay */
phy_write
(
phydev
,
MDIO_DEVAD_NONE
,
0x1E
,
0x8000
);
priv
->
clk_25m_mask
&=
~
clear
;
priv
->
clk_25m_reg
&=
~
clear
;
}
}
if
(
phydev
->
drv
->
uid
==
AR8031_PHY_ID
&&
!
ofnode_read_u32
(
node
,
"qca,clk-out-strength"
,
&
strength
))
{
switch
(
strength
)
{
case
AR803X_STRENGTH_FULL
:
sel
=
AR803x_CLK_25M_DR_FULL
;
break
;
case
AR803X_STRENGTH_HALF
:
sel
=
AR803x_CLK_25M_DR_HALF
;
break
;
case
AR803X_STRENGTH_QUARTER
:
sel
=
AR803x_CLK_25M_DR_QUARTER
;
break
;
default:
dev_err
(
phydev
->
dev
,
"invalid qca,clk-out-strength
\n
"
);
free
(
priv
);
return
-
EINVAL
;
}
priv
->
clk_25m_mask
|=
AR803x_CLK_25M_DR_MASK
;
priv
->
clk_25m_reg
|=
FIELD_PREP
(
AR803x_CLK_25M_DR_MASK
,
sel
);
}
debug
(
"%s: flags=%x clk_25m_reg=%04x clk_25m_mask=%04x
\n
"
,
__func__
,
priv
->
flags
,
priv
->
clk_25m_reg
,
priv
->
clk_25m_mask
);
#endif
return
0
;
}
static
int
ar803x_config
(
struct
phy_device
*
phydev
)
{
int
ret
;
ret
=
ar803x_of_init
(
phydev
);
if
(
ret
<
0
)
return
ret
;
ret
=
ar803x_delay_config
(
phydev
);
if
(
ret
<
0
)
return
ret
;
ret
=
ar803x_regs_config
(
phydev
);
if
(
ret
<
0
)
return
ret
;
phydev
->
supported
=
phydev
->
drv
->
features
;
genphy_config_aneg
(
phydev
);
...
...
@@ -93,8 +337,8 @@ static int ar8035_config(struct phy_device *phydev)
static
struct
phy_driver
AR8021_driver
=
{
.
name
=
"AR8021"
,
.
uid
=
0x4dd040
,
.
mask
=
0x
4
ffff0
,
.
uid
=
AR8021_PHY_ID
,
.
mask
=
0x
fff
ffff0
,
.
features
=
PHY_GBIT_FEATURES
,
.
config
=
ar8021_config
,
.
startup
=
genphy_startup
,
...
...
@@ -103,20 +347,20 @@ static struct phy_driver AR8021_driver = {
static
struct
phy_driver
AR8031_driver
=
{
.
name
=
"AR8031/AR8033"
,
.
uid
=
0x4dd074
,
.
uid
=
AR8031_PHY_ID
,
.
mask
=
0xffffffef
,
.
features
=
PHY_GBIT_FEATURES
,
.
config
=
ar803
1
_config
,
.
config
=
ar803
x
_config
,
.
startup
=
genphy_startup
,
.
shutdown
=
genphy_shutdown
,
};
static
struct
phy_driver
AR8035_driver
=
{
.
name
=
"AR8035"
,
.
uid
=
0x4dd072
,
.
uid
=
AR8035_PHY_ID
,
.
mask
=
0xffffffef
,
.
features
=
PHY_GBIT_FEATURES
,
.
config
=
ar803
5
_config
,
.
config
=
ar803
x
_config
,
.
startup
=
genphy_startup
,
.
shutdown
=
genphy_shutdown
,
};
...
...
include/dt-bindings/net/qca-ar803x.h
0 → 100644
浏览文件 @
67887903
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Device Tree constants for the Qualcomm Atheros AR803x PHYs
*/
#ifndef _DT_BINDINGS_QCA_AR803X_H
#define _DT_BINDINGS_QCA_AR803X_H
#define AR803X_STRENGTH_FULL 0
#define AR803X_STRENGTH_HALF 1
#define AR803X_STRENGTH_QUARTER 2
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录