]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - drivers/net/phy/micrel.c
OMAP3: igep00x0: Fix boot hang and add support for status LED.
[karo-tx-uboot.git] / drivers / net / phy / micrel.c
1 /*
2  * Micrel PHY drivers
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  *
6  * Copyright 2010-2011 Freescale Semiconductor, Inc.
7  * author Andy Fleming
8  * (C) 2012 NetModule AG, David Andrey, added KSZ9031
9  */
10 #include <config.h>
11 #include <common.h>
12 #include <micrel.h>
13 #include <phy.h>
14
15 static 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
25 #ifndef CONFIG_PHY_MICREL_KSZ9021
26 /*
27  * I can't believe Micrel used the exact same part number
28  * for the KSZ9021. Shame Micrel, Shame!
29  */
30 static 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 };
39 #endif
40
41
42 /*
43  * 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
52 static 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 }
71
72 #ifdef CONFIG_PHY_MICREL_KSZ9021
73 /*
74  * KSZ9021
75  */
76
77 /* PHY Registers */
78 #define MII_KSZ9021_EXTENDED_CTRL       0x0b
79 #define MII_KSZ9021_EXTENDED_DATAW      0x0c
80 #define MII_KSZ9021_EXTENDED_DATAR      0x0d
81
82 #define CTRL1000_PREFER_MASTER          (1 << 10)
83 #define CTRL1000_CONFIG_MASTER          (1 << 11)
84 #define CTRL1000_MANUAL_CONFIG          (1 << 12)
85
86 int 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
95 int 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
102
103 static 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
109 static 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
115 /* Micrel ksz9021 */
116 static 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
138 static struct phy_driver ksz9021_driver = {
139         .name = "Micrel ksz9021",
140         .uid  = 0x221610,
141         .mask = 0xfffff0,
142         .features = PHY_GBIT_FEATURES,
143         .config = &ksz9021_config,
144         .startup = &ksz90xx_startup,
145         .shutdown = &genphy_shutdown,
146         .writeext = &ksz9021_phy_extwrite,
147         .readext = &ksz9021_phy_extread,
148 };
149 #endif
150
151 /**
152  * KSZ9031
153  */
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*/
159 int 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
176 int 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
188 static 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
195 static 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
203 static struct phy_driver ksz9031_driver = {
204         .name = "Micrel ksz9031",
205         .uid  = 0x221620,
206         .mask = 0xfffff0,
207         .features = PHY_GBIT_FEATURES,
208         .config   = &genphy_config,
209         .startup  = &ksz90xx_startup,
210         .shutdown = &genphy_shutdown,
211         .writeext = &ksz9031_phy_extwrite,
212         .readext = &ksz9031_phy_extread,
213 };
214
215 int phy_micrel_init(void)
216 {
217         phy_register(&KSZ804_driver);
218 #ifdef CONFIG_PHY_MICREL_KSZ9021
219         phy_register(&ksz9021_driver);
220 #else
221         phy_register(&KS8721_driver);
222 #endif
223         phy_register(&ksz9031_driver);
224         return 0;
225 }