]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/phy/micrel.c
Merge branch 'master' of git://git.denx.de/u-boot-microblaze
[karo-tx-uboot.git] / drivers / net / phy / micrel.c
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
21  *
22  */
23 #include <config.h>
24 #include <common.h>
25 #include <micrel.h>
26 #include <phy.h>
27
28 static struct phy_driver KSZ804_driver = {
29         .name = "Micrel KSZ804",
30         .uid = 0x221510,
31         .mask = 0xfffff0,
32         .features = PHY_BASIC_FEATURES,
33         .config = &genphy_config,
34         .startup = &genphy_startup,
35         .shutdown = &genphy_shutdown,
36 };
37
38 #ifndef CONFIG_PHY_MICREL_KSZ9021
39 /*
40  * I can't believe Micrel used the exact same part number
41  * for the KSZ9021
42  * Shame Micrel, Shame!!!!!
43  */
44 static struct phy_driver KS8721_driver = {
45         .name = "Micrel KS8721BL",
46         .uid = 0x221610,
47         .mask = 0xfffff0,
48         .features = PHY_BASIC_FEATURES,
49         .config = &genphy_config,
50         .startup = &genphy_startup,
51         .shutdown = &genphy_shutdown,
52 };
53 #endif
54
55 #ifdef CONFIG_PHY_MICREL_KSZ9021
56 /* ksz9021 PHY Registers */
57 #define MII_KSZ9021_EXTENDED_CTRL       0x0b
58 #define MII_KSZ9021_EXTENDED_DATAW      0x0c
59 #define MII_KSZ9021_EXTENDED_DATAR      0x0d
60 #define MII_KSZ9021_PHY_CTL             0x1f
61 #define MIIM_KSZ9021_PHYCTL_1000        (1 << 6)
62 #define MIIM_KSZ9021_PHYCTL_100         (1 << 5)
63 #define MIIM_KSZ9021_PHYCTL_10          (1 << 4)
64 #define MIIM_KSZ9021_PHYCTL_DUPLEX      (1 << 3)
65
66 #define CTRL1000_PREFER_MASTER          (1 << 10)
67 #define CTRL1000_CONFIG_MASTER          (1 << 11)
68 #define CTRL1000_MANUAL_CONFIG          (1 << 12)
69
70 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
71 {
72         /* extended registers */
73         phy_write(phydev, MDIO_DEVAD_NONE,
74                 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
75         return phy_write(phydev, MDIO_DEVAD_NONE,
76                 MII_KSZ9021_EXTENDED_DATAW, val);
77 }
78
79 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
80 {
81         /* extended registers */
82         phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
83         return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
84 }
85
86 /* Micrel ksz9021 */
87 static int ksz9021_config(struct phy_device *phydev)
88 {
89         unsigned ctrl1000 = 0;
90         const unsigned master = CTRL1000_PREFER_MASTER |
91                         CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
92         unsigned features = phydev->drv->features;
93
94         if (getenv("disable_giga"))
95                 features &= ~(SUPPORTED_1000baseT_Half |
96                                 SUPPORTED_1000baseT_Full);
97         /* force master mode for 1000BaseT due to chip errata */
98         if (features & SUPPORTED_1000baseT_Half)
99                 ctrl1000 |= ADVERTISE_1000HALF | master;
100         if (features & SUPPORTED_1000baseT_Full)
101                 ctrl1000 |= ADVERTISE_1000FULL | master;
102         phydev->advertising = phydev->supported = features;
103         phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
104         genphy_config_aneg(phydev);
105         genphy_restart_aneg(phydev);
106         return 0;
107 }
108
109 static int ksz9021_startup(struct phy_device *phydev)
110 {
111         unsigned phy_ctl;
112         genphy_update_link(phydev);
113         phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_PHY_CTL);
114
115         if (phy_ctl & MIIM_KSZ9021_PHYCTL_DUPLEX)
116                 phydev->duplex = DUPLEX_FULL;
117         else
118                 phydev->duplex = DUPLEX_HALF;
119
120         if (phy_ctl & MIIM_KSZ9021_PHYCTL_1000)
121                 phydev->speed = SPEED_1000;
122         else if (phy_ctl & MIIM_KSZ9021_PHYCTL_100)
123                 phydev->speed = SPEED_100;
124         else if (phy_ctl & MIIM_KSZ9021_PHYCTL_10)
125                 phydev->speed = SPEED_10;
126         return 0;
127 }
128
129 static struct phy_driver ksz9021_driver = {
130         .name = "Micrel ksz9021",
131         .uid  = 0x221610,
132         .mask = 0xfffff0,
133         .features = PHY_GBIT_FEATURES,
134         .config = &ksz9021_config,
135         .startup = &ksz9021_startup,
136         .shutdown = &genphy_shutdown,
137 };
138 #endif
139
140 int phy_micrel_init(void)
141 {
142         phy_register(&KSZ804_driver);
143 #ifdef CONFIG_PHY_MICREL_KSZ9021
144         phy_register(&ksz9021_driver);
145 #else
146         phy_register(&KS8721_driver);
147 #endif
148         return 0;
149 }