blob: 22035c2496d563a18309e5af453223aa09968579 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Andy Fleming60ca78b2011-04-07 21:56:05 -05002/*
3 * Atheros PHY drivers
4 *
Xie Xiaobodcc307e2013-04-10 16:23:39 +08005 * Copyright 2011, 2013 Freescale Semiconductor, Inc.
Andy Fleming60ca78b2011-04-07 21:56:05 -05006 * author Andy Fleming
Andy Fleming60ca78b2011-04-07 21:56:05 -05007 */
Joe Hershberger14b48122018-07-25 12:59:22 -05008#include <common.h>
Andy Fleming60ca78b2011-04-07 21:56:05 -05009#include <phy.h>
10
Mugunthan V N3e4537d2016-10-13 19:33:36 +053011#define AR803x_PHY_DEBUG_ADDR_REG 0x1d
12#define AR803x_PHY_DEBUG_DATA_REG 0x1e
13
14#define AR803x_DEBUG_REG_5 0x5
Vladimir Oltean23d8b892020-05-07 00:11:49 +020015#define AR803x_RGMII_TX_CLK_DLY BIT(8)
Mugunthan V N3e4537d2016-10-13 19:33:36 +053016
17#define AR803x_DEBUG_REG_0 0x0
Vladimir Oltean23d8b892020-05-07 00:11:49 +020018#define AR803x_RGMII_RX_CLK_DLY BIT(15)
19
Vladimir Oltean3e7330e2020-05-07 00:11:50 +020020/* CLK_25M register is at MMD 7, address 0x8016 */
21#define AR803x_CLK_25M_SEL_REG 0x8016
22/* AR8035: Select frequency on CLK_25M pin through bits 4:3 */
23#define AR8035_CLK_25M_FREQ_25M (0 | 0)
24#define AR8035_CLK_25M_FREQ_50M (0 | BIT(3))
25#define AR8035_CLK_25M_FREQ_62M (BIT(4) | 0)
26#define AR8035_CLK_25M_FREQ_125M (BIT(4) | BIT(3))
27#define AR8035_CLK_25M_MASK GENMASK(4, 3)
28
Michael Walle69a107e2020-05-07 00:11:54 +020029#define AR8021_PHY_ID 0x004dd040
30#define AR8031_PHY_ID 0x004dd074
31#define AR8035_PHY_ID 0x004dd072
32
Michael Wallefb4a4652020-05-07 00:11:55 +020033static int ar803x_debug_reg_read(struct phy_device *phydev, u16 reg)
Vladimir Oltean23d8b892020-05-07 00:11:49 +020034{
Michael Wallefb4a4652020-05-07 00:11:55 +020035 int ret;
Vladimir Oltean23d8b892020-05-07 00:11:49 +020036
Michael Wallefb4a4652020-05-07 00:11:55 +020037 ret = phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG,
38 reg);
39 if (ret < 0)
40 return ret;
41
42 return phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG);
43}
44
45static int ar803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
46 u16 clear, u16 set)
47{
48 int val;
49
50 val = ar803x_debug_reg_read(phydev, reg);
51 if (val < 0)
52 return val;
53
54 val &= 0xffff;
55 val &= ~clear;
56 val |= set;
57
58 return phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG,
59 val);
60}
61
62static int ar803x_enable_rx_delay(struct phy_device *phydev, bool on)
63{
64 u16 clear = 0, set = 0;
65
Vladimir Oltean23d8b892020-05-07 00:11:49 +020066 if (on)
Michael Wallefb4a4652020-05-07 00:11:55 +020067 set = AR803x_RGMII_RX_CLK_DLY;
Vladimir Oltean23d8b892020-05-07 00:11:49 +020068 else
Michael Wallefb4a4652020-05-07 00:11:55 +020069 clear = AR803x_RGMII_RX_CLK_DLY;
70
71 return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_0, clear, set);
Vladimir Oltean23d8b892020-05-07 00:11:49 +020072}
73
Michael Wallefb4a4652020-05-07 00:11:55 +020074static int ar803x_enable_tx_delay(struct phy_device *phydev, bool on)
Vladimir Oltean23d8b892020-05-07 00:11:49 +020075{
Michael Wallefb4a4652020-05-07 00:11:55 +020076 u16 clear = 0, set = 0;
Vladimir Oltean23d8b892020-05-07 00:11:49 +020077
Vladimir Oltean23d8b892020-05-07 00:11:49 +020078 if (on)
Michael Wallefb4a4652020-05-07 00:11:55 +020079 set = AR803x_RGMII_TX_CLK_DLY;
Vladimir Oltean23d8b892020-05-07 00:11:49 +020080 else
Michael Wallefb4a4652020-05-07 00:11:55 +020081 clear = AR803x_RGMII_TX_CLK_DLY;
82
83 return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_5, clear, set);
Vladimir Oltean23d8b892020-05-07 00:11:49 +020084}
Mugunthan V N3e4537d2016-10-13 19:33:36 +053085
Andy Fleming60ca78b2011-04-07 21:56:05 -050086static int ar8021_config(struct phy_device *phydev)
87{
Vladimir Oltean1e37f752020-05-07 00:11:52 +020088 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
89 BMCR_ANENABLE | BMCR_ANRESTART);
90
91 ar803x_enable_tx_delay(phydev, true);
Andy Fleming60ca78b2011-04-07 21:56:05 -050092
Zhao Qiang04f2ba42013-12-23 15:51:33 +080093 phydev->supported = phydev->drv->features;
Mugunthan V N3e4537d2016-10-13 19:33:36 +053094 return 0;
95}
96
Michael Walle376019a2020-05-07 00:11:56 +020097static int ar803x_delay_config(struct phy_device *phydev)
Mugunthan V N3e4537d2016-10-13 19:33:36 +053098{
Michael Walle376019a2020-05-07 00:11:56 +020099 int ret;
100
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530101 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200102 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
Michael Walle376019a2020-05-07 00:11:56 +0200103 ret = ar803x_enable_tx_delay(phydev, true);
Vladimir Oltean3ccbb4b2020-05-07 00:11:51 +0200104 else
Michael Walle376019a2020-05-07 00:11:56 +0200105 ret = ar803x_enable_tx_delay(phydev, false);
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530106
107 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200108 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
Michael Walle376019a2020-05-07 00:11:56 +0200109 ret = ar803x_enable_rx_delay(phydev, true);
Vladimir Oltean3ccbb4b2020-05-07 00:11:51 +0200110 else
Michael Walle376019a2020-05-07 00:11:56 +0200111 ret = ar803x_enable_rx_delay(phydev, false);
112
113 return ret;
114}
115
116static int ar8031_config(struct phy_device *phydev)
117{
118 int ret;
119
120 ret = ar803x_delay_config(phydev);
121 if (ret < 0)
122 return ret;
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530123
124 phydev->supported = phydev->drv->features;
125
126 genphy_config_aneg(phydev);
127 genphy_restart_aneg(phydev);
128
Andy Fleming60ca78b2011-04-07 21:56:05 -0500129 return 0;
130}
131
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800132static int ar8035_config(struct phy_device *phydev)
133{
Michael Walle376019a2020-05-07 00:11:56 +0200134 int ret;
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800135 int regval;
136
Vladimir Oltean3e7330e2020-05-07 00:11:50 +0200137 /* Configure CLK_25M output clock at 125 MHz */
138 regval = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG);
139 regval &= ~AR8035_CLK_25M_MASK; /* No surprises */
140 regval |= AR8035_CLK_25M_FREQ_125M;
141 phy_write_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG, regval);
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800142
Michael Walle376019a2020-05-07 00:11:56 +0200143 ret = ar803x_delay_config(phydev);
144 if (ret < 0)
145 return ret;
Andrea Merello1e3e19f2016-05-26 18:24:28 +0200146
Xiaobo Xieaa09e682014-04-11 16:03:11 +0800147 phydev->supported = phydev->drv->features;
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800148
Alison Wang5dc3af82016-02-19 15:52:28 +0800149 genphy_config_aneg(phydev);
150 genphy_restart_aneg(phydev);
151
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800152 return 0;
153}
154
Kim Phillips40c2c032012-10-29 13:34:33 +0000155static struct phy_driver AR8021_driver = {
Andy Fleming60ca78b2011-04-07 21:56:05 -0500156 .name = "AR8021",
Michael Walle69a107e2020-05-07 00:11:54 +0200157 .uid = AR8021_PHY_ID,
Michael Wallea5eb6592020-05-07 00:11:53 +0200158 .mask = 0xfffffff0,
Andy Fleming60ca78b2011-04-07 21:56:05 -0500159 .features = PHY_GBIT_FEATURES,
160 .config = ar8021_config,
161 .startup = genphy_startup,
162 .shutdown = genphy_shutdown,
163};
164
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200165static struct phy_driver AR8031_driver = {
Shengzhou Liu76f57c32013-08-08 16:33:35 +0800166 .name = "AR8031/AR8033",
Michael Walle69a107e2020-05-07 00:11:54 +0200167 .uid = AR8031_PHY_ID,
Fabio Estevam2edb6062014-01-03 15:55:59 -0200168 .mask = 0xffffffef,
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200169 .features = PHY_GBIT_FEATURES,
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530170 .config = ar8031_config,
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200171 .startup = genphy_startup,
172 .shutdown = genphy_shutdown,
173};
174
175static struct phy_driver AR8035_driver = {
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800176 .name = "AR8035",
Michael Walle69a107e2020-05-07 00:11:54 +0200177 .uid = AR8035_PHY_ID,
Fabio Estevam2edb6062014-01-03 15:55:59 -0200178 .mask = 0xffffffef,
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800179 .features = PHY_GBIT_FEATURES,
180 .config = ar8035_config,
181 .startup = genphy_startup,
182 .shutdown = genphy_shutdown,
183};
184
Andy Fleming60ca78b2011-04-07 21:56:05 -0500185int phy_atheros_init(void)
186{
187 phy_register(&AR8021_driver);
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200188 phy_register(&AR8031_driver);
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800189 phy_register(&AR8035_driver);
Andy Fleming60ca78b2011-04-07 21:56:05 -0500190
191 return 0;
192}