blob: 1815b2900ddb2ad1ec80cb9d521bda1ddaa323de [file] [log] [blame]
Andy Fleming60ca78b2011-04-07 21:56:05 -05001/*
2 * Micrel PHY drivers
3 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Andy Fleming60ca78b2011-04-07 21:56:05 -05005 *
6 * Copyright 2010-2011 Freescale Semiconductor, Inc.
7 * author Andy Fleming
David Andreyf0d83c42013-02-06 22:18:37 +01008 * (C) 2012 NetModule AG, David Andrey, added KSZ9031
Andy Fleming60ca78b2011-04-07 21:56:05 -05009 */
Troy Kisky80b6b092012-02-07 14:08:48 +000010#include <config.h>
11#include <common.h>
12#include <micrel.h>
Andy Fleming60ca78b2011-04-07 21:56:05 -050013#include <phy.h>
14
15static struct phy_driver KSZ804_driver = {
16 .name = "Micrel KSZ804",
17 .uid = 0x221510,
18 .mask = 0xfffff0,
19 .features = PHY_BASIC_FEATURES,
20 .config = &genphy_config,
21 .startup = &genphy_startup,
22 .shutdown = &genphy_shutdown,
23};
24
Philippe De Muyter2616b212014-02-19 17:21:59 +010025/**
26 * KSZ8895
27 */
28
29static unsigned short smireg_to_phy(unsigned short reg)
30{
31 return ((reg & 0xc0) >> 3) + 0x06 + ((reg & 0x20) >> 5);
32}
33
34static unsigned short smireg_to_reg(unsigned short reg)
35{
36 return reg & 0x1F;
37}
38
39static void ksz8895_write_smireg(struct phy_device *phydev, int smireg, int val)
40{
41 phydev->bus->write(phydev->bus, smireg_to_phy(smireg), MDIO_DEVAD_NONE,
42 smireg_to_reg(smireg), val);
43}
44
45#if 0
46static int ksz8895_read_smireg(struct phy_device *phydev, int smireg)
47{
48 return phydev->bus->read(phydev->bus, smireg_to_phy(smireg),
49 MDIO_DEVAD_NONE, smireg_to_reg(smireg));
50}
51#endif
52
53int ksz8895_config(struct phy_device *phydev)
54{
55 /* we are connected directly to the switch without
56 * dedicated PHY. SCONF1 == 001 */
57 phydev->link = 1;
58 phydev->duplex = DUPLEX_FULL;
59 phydev->speed = SPEED_100;
60
61 /* Force the switch to start */
62 ksz8895_write_smireg(phydev, 1, 1);
63
64 return 0;
65}
66
67static int ksz8895_startup(struct phy_device *phydev)
68{
69 return 0;
70}
71
72static struct phy_driver ksz8895_driver = {
73 .name = "Micrel KSZ8895/KSZ8864",
74 .uid = 0x221450,
75 .mask = 0xffffe1,
76 .features = PHY_BASIC_FEATURES,
77 .config = &ksz8895_config,
78 .startup = &ksz8895_startup,
79 .shutdown = &genphy_shutdown,
80};
81
Troy Kiskyb4fd97f2012-06-28 08:00:28 +000082#ifndef CONFIG_PHY_MICREL_KSZ9021
83/*
84 * I can't believe Micrel used the exact same part number
Pavel Machek5f022112014-09-09 14:26:51 +020085 * for the KSZ9021. Shame Micrel, Shame!
Troy Kiskyb4fd97f2012-06-28 08:00:28 +000086 */
Vladimir Zapolskiya4baa582011-12-06 02:47:57 +000087static struct phy_driver KS8721_driver = {
88 .name = "Micrel KS8721BL",
89 .uid = 0x221610,
90 .mask = 0xfffff0,
91 .features = PHY_BASIC_FEATURES,
92 .config = &genphy_config,
93 .startup = &genphy_startup,
94 .shutdown = &genphy_shutdown,
95};
Troy Kiskyb4fd97f2012-06-28 08:00:28 +000096#endif
Vladimir Zapolskiya4baa582011-12-06 02:47:57 +000097
David Andreyf0d83c42013-02-06 22:18:37 +010098
Pavel Machek5f022112014-09-09 14:26:51 +020099/*
David Andreyf0d83c42013-02-06 22:18:37 +0100100 * KSZ9021 - KSZ9031 common
101 */
102
103#define MII_KSZ90xx_PHY_CTL 0x1f
104#define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6)
105#define MIIM_KSZ90xx_PHYCTL_100 (1 << 5)
106#define MIIM_KSZ90xx_PHYCTL_10 (1 << 4)
107#define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3)
108
109static int ksz90xx_startup(struct phy_device *phydev)
110{
111 unsigned phy_ctl;
112 genphy_update_link(phydev);
113 phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
114
115 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
116 phydev->duplex = DUPLEX_FULL;
117 else
118 phydev->duplex = DUPLEX_HALF;
119
120 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
121 phydev->speed = SPEED_1000;
122 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
123 phydev->speed = SPEED_100;
124 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
125 phydev->speed = SPEED_10;
126 return 0;
127}
David Andreyf0d83c42013-02-06 22:18:37 +0100128
Pavel Machek5f022112014-09-09 14:26:51 +0200129#ifdef CONFIG_PHY_MICREL_KSZ9021
David Andreyf0d83c42013-02-06 22:18:37 +0100130/*
131 * KSZ9021
132 */
133
134/* PHY Registers */
Troy Kisky80b6b092012-02-07 14:08:48 +0000135#define MII_KSZ9021_EXTENDED_CTRL 0x0b
136#define MII_KSZ9021_EXTENDED_DATAW 0x0c
137#define MII_KSZ9021_EXTENDED_DATAR 0x0d
Troy Kisky80b6b092012-02-07 14:08:48 +0000138
139#define CTRL1000_PREFER_MASTER (1 << 10)
140#define CTRL1000_CONFIG_MASTER (1 << 11)
141#define CTRL1000_MANUAL_CONFIG (1 << 12)
142
143int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
144{
145 /* extended registers */
146 phy_write(phydev, MDIO_DEVAD_NONE,
147 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
148 return phy_write(phydev, MDIO_DEVAD_NONE,
149 MII_KSZ9021_EXTENDED_DATAW, val);
150}
151
152int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
153{
154 /* extended registers */
155 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
156 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
157}
158
Stefano Babica8aa2992013-09-02 15:42:31 +0200159
160static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
161 int regnum)
162{
163 return ksz9021_phy_extended_read(phydev, regnum);
164}
165
166static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
167 int devaddr, int regnum, u16 val)
168{
169 return ksz9021_phy_extended_write(phydev, regnum, val);
170}
171
Troy Kisky80b6b092012-02-07 14:08:48 +0000172/* Micrel ksz9021 */
173static int ksz9021_config(struct phy_device *phydev)
174{
175 unsigned ctrl1000 = 0;
176 const unsigned master = CTRL1000_PREFER_MASTER |
177 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
178 unsigned features = phydev->drv->features;
179
180 if (getenv("disable_giga"))
181 features &= ~(SUPPORTED_1000baseT_Half |
182 SUPPORTED_1000baseT_Full);
183 /* force master mode for 1000BaseT due to chip errata */
184 if (features & SUPPORTED_1000baseT_Half)
185 ctrl1000 |= ADVERTISE_1000HALF | master;
186 if (features & SUPPORTED_1000baseT_Full)
187 ctrl1000 |= ADVERTISE_1000FULL | master;
188 phydev->advertising = phydev->supported = features;
189 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
190 genphy_config_aneg(phydev);
191 genphy_restart_aneg(phydev);
192 return 0;
193}
194
Troy Kisky80b6b092012-02-07 14:08:48 +0000195static struct phy_driver ksz9021_driver = {
196 .name = "Micrel ksz9021",
197 .uid = 0x221610,
198 .mask = 0xfffff0,
199 .features = PHY_GBIT_FEATURES,
200 .config = &ksz9021_config,
David Andreyf0d83c42013-02-06 22:18:37 +0100201 .startup = &ksz90xx_startup,
Troy Kisky80b6b092012-02-07 14:08:48 +0000202 .shutdown = &genphy_shutdown,
Stefano Babica8aa2992013-09-02 15:42:31 +0200203 .writeext = &ksz9021_phy_extwrite,
204 .readext = &ksz9021_phy_extread,
Troy Kisky80b6b092012-02-07 14:08:48 +0000205};
Troy Kiskyb4fd97f2012-06-28 08:00:28 +0000206#endif
Troy Kisky80b6b092012-02-07 14:08:48 +0000207
SARTRE Leoeaf68ac2013-04-30 16:57:25 +0200208/**
David Andreyf0d83c42013-02-06 22:18:37 +0100209 * KSZ9031
210 */
SARTRE Leoeaf68ac2013-04-30 16:57:25 +0200211/* PHY Registers */
212#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
213#define MII_KSZ9031_MMD_REG_DATA 0x0e
214
215/* Accessors to extended registers*/
216int ksz9031_phy_extended_write(struct phy_device *phydev,
217 int devaddr, int regnum, u16 mode, u16 val)
218{
219 /*select register addr for mmd*/
220 phy_write(phydev, MDIO_DEVAD_NONE,
221 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
222 /*select register for mmd*/
223 phy_write(phydev, MDIO_DEVAD_NONE,
224 MII_KSZ9031_MMD_REG_DATA, regnum);
225 /*setup mode*/
226 phy_write(phydev, MDIO_DEVAD_NONE,
227 MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
228 /*write the value*/
229 return phy_write(phydev, MDIO_DEVAD_NONE,
230 MII_KSZ9031_MMD_REG_DATA, val);
231}
232
233int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
234 int regnum, u16 mode)
235{
236 phy_write(phydev, MDIO_DEVAD_NONE,
237 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
238 phy_write(phydev, MDIO_DEVAD_NONE,
239 MII_KSZ9031_MMD_REG_DATA, regnum);
240 phy_write(phydev, MDIO_DEVAD_NONE,
241 MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
242 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
243}
244
Stefano Babica8aa2992013-09-02 15:42:31 +0200245static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
246 int regnum)
247{
248 return ksz9031_phy_extended_read(phydev, devaddr, regnum,
249 MII_KSZ9031_MOD_DATA_NO_POST_INC);
250};
251
252static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
253 int devaddr, int regnum, u16 val)
254{
255 return ksz9031_phy_extended_write(phydev, devaddr, regnum,
256 MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
257};
258
259
David Andreyf0d83c42013-02-06 22:18:37 +0100260static struct phy_driver ksz9031_driver = {
261 .name = "Micrel ksz9031",
262 .uid = 0x221620,
Stefano Babicd9e36ad2013-09-02 15:42:29 +0200263 .mask = 0xfffff0,
David Andreyf0d83c42013-02-06 22:18:37 +0100264 .features = PHY_GBIT_FEATURES,
265 .config = &genphy_config,
266 .startup = &ksz90xx_startup,
267 .shutdown = &genphy_shutdown,
Stefano Babica8aa2992013-09-02 15:42:31 +0200268 .writeext = &ksz9031_phy_extwrite,
269 .readext = &ksz9031_phy_extread,
David Andreyf0d83c42013-02-06 22:18:37 +0100270};
271
Andy Fleming60ca78b2011-04-07 21:56:05 -0500272int phy_micrel_init(void)
273{
274 phy_register(&KSZ804_driver);
Troy Kiskyb4fd97f2012-06-28 08:00:28 +0000275#ifdef CONFIG_PHY_MICREL_KSZ9021
Troy Kisky80b6b092012-02-07 14:08:48 +0000276 phy_register(&ksz9021_driver);
Troy Kiskyb4fd97f2012-06-28 08:00:28 +0000277#else
278 phy_register(&KS8721_driver);
279#endif
David Andreyf0d83c42013-02-06 22:18:37 +0100280 phy_register(&ksz9031_driver);
Philippe De Muyter2616b212014-02-19 17:21:59 +0100281 phy_register(&ksz8895_driver);
Andy Fleming60ca78b2011-04-07 21:56:05 -0500282 return 0;
283}