blob: 507b9a368be72e6d24fea6da9f169cbc2c4cb579 [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
Troy Kiskycc5f5522012-06-28 08:00:28 +000025#ifndef CONFIG_PHY_MICREL_KSZ9021
26/*
27 * I can't believe Micrel used the exact same part number
Pavel Machek58ec63d2014-09-09 14:26:51 +020028 * for the KSZ9021. Shame Micrel, Shame!
Troy Kiskycc5f5522012-06-28 08:00:28 +000029 */
Vladimir Zapolskiyfcc0c752011-12-06 02:47:57 +000030static struct phy_driver KS8721_driver = {
31 .name = "Micrel KS8721BL",
32 .uid = 0x221610,
33 .mask = 0xfffff0,
34 .features = PHY_BASIC_FEATURES,
35 .config = &genphy_config,
36 .startup = &genphy_startup,
37 .shutdown = &genphy_shutdown,
38};
Troy Kiskycc5f5522012-06-28 08:00:28 +000039#endif
Vladimir Zapolskiyfcc0c752011-12-06 02:47:57 +000040
David Andrey62d7dba2013-02-06 22:18:37 +010041
Pavel Machek58ec63d2014-09-09 14:26:51 +020042/*
David Andrey62d7dba2013-02-06 22:18:37 +010043 * KSZ9021 - KSZ9031 common
44 */
45
46#define MII_KSZ90xx_PHY_CTL 0x1f
47#define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6)
48#define MIIM_KSZ90xx_PHYCTL_100 (1 << 5)
49#define MIIM_KSZ90xx_PHYCTL_10 (1 << 4)
50#define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3)
51
52static int ksz90xx_startup(struct phy_device *phydev)
53{
54 unsigned phy_ctl;
55 genphy_update_link(phydev);
56 phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
57
58 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
59 phydev->duplex = DUPLEX_FULL;
60 else
61 phydev->duplex = DUPLEX_HALF;
62
63 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
64 phydev->speed = SPEED_1000;
65 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
66 phydev->speed = SPEED_100;
67 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
68 phydev->speed = SPEED_10;
69 return 0;
70}
David Andrey62d7dba2013-02-06 22:18:37 +010071
Pavel Machek58ec63d2014-09-09 14:26:51 +020072#ifdef CONFIG_PHY_MICREL_KSZ9021
David Andrey62d7dba2013-02-06 22:18:37 +010073/*
74 * KSZ9021
75 */
76
77/* PHY Registers */
Troy Kisky8682aba2012-02-07 14:08:48 +000078#define MII_KSZ9021_EXTENDED_CTRL 0x0b
79#define MII_KSZ9021_EXTENDED_DATAW 0x0c
80#define MII_KSZ9021_EXTENDED_DATAR 0x0d
Troy Kisky8682aba2012-02-07 14:08:48 +000081
82#define CTRL1000_PREFER_MASTER (1 << 10)
83#define CTRL1000_CONFIG_MASTER (1 << 11)
84#define CTRL1000_MANUAL_CONFIG (1 << 12)
85
86int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
87{
88 /* extended registers */
89 phy_write(phydev, MDIO_DEVAD_NONE,
90 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
91 return phy_write(phydev, MDIO_DEVAD_NONE,
92 MII_KSZ9021_EXTENDED_DATAW, val);
93}
94
95int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
96{
97 /* extended registers */
98 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
99 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
100}
101
Stefano Babic9ced16f2013-09-02 15:42:31 +0200102
103static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
104 int regnum)
105{
106 return ksz9021_phy_extended_read(phydev, regnum);
107}
108
109static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
110 int devaddr, int regnum, u16 val)
111{
112 return ksz9021_phy_extended_write(phydev, regnum, val);
113}
114
Troy Kisky8682aba2012-02-07 14:08:48 +0000115/* Micrel ksz9021 */
116static int ksz9021_config(struct phy_device *phydev)
117{
118 unsigned ctrl1000 = 0;
119 const unsigned master = CTRL1000_PREFER_MASTER |
120 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
121 unsigned features = phydev->drv->features;
122
123 if (getenv("disable_giga"))
124 features &= ~(SUPPORTED_1000baseT_Half |
125 SUPPORTED_1000baseT_Full);
126 /* force master mode for 1000BaseT due to chip errata */
127 if (features & SUPPORTED_1000baseT_Half)
128 ctrl1000 |= ADVERTISE_1000HALF | master;
129 if (features & SUPPORTED_1000baseT_Full)
130 ctrl1000 |= ADVERTISE_1000FULL | master;
131 phydev->advertising = phydev->supported = features;
132 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
133 genphy_config_aneg(phydev);
134 genphy_restart_aneg(phydev);
135 return 0;
136}
137
Troy Kisky8682aba2012-02-07 14:08:48 +0000138static struct phy_driver ksz9021_driver = {
139 .name = "Micrel ksz9021",
140 .uid = 0x221610,
141 .mask = 0xfffff0,
142 .features = PHY_GBIT_FEATURES,
143 .config = &ksz9021_config,
David Andrey62d7dba2013-02-06 22:18:37 +0100144 .startup = &ksz90xx_startup,
Troy Kisky8682aba2012-02-07 14:08:48 +0000145 .shutdown = &genphy_shutdown,
Stefano Babic9ced16f2013-09-02 15:42:31 +0200146 .writeext = &ksz9021_phy_extwrite,
147 .readext = &ksz9021_phy_extread,
Troy Kisky8682aba2012-02-07 14:08:48 +0000148};
Troy Kiskycc5f5522012-06-28 08:00:28 +0000149#endif
Troy Kisky8682aba2012-02-07 14:08:48 +0000150
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200151/**
David Andrey62d7dba2013-02-06 22:18:37 +0100152 * KSZ9031
153 */
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200154/* PHY Registers */
155#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
156#define MII_KSZ9031_MMD_REG_DATA 0x0e
157
158/* Accessors to extended registers*/
159int ksz9031_phy_extended_write(struct phy_device *phydev,
160 int devaddr, int regnum, u16 mode, u16 val)
161{
162 /*select register addr for mmd*/
163 phy_write(phydev, MDIO_DEVAD_NONE,
164 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
165 /*select register for mmd*/
166 phy_write(phydev, MDIO_DEVAD_NONE,
167 MII_KSZ9031_MMD_REG_DATA, regnum);
168 /*setup mode*/
169 phy_write(phydev, MDIO_DEVAD_NONE,
170 MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
171 /*write the value*/
172 return phy_write(phydev, MDIO_DEVAD_NONE,
173 MII_KSZ9031_MMD_REG_DATA, val);
174}
175
176int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
177 int regnum, u16 mode)
178{
179 phy_write(phydev, MDIO_DEVAD_NONE,
180 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
181 phy_write(phydev, MDIO_DEVAD_NONE,
182 MII_KSZ9031_MMD_REG_DATA, regnum);
183 phy_write(phydev, MDIO_DEVAD_NONE,
184 MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
185 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
186}
187
Stefano Babic9ced16f2013-09-02 15:42:31 +0200188static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
189 int regnum)
190{
191 return ksz9031_phy_extended_read(phydev, devaddr, regnum,
192 MII_KSZ9031_MOD_DATA_NO_POST_INC);
193};
194
195static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
196 int devaddr, int regnum, u16 val)
197{
198 return ksz9031_phy_extended_write(phydev, devaddr, regnum,
199 MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
200};
201
202
David Andrey62d7dba2013-02-06 22:18:37 +0100203static struct phy_driver ksz9031_driver = {
204 .name = "Micrel ksz9031",
205 .uid = 0x221620,
Stefano Babice8194d52013-09-02 15:42:29 +0200206 .mask = 0xfffff0,
David Andrey62d7dba2013-02-06 22:18:37 +0100207 .features = PHY_GBIT_FEATURES,
208 .config = &genphy_config,
209 .startup = &ksz90xx_startup,
210 .shutdown = &genphy_shutdown,
Stefano Babic9ced16f2013-09-02 15:42:31 +0200211 .writeext = &ksz9031_phy_extwrite,
212 .readext = &ksz9031_phy_extread,
David Andrey62d7dba2013-02-06 22:18:37 +0100213};
214
Andy Fleming9082eea2011-04-07 21:56:05 -0500215int phy_micrel_init(void)
216{
217 phy_register(&KSZ804_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000218#ifdef CONFIG_PHY_MICREL_KSZ9021
Troy Kisky8682aba2012-02-07 14:08:48 +0000219 phy_register(&ksz9021_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000220#else
221 phy_register(&KS8721_driver);
222#endif
David Andrey62d7dba2013-02-06 22:18:37 +0100223 phy_register(&ksz9031_driver);
Andy Fleming9082eea2011-04-07 21:56:05 -0500224 return 0;
225}