blob: 5e49666bbb34e1a12d748db7a8c1107828311f78 [file] [log] [blame]
Andy Fleming9082eea2011-04-07 21:56:05 -05001/*
2 * Micrel PHY drivers
3 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Andy Fleming9082eea2011-04-07 21:56:05 -05005 *
6 * Copyright 2010-2011 Freescale Semiconductor, Inc.
7 * author Andy Fleming
David Andrey62d7dba2013-02-06 22:18:37 +01008 * (C) 2012 NetModule AG, David Andrey, added KSZ9031
Andy Fleming9082eea2011-04-07 21:56:05 -05009 */
Troy Kisky8682aba2012-02-07 14:08:48 +000010#include <config.h>
11#include <common.h>
12#include <micrel.h>
Andy Fleming9082eea2011-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
Sylvain Lemieux6617f872015-09-09 16:29:51 -040025static struct phy_driver KSZ8031_driver = {
26 .name = "Micrel KSZ8021/KSZ8031",
27 .uid = 0x221550,
28 .mask = 0xfffff0,
29 .features = PHY_BASIC_FEATURES,
30 .config = &genphy_config,
31 .startup = &genphy_startup,
32 .shutdown = &genphy_shutdown,
33};
34
Sylvain Rochet4f485152015-10-07 22:54:22 +020035/**
36 * KSZ8051
37 */
38#define MII_KSZ8051_PHY_OMSO 0x16
39#define MII_KSZ8051_PHY_OMSO_NAND_TREE_ON (1 << 5)
40
41static int ksz8051_config(struct phy_device *phydev)
42{
43 unsigned val;
44
45 /* Disable NAND-tree */
46 val = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ8051_PHY_OMSO);
47 val &= ~MII_KSZ8051_PHY_OMSO_NAND_TREE_ON;
48 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ8051_PHY_OMSO, val);
49
50 return genphy_config(phydev);
51}
52
53static struct phy_driver KSZ8051_driver = {
54 .name = "Micrel KSZ8051",
55 .uid = 0x221550,
56 .mask = 0xfffff0,
57 .features = PHY_BASIC_FEATURES,
58 .config = &ksz8051_config,
59 .startup = &genphy_startup,
60 .shutdown = &genphy_shutdown,
61};
62
Luca Elleroc6a40f62015-03-24 11:32:24 +010063static struct phy_driver KSZ8081_driver = {
64 .name = "Micrel KSZ8081",
65 .uid = 0x221560,
66 .mask = 0xfffff0,
67 .features = PHY_BASIC_FEATURES,
68 .config = &genphy_config,
69 .startup = &genphy_startup,
70 .shutdown = &genphy_shutdown,
71};
72
Philippe De Muyterb7a5b082014-02-19 17:21:59 +010073/**
74 * KSZ8895
75 */
76
77static unsigned short smireg_to_phy(unsigned short reg)
78{
79 return ((reg & 0xc0) >> 3) + 0x06 + ((reg & 0x20) >> 5);
80}
81
82static unsigned short smireg_to_reg(unsigned short reg)
83{
84 return reg & 0x1F;
85}
86
87static void ksz8895_write_smireg(struct phy_device *phydev, int smireg, int val)
88{
89 phydev->bus->write(phydev->bus, smireg_to_phy(smireg), MDIO_DEVAD_NONE,
90 smireg_to_reg(smireg), val);
91}
92
93#if 0
94static int ksz8895_read_smireg(struct phy_device *phydev, int smireg)
95{
96 return phydev->bus->read(phydev->bus, smireg_to_phy(smireg),
97 MDIO_DEVAD_NONE, smireg_to_reg(smireg));
98}
99#endif
100
101int ksz8895_config(struct phy_device *phydev)
102{
103 /* we are connected directly to the switch without
104 * dedicated PHY. SCONF1 == 001 */
105 phydev->link = 1;
106 phydev->duplex = DUPLEX_FULL;
107 phydev->speed = SPEED_100;
108
109 /* Force the switch to start */
110 ksz8895_write_smireg(phydev, 1, 1);
111
112 return 0;
113}
114
115static int ksz8895_startup(struct phy_device *phydev)
116{
117 return 0;
118}
119
120static struct phy_driver ksz8895_driver = {
121 .name = "Micrel KSZ8895/KSZ8864",
122 .uid = 0x221450,
123 .mask = 0xffffe1,
124 .features = PHY_BASIC_FEATURES,
125 .config = &ksz8895_config,
126 .startup = &ksz8895_startup,
127 .shutdown = &genphy_shutdown,
128};
129
Troy Kiskycc5f5522012-06-28 08:00:28 +0000130#ifndef CONFIG_PHY_MICREL_KSZ9021
131/*
132 * I can't believe Micrel used the exact same part number
Pavel Machek58ec63d2014-09-09 14:26:51 +0200133 * for the KSZ9021. Shame Micrel, Shame!
Troy Kiskycc5f5522012-06-28 08:00:28 +0000134 */
Vladimir Zapolskiyfcc0c752011-12-06 02:47:57 +0000135static struct phy_driver KS8721_driver = {
136 .name = "Micrel KS8721BL",
137 .uid = 0x221610,
138 .mask = 0xfffff0,
139 .features = PHY_BASIC_FEATURES,
140 .config = &genphy_config,
141 .startup = &genphy_startup,
142 .shutdown = &genphy_shutdown,
143};
Troy Kiskycc5f5522012-06-28 08:00:28 +0000144#endif
Vladimir Zapolskiyfcc0c752011-12-06 02:47:57 +0000145
David Andrey62d7dba2013-02-06 22:18:37 +0100146
Pavel Machek58ec63d2014-09-09 14:26:51 +0200147/*
David Andrey62d7dba2013-02-06 22:18:37 +0100148 * KSZ9021 - KSZ9031 common
149 */
150
151#define MII_KSZ90xx_PHY_CTL 0x1f
152#define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6)
153#define MIIM_KSZ90xx_PHYCTL_100 (1 << 5)
154#define MIIM_KSZ90xx_PHYCTL_10 (1 << 4)
155#define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3)
156
157static int ksz90xx_startup(struct phy_device *phydev)
158{
159 unsigned phy_ctl;
160 genphy_update_link(phydev);
161 phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
162
163 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
164 phydev->duplex = DUPLEX_FULL;
165 else
166 phydev->duplex = DUPLEX_HALF;
167
168 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
169 phydev->speed = SPEED_1000;
170 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
171 phydev->speed = SPEED_100;
172 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
173 phydev->speed = SPEED_10;
174 return 0;
175}
David Andrey62d7dba2013-02-06 22:18:37 +0100176
Pavel Machek58ec63d2014-09-09 14:26:51 +0200177#ifdef CONFIG_PHY_MICREL_KSZ9021
David Andrey62d7dba2013-02-06 22:18:37 +0100178/*
179 * KSZ9021
180 */
181
182/* PHY Registers */
Troy Kisky8682aba2012-02-07 14:08:48 +0000183#define MII_KSZ9021_EXTENDED_CTRL 0x0b
184#define MII_KSZ9021_EXTENDED_DATAW 0x0c
185#define MII_KSZ9021_EXTENDED_DATAR 0x0d
Troy Kisky8682aba2012-02-07 14:08:48 +0000186
187#define CTRL1000_PREFER_MASTER (1 << 10)
188#define CTRL1000_CONFIG_MASTER (1 << 11)
189#define CTRL1000_MANUAL_CONFIG (1 << 12)
190
191int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
192{
193 /* extended registers */
194 phy_write(phydev, MDIO_DEVAD_NONE,
195 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
196 return phy_write(phydev, MDIO_DEVAD_NONE,
197 MII_KSZ9021_EXTENDED_DATAW, val);
198}
199
200int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
201{
202 /* extended registers */
203 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
204 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
205}
206
Stefano Babic9ced16f2013-09-02 15:42:31 +0200207
208static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
209 int regnum)
210{
211 return ksz9021_phy_extended_read(phydev, regnum);
212}
213
214static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
215 int devaddr, int regnum, u16 val)
216{
217 return ksz9021_phy_extended_write(phydev, regnum, val);
218}
219
Troy Kisky8682aba2012-02-07 14:08:48 +0000220/* Micrel ksz9021 */
221static int ksz9021_config(struct phy_device *phydev)
222{
223 unsigned ctrl1000 = 0;
224 const unsigned master = CTRL1000_PREFER_MASTER |
225 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
226 unsigned features = phydev->drv->features;
227
228 if (getenv("disable_giga"))
229 features &= ~(SUPPORTED_1000baseT_Half |
230 SUPPORTED_1000baseT_Full);
231 /* force master mode for 1000BaseT due to chip errata */
232 if (features & SUPPORTED_1000baseT_Half)
233 ctrl1000 |= ADVERTISE_1000HALF | master;
234 if (features & SUPPORTED_1000baseT_Full)
235 ctrl1000 |= ADVERTISE_1000FULL | master;
236 phydev->advertising = phydev->supported = features;
237 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
238 genphy_config_aneg(phydev);
239 genphy_restart_aneg(phydev);
240 return 0;
241}
242
Troy Kisky8682aba2012-02-07 14:08:48 +0000243static struct phy_driver ksz9021_driver = {
244 .name = "Micrel ksz9021",
245 .uid = 0x221610,
246 .mask = 0xfffff0,
247 .features = PHY_GBIT_FEATURES,
248 .config = &ksz9021_config,
David Andrey62d7dba2013-02-06 22:18:37 +0100249 .startup = &ksz90xx_startup,
Troy Kisky8682aba2012-02-07 14:08:48 +0000250 .shutdown = &genphy_shutdown,
Stefano Babic9ced16f2013-09-02 15:42:31 +0200251 .writeext = &ksz9021_phy_extwrite,
252 .readext = &ksz9021_phy_extread,
Troy Kisky8682aba2012-02-07 14:08:48 +0000253};
Troy Kiskycc5f5522012-06-28 08:00:28 +0000254#endif
Troy Kisky8682aba2012-02-07 14:08:48 +0000255
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200256/**
David Andrey62d7dba2013-02-06 22:18:37 +0100257 * KSZ9031
258 */
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200259/* PHY Registers */
260#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
261#define MII_KSZ9031_MMD_REG_DATA 0x0e
262
263/* Accessors to extended registers*/
264int ksz9031_phy_extended_write(struct phy_device *phydev,
265 int devaddr, int regnum, u16 mode, u16 val)
266{
267 /*select register addr for mmd*/
268 phy_write(phydev, MDIO_DEVAD_NONE,
269 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
270 /*select register for mmd*/
271 phy_write(phydev, MDIO_DEVAD_NONE,
272 MII_KSZ9031_MMD_REG_DATA, regnum);
273 /*setup mode*/
274 phy_write(phydev, MDIO_DEVAD_NONE,
275 MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
276 /*write the value*/
277 return phy_write(phydev, MDIO_DEVAD_NONE,
278 MII_KSZ9031_MMD_REG_DATA, val);
279}
280
281int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
282 int regnum, u16 mode)
283{
284 phy_write(phydev, MDIO_DEVAD_NONE,
285 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
286 phy_write(phydev, MDIO_DEVAD_NONE,
287 MII_KSZ9031_MMD_REG_DATA, regnum);
288 phy_write(phydev, MDIO_DEVAD_NONE,
289 MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
290 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
291}
292
Stefano Babic9ced16f2013-09-02 15:42:31 +0200293static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
294 int regnum)
295{
296 return ksz9031_phy_extended_read(phydev, devaddr, regnum,
297 MII_KSZ9031_MOD_DATA_NO_POST_INC);
298};
299
300static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
301 int devaddr, int regnum, u16 val)
302{
303 return ksz9031_phy_extended_write(phydev, devaddr, regnum,
304 MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
305};
306
307
David Andrey62d7dba2013-02-06 22:18:37 +0100308static struct phy_driver ksz9031_driver = {
309 .name = "Micrel ksz9031",
310 .uid = 0x221620,
Stefano Babice8194d52013-09-02 15:42:29 +0200311 .mask = 0xfffff0,
David Andrey62d7dba2013-02-06 22:18:37 +0100312 .features = PHY_GBIT_FEATURES,
313 .config = &genphy_config,
314 .startup = &ksz90xx_startup,
315 .shutdown = &genphy_shutdown,
Stefano Babic9ced16f2013-09-02 15:42:31 +0200316 .writeext = &ksz9031_phy_extwrite,
317 .readext = &ksz9031_phy_extread,
David Andrey62d7dba2013-02-06 22:18:37 +0100318};
319
Andy Fleming9082eea2011-04-07 21:56:05 -0500320int phy_micrel_init(void)
321{
322 phy_register(&KSZ804_driver);
Sylvain Lemieux6617f872015-09-09 16:29:51 -0400323 phy_register(&KSZ8031_driver);
Sylvain Rochet4f485152015-10-07 22:54:22 +0200324 phy_register(&KSZ8051_driver);
Luca Elleroc6a40f62015-03-24 11:32:24 +0100325 phy_register(&KSZ8081_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000326#ifdef CONFIG_PHY_MICREL_KSZ9021
Troy Kisky8682aba2012-02-07 14:08:48 +0000327 phy_register(&ksz9021_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000328#else
329 phy_register(&KS8721_driver);
330#endif
David Andrey62d7dba2013-02-06 22:18:37 +0100331 phy_register(&ksz9031_driver);
Philippe De Muyterb7a5b082014-02-19 17:21:59 +0100332 phy_register(&ksz8895_driver);
Andy Fleming9082eea2011-04-07 21:56:05 -0500333 return 0;
334}