]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/net/phy/micrel.c
Licenses: introduce SPDX Unique Lincense Identifiers
[people/ms/u-boot.git] / drivers / net / phy / micrel.c
CommitLineData
9082eeac
AF
1/*
2 * Micrel PHY drivers
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17 * MA 02111-1307 USA
18 *
19 * Copyright 2010-2011 Freescale Semiconductor, Inc.
20 * author Andy Fleming
62d7dba7 21 * (C) 2012 NetModule AG, David Andrey, added KSZ9031
9082eeac
AF
22 *
23 */
8682aba7
TK
24#include <config.h>
25#include <common.h>
26#include <micrel.h>
9082eeac
AF
27#include <phy.h>
28
29static struct phy_driver KSZ804_driver = {
30 .name = "Micrel KSZ804",
31 .uid = 0x221510,
32 .mask = 0xfffff0,
33 .features = PHY_BASIC_FEATURES,
34 .config = &genphy_config,
35 .startup = &genphy_startup,
36 .shutdown = &genphy_shutdown,
37};
38
cc5f5522
TK
39#ifndef CONFIG_PHY_MICREL_KSZ9021
40/*
41 * I can't believe Micrel used the exact same part number
42 * for the KSZ9021
43 * Shame Micrel, Shame!!!!!
44 */
fcc0c75d
VZ
45static struct phy_driver KS8721_driver = {
46 .name = "Micrel KS8721BL",
47 .uid = 0x221610,
48 .mask = 0xfffff0,
49 .features = PHY_BASIC_FEATURES,
50 .config = &genphy_config,
51 .startup = &genphy_startup,
52 .shutdown = &genphy_shutdown,
53};
cc5f5522 54#endif
fcc0c75d 55
62d7dba7
DA
56
57/**
58 * KSZ9021 - KSZ9031 common
59 */
60
61#define MII_KSZ90xx_PHY_CTL 0x1f
62#define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6)
63#define MIIM_KSZ90xx_PHYCTL_100 (1 << 5)
64#define MIIM_KSZ90xx_PHYCTL_10 (1 << 4)
65#define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3)
66
67static int ksz90xx_startup(struct phy_device *phydev)
68{
69 unsigned phy_ctl;
70 genphy_update_link(phydev);
71 phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
72
73 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
74 phydev->duplex = DUPLEX_FULL;
75 else
76 phydev->duplex = DUPLEX_HALF;
77
78 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
79 phydev->speed = SPEED_1000;
80 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
81 phydev->speed = SPEED_100;
82 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
83 phydev->speed = SPEED_10;
84 return 0;
85}
cc5f5522 86#ifdef CONFIG_PHY_MICREL_KSZ9021
62d7dba7
DA
87
88/*
89 * KSZ9021
90 */
91
92/* PHY Registers */
8682aba7
TK
93#define MII_KSZ9021_EXTENDED_CTRL 0x0b
94#define MII_KSZ9021_EXTENDED_DATAW 0x0c
95#define MII_KSZ9021_EXTENDED_DATAR 0x0d
8682aba7
TK
96
97#define CTRL1000_PREFER_MASTER (1 << 10)
98#define CTRL1000_CONFIG_MASTER (1 << 11)
99#define CTRL1000_MANUAL_CONFIG (1 << 12)
100
101int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
102{
103 /* extended registers */
104 phy_write(phydev, MDIO_DEVAD_NONE,
105 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
106 return phy_write(phydev, MDIO_DEVAD_NONE,
107 MII_KSZ9021_EXTENDED_DATAW, val);
108}
109
110int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
111{
112 /* extended registers */
113 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
114 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
115}
116
117/* Micrel ksz9021 */
118static int ksz9021_config(struct phy_device *phydev)
119{
120 unsigned ctrl1000 = 0;
121 const unsigned master = CTRL1000_PREFER_MASTER |
122 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
123 unsigned features = phydev->drv->features;
124
125 if (getenv("disable_giga"))
126 features &= ~(SUPPORTED_1000baseT_Half |
127 SUPPORTED_1000baseT_Full);
128 /* force master mode for 1000BaseT due to chip errata */
129 if (features & SUPPORTED_1000baseT_Half)
130 ctrl1000 |= ADVERTISE_1000HALF | master;
131 if (features & SUPPORTED_1000baseT_Full)
132 ctrl1000 |= ADVERTISE_1000FULL | master;
133 phydev->advertising = phydev->supported = features;
134 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
135 genphy_config_aneg(phydev);
136 genphy_restart_aneg(phydev);
137 return 0;
138}
139
8682aba7
TK
140static struct phy_driver ksz9021_driver = {
141 .name = "Micrel ksz9021",
142 .uid = 0x221610,
143 .mask = 0xfffff0,
144 .features = PHY_GBIT_FEATURES,
145 .config = &ksz9021_config,
62d7dba7 146 .startup = &ksz90xx_startup,
8682aba7
TK
147 .shutdown = &genphy_shutdown,
148};
cc5f5522 149#endif
8682aba7 150
42a7cb50 151/**
62d7dba7
DA
152 * KSZ9031
153 */
42a7cb50
SL
154/* 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
62d7dba7
DA
188static struct phy_driver ksz9031_driver = {
189 .name = "Micrel ksz9031",
190 .uid = 0x221620,
191 .mask = 0xfffffe,
192 .features = PHY_GBIT_FEATURES,
193 .config = &genphy_config,
194 .startup = &ksz90xx_startup,
195 .shutdown = &genphy_shutdown,
196};
197
9082eeac
AF
198int phy_micrel_init(void)
199{
200 phy_register(&KSZ804_driver);
cc5f5522 201#ifdef CONFIG_PHY_MICREL_KSZ9021
8682aba7 202 phy_register(&ksz9021_driver);
cc5f5522
TK
203#else
204 phy_register(&KS8721_driver);
205#endif
62d7dba7 206 phy_register(&ksz9031_driver);
9082eeac
AF
207 return 0;
208}