blob: 5d7e3be52e095cf06977b7f5ee68b575f2a284f4 [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
28 * for the KSZ9021
29 * Shame Micrel, Shame!!!!!
30 */
Vladimir Zapolskiyfcc0c752011-12-06 02:47:57 +000031static struct phy_driver KS8721_driver = {
32 .name = "Micrel KS8721BL",
33 .uid = 0x221610,
34 .mask = 0xfffff0,
35 .features = PHY_BASIC_FEATURES,
36 .config = &genphy_config,
37 .startup = &genphy_startup,
38 .shutdown = &genphy_shutdown,
39};
Troy Kiskycc5f5522012-06-28 08:00:28 +000040#endif
Vladimir Zapolskiyfcc0c752011-12-06 02:47:57 +000041
David Andrey62d7dba2013-02-06 22:18:37 +010042
43/**
44 * KSZ9021 - KSZ9031 common
45 */
46
47#define MII_KSZ90xx_PHY_CTL 0x1f
48#define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6)
49#define MIIM_KSZ90xx_PHYCTL_100 (1 << 5)
50#define MIIM_KSZ90xx_PHYCTL_10 (1 << 4)
51#define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3)
52
53static int ksz90xx_startup(struct phy_device *phydev)
54{
55 unsigned phy_ctl;
56 genphy_update_link(phydev);
57 phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
58
59 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
60 phydev->duplex = DUPLEX_FULL;
61 else
62 phydev->duplex = DUPLEX_HALF;
63
64 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
65 phydev->speed = SPEED_1000;
66 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
67 phydev->speed = SPEED_100;
68 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
69 phydev->speed = SPEED_10;
70 return 0;
71}
Troy Kiskycc5f5522012-06-28 08:00:28 +000072#ifdef CONFIG_PHY_MICREL_KSZ9021
David Andrey62d7dba2013-02-06 22:18:37 +010073
74/*
75 * KSZ9021
76 */
77
78/* PHY Registers */
Troy Kisky8682aba2012-02-07 14:08:48 +000079#define MII_KSZ9021_EXTENDED_CTRL 0x0b
80#define MII_KSZ9021_EXTENDED_DATAW 0x0c
81#define MII_KSZ9021_EXTENDED_DATAR 0x0d
Troy Kisky8682aba2012-02-07 14:08:48 +000082
83#define CTRL1000_PREFER_MASTER (1 << 10)
84#define CTRL1000_CONFIG_MASTER (1 << 11)
85#define CTRL1000_MANUAL_CONFIG (1 << 12)
86
87int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
88{
89 /* extended registers */
90 phy_write(phydev, MDIO_DEVAD_NONE,
91 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
92 return phy_write(phydev, MDIO_DEVAD_NONE,
93 MII_KSZ9021_EXTENDED_DATAW, val);
94}
95
96int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
97{
98 /* extended registers */
99 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
100 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
101}
102
Stefano Babic9ced16f2013-09-02 15:42:31 +0200103
104static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
105 int regnum)
106{
107 return ksz9021_phy_extended_read(phydev, regnum);
108}
109
110static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
111 int devaddr, int regnum, u16 val)
112{
113 return ksz9021_phy_extended_write(phydev, regnum, val);
114}
115
Troy Kisky8682aba2012-02-07 14:08:48 +0000116/* Micrel ksz9021 */
117static int ksz9021_config(struct phy_device *phydev)
118{
119 unsigned ctrl1000 = 0;
120 const unsigned master = CTRL1000_PREFER_MASTER |
121 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
122 unsigned features = phydev->drv->features;
123
124 if (getenv("disable_giga"))
125 features &= ~(SUPPORTED_1000baseT_Half |
126 SUPPORTED_1000baseT_Full);
127 /* force master mode for 1000BaseT due to chip errata */
128 if (features & SUPPORTED_1000baseT_Half)
129 ctrl1000 |= ADVERTISE_1000HALF | master;
130 if (features & SUPPORTED_1000baseT_Full)
131 ctrl1000 |= ADVERTISE_1000FULL | master;
132 phydev->advertising = phydev->supported = features;
133 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
134 genphy_config_aneg(phydev);
135 genphy_restart_aneg(phydev);
136 return 0;
137}
138
Troy Kisky8682aba2012-02-07 14:08:48 +0000139static struct phy_driver ksz9021_driver = {
140 .name = "Micrel ksz9021",
141 .uid = 0x221610,
142 .mask = 0xfffff0,
143 .features = PHY_GBIT_FEATURES,
144 .config = &ksz9021_config,
David Andrey62d7dba2013-02-06 22:18:37 +0100145 .startup = &ksz90xx_startup,
Troy Kisky8682aba2012-02-07 14:08:48 +0000146 .shutdown = &genphy_shutdown,
Stefano Babic9ced16f2013-09-02 15:42:31 +0200147 .writeext = &ksz9021_phy_extwrite,
148 .readext = &ksz9021_phy_extread,
Troy Kisky8682aba2012-02-07 14:08:48 +0000149};
Troy Kiskycc5f5522012-06-28 08:00:28 +0000150#endif
Troy Kisky8682aba2012-02-07 14:08:48 +0000151
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200152/**
David Andrey62d7dba2013-02-06 22:18:37 +0100153 * KSZ9031
154 */
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200155/* PHY Registers */
156#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
157#define MII_KSZ9031_MMD_REG_DATA 0x0e
158
159/* Accessors to extended registers*/
160int ksz9031_phy_extended_write(struct phy_device *phydev,
161 int devaddr, int regnum, u16 mode, u16 val)
162{
163 /*select register addr for mmd*/
164 phy_write(phydev, MDIO_DEVAD_NONE,
165 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
166 /*select register for mmd*/
167 phy_write(phydev, MDIO_DEVAD_NONE,
168 MII_KSZ9031_MMD_REG_DATA, regnum);
169 /*setup mode*/
170 phy_write(phydev, MDIO_DEVAD_NONE,
171 MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
172 /*write the value*/
173 return phy_write(phydev, MDIO_DEVAD_NONE,
174 MII_KSZ9031_MMD_REG_DATA, val);
175}
176
177int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
178 int regnum, u16 mode)
179{
180 phy_write(phydev, MDIO_DEVAD_NONE,
181 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
182 phy_write(phydev, MDIO_DEVAD_NONE,
183 MII_KSZ9031_MMD_REG_DATA, regnum);
184 phy_write(phydev, MDIO_DEVAD_NONE,
185 MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
186 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
187}
188
Stefano Babic9ced16f2013-09-02 15:42:31 +0200189static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
190 int regnum)
191{
192 return ksz9031_phy_extended_read(phydev, devaddr, regnum,
193 MII_KSZ9031_MOD_DATA_NO_POST_INC);
194};
195
196static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
197 int devaddr, int regnum, u16 val)
198{
199 return ksz9031_phy_extended_write(phydev, devaddr, regnum,
200 MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
201};
202
203
David Andrey62d7dba2013-02-06 22:18:37 +0100204static struct phy_driver ksz9031_driver = {
205 .name = "Micrel ksz9031",
206 .uid = 0x221620,
Stefano Babice8194d52013-09-02 15:42:29 +0200207 .mask = 0xfffff0,
David Andrey62d7dba2013-02-06 22:18:37 +0100208 .features = PHY_GBIT_FEATURES,
209 .config = &genphy_config,
210 .startup = &ksz90xx_startup,
211 .shutdown = &genphy_shutdown,
Stefano Babic9ced16f2013-09-02 15:42:31 +0200212 .writeext = &ksz9031_phy_extwrite,
213 .readext = &ksz9031_phy_extread,
David Andrey62d7dba2013-02-06 22:18:37 +0100214};
215
Andy Fleming9082eea2011-04-07 21:56:05 -0500216int phy_micrel_init(void)
217{
218 phy_register(&KSZ804_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000219#ifdef CONFIG_PHY_MICREL_KSZ9021
Troy Kisky8682aba2012-02-07 14:08:48 +0000220 phy_register(&ksz9021_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000221#else
222 phy_register(&KS8721_driver);
223#endif
David Andrey62d7dba2013-02-06 22:18:37 +0100224 phy_register(&ksz9031_driver);
Andy Fleming9082eea2011-04-07 21:56:05 -0500225 return 0;
226}