blob: a7450f832646d6d3e85a4f3026659611c83f0245 [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
103/* Micrel ksz9021 */
104static int ksz9021_config(struct phy_device *phydev)
105{
106 unsigned ctrl1000 = 0;
107 const unsigned master = CTRL1000_PREFER_MASTER |
108 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
109 unsigned features = phydev->drv->features;
110
111 if (getenv("disable_giga"))
112 features &= ~(SUPPORTED_1000baseT_Half |
113 SUPPORTED_1000baseT_Full);
114 /* force master mode for 1000BaseT due to chip errata */
115 if (features & SUPPORTED_1000baseT_Half)
116 ctrl1000 |= ADVERTISE_1000HALF | master;
117 if (features & SUPPORTED_1000baseT_Full)
118 ctrl1000 |= ADVERTISE_1000FULL | master;
119 phydev->advertising = phydev->supported = features;
120 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
121 genphy_config_aneg(phydev);
122 genphy_restart_aneg(phydev);
123 return 0;
124}
125
Troy Kisky8682aba2012-02-07 14:08:48 +0000126static struct phy_driver ksz9021_driver = {
127 .name = "Micrel ksz9021",
128 .uid = 0x221610,
129 .mask = 0xfffff0,
130 .features = PHY_GBIT_FEATURES,
131 .config = &ksz9021_config,
David Andrey62d7dba2013-02-06 22:18:37 +0100132 .startup = &ksz90xx_startup,
Troy Kisky8682aba2012-02-07 14:08:48 +0000133 .shutdown = &genphy_shutdown,
134};
Troy Kiskycc5f5522012-06-28 08:00:28 +0000135#endif
Troy Kisky8682aba2012-02-07 14:08:48 +0000136
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200137/**
David Andrey62d7dba2013-02-06 22:18:37 +0100138 * KSZ9031
139 */
SARTRE Leo42a7cb52013-04-30 16:57:25 +0200140/* PHY Registers */
141#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
142#define MII_KSZ9031_MMD_REG_DATA 0x0e
143
144/* Accessors to extended registers*/
145int ksz9031_phy_extended_write(struct phy_device *phydev,
146 int devaddr, int regnum, u16 mode, u16 val)
147{
148 /*select register addr for mmd*/
149 phy_write(phydev, MDIO_DEVAD_NONE,
150 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
151 /*select register for mmd*/
152 phy_write(phydev, MDIO_DEVAD_NONE,
153 MII_KSZ9031_MMD_REG_DATA, regnum);
154 /*setup mode*/
155 phy_write(phydev, MDIO_DEVAD_NONE,
156 MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
157 /*write the value*/
158 return phy_write(phydev, MDIO_DEVAD_NONE,
159 MII_KSZ9031_MMD_REG_DATA, val);
160}
161
162int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
163 int regnum, u16 mode)
164{
165 phy_write(phydev, MDIO_DEVAD_NONE,
166 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
167 phy_write(phydev, MDIO_DEVAD_NONE,
168 MII_KSZ9031_MMD_REG_DATA, regnum);
169 phy_write(phydev, MDIO_DEVAD_NONE,
170 MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
171 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
172}
173
David Andrey62d7dba2013-02-06 22:18:37 +0100174static struct phy_driver ksz9031_driver = {
175 .name = "Micrel ksz9031",
176 .uid = 0x221620,
177 .mask = 0xfffffe,
178 .features = PHY_GBIT_FEATURES,
179 .config = &genphy_config,
180 .startup = &ksz90xx_startup,
181 .shutdown = &genphy_shutdown,
182};
183
Andy Fleming9082eea2011-04-07 21:56:05 -0500184int phy_micrel_init(void)
185{
186 phy_register(&KSZ804_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000187#ifdef CONFIG_PHY_MICREL_KSZ9021
Troy Kisky8682aba2012-02-07 14:08:48 +0000188 phy_register(&ksz9021_driver);
Troy Kiskycc5f5522012-06-28 08:00:28 +0000189#else
190 phy_register(&KS8721_driver);
191#endif
David Andrey62d7dba2013-02-06 22:18:37 +0100192 phy_register(&ksz9031_driver);
Andy Fleming9082eea2011-04-07 21:56:05 -0500193 return 0;
194}