]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/phy/micrel.c
net: phy: micrel: add support for KSZ8895 switch in SMI mode
[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 /**
26  * KSZ8895
27  */
28
29 static unsigned short smireg_to_phy(unsigned short reg)
30 {
31         return ((reg & 0xc0) >> 3) + 0x06 + ((reg & 0x20) >> 5);
32 }
33
34 static unsigned short smireg_to_reg(unsigned short reg)
35 {
36         return reg & 0x1F;
37 }
38
39 static void ksz8895_write_smireg(struct phy_device *phydev, int smireg, int val)
40 {
41         phydev->bus->write(phydev->bus, smireg_to_phy(smireg), MDIO_DEVAD_NONE,
42                                                 smireg_to_reg(smireg), val);
43 }
44
45 #if 0
46 static int ksz8895_read_smireg(struct phy_device *phydev, int smireg)
47 {
48         return phydev->bus->read(phydev->bus, smireg_to_phy(smireg),
49                                         MDIO_DEVAD_NONE, smireg_to_reg(smireg));
50 }
51 #endif
52
53 int ksz8895_config(struct phy_device *phydev)
54 {
55         /* we are connected directly to the switch without
56          * dedicated PHY. SCONF1 == 001 */
57         phydev->link = 1;
58         phydev->duplex = DUPLEX_FULL;
59         phydev->speed = SPEED_100;
60
61         /* Force the switch to start */
62         ksz8895_write_smireg(phydev, 1, 1);
63
64         return 0;
65 }
66
67 static int ksz8895_startup(struct phy_device *phydev)
68 {
69         return 0;
70 }
71
72 static struct phy_driver ksz8895_driver = {
73         .name = "Micrel KSZ8895/KSZ8864",
74         .uid  = 0x221450,
75         .mask = 0xffffe1,
76         .features = PHY_BASIC_FEATURES,
77         .config   = &ksz8895_config,
78         .startup  = &ksz8895_startup,
79         .shutdown = &genphy_shutdown,
80 };
81
82 #ifndef CONFIG_PHY_MICREL_KSZ9021
83 /*
84  * I can't believe Micrel used the exact same part number
85  * for the KSZ9021. Shame Micrel, Shame!
86  */
87 static struct phy_driver KS8721_driver = {
88         .name = "Micrel KS8721BL",
89         .uid = 0x221610,
90         .mask = 0xfffff0,
91         .features = PHY_BASIC_FEATURES,
92         .config = &genphy_config,
93         .startup = &genphy_startup,
94         .shutdown = &genphy_shutdown,
95 };
96 #endif
97
98
99 /*
100  * KSZ9021 - KSZ9031 common
101  */
102
103 #define MII_KSZ90xx_PHY_CTL             0x1f
104 #define MIIM_KSZ90xx_PHYCTL_1000        (1 << 6)
105 #define MIIM_KSZ90xx_PHYCTL_100         (1 << 5)
106 #define MIIM_KSZ90xx_PHYCTL_10          (1 << 4)
107 #define MIIM_KSZ90xx_PHYCTL_DUPLEX      (1 << 3)
108
109 static int ksz90xx_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_KSZ90xx_PHY_CTL);
114
115         if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
116                 phydev->duplex = DUPLEX_FULL;
117         else
118                 phydev->duplex = DUPLEX_HALF;
119
120         if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
121                 phydev->speed = SPEED_1000;
122         else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
123                 phydev->speed = SPEED_100;
124         else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
125                 phydev->speed = SPEED_10;
126         return 0;
127 }
128
129 #ifdef CONFIG_PHY_MICREL_KSZ9021
130 /*
131  * KSZ9021
132  */
133
134 /* PHY Registers */
135 #define MII_KSZ9021_EXTENDED_CTRL       0x0b
136 #define MII_KSZ9021_EXTENDED_DATAW      0x0c
137 #define MII_KSZ9021_EXTENDED_DATAR      0x0d
138
139 #define CTRL1000_PREFER_MASTER          (1 << 10)
140 #define CTRL1000_CONFIG_MASTER          (1 << 11)
141 #define CTRL1000_MANUAL_CONFIG          (1 << 12)
142
143 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
144 {
145         /* extended registers */
146         phy_write(phydev, MDIO_DEVAD_NONE,
147                 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
148         return phy_write(phydev, MDIO_DEVAD_NONE,
149                 MII_KSZ9021_EXTENDED_DATAW, val);
150 }
151
152 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
153 {
154         /* extended registers */
155         phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
156         return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
157 }
158
159
160 static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
161                               int regnum)
162 {
163         return ksz9021_phy_extended_read(phydev, regnum);
164 }
165
166 static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
167                                int devaddr, int regnum, u16 val)
168 {
169         return ksz9021_phy_extended_write(phydev, regnum, val);
170 }
171
172 /* Micrel ksz9021 */
173 static int ksz9021_config(struct phy_device *phydev)
174 {
175         unsigned ctrl1000 = 0;
176         const unsigned master = CTRL1000_PREFER_MASTER |
177                         CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
178         unsigned features = phydev->drv->features;
179
180         if (getenv("disable_giga"))
181                 features &= ~(SUPPORTED_1000baseT_Half |
182                                 SUPPORTED_1000baseT_Full);
183         /* force master mode for 1000BaseT due to chip errata */
184         if (features & SUPPORTED_1000baseT_Half)
185                 ctrl1000 |= ADVERTISE_1000HALF | master;
186         if (features & SUPPORTED_1000baseT_Full)
187                 ctrl1000 |= ADVERTISE_1000FULL | master;
188         phydev->advertising = phydev->supported = features;
189         phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
190         genphy_config_aneg(phydev);
191         genphy_restart_aneg(phydev);
192         return 0;
193 }
194
195 static struct phy_driver ksz9021_driver = {
196         .name = "Micrel ksz9021",
197         .uid  = 0x221610,
198         .mask = 0xfffff0,
199         .features = PHY_GBIT_FEATURES,
200         .config = &ksz9021_config,
201         .startup = &ksz90xx_startup,
202         .shutdown = &genphy_shutdown,
203         .writeext = &ksz9021_phy_extwrite,
204         .readext = &ksz9021_phy_extread,
205 };
206 #endif
207
208 /**
209  * KSZ9031
210  */
211 /* PHY Registers */
212 #define MII_KSZ9031_MMD_ACCES_CTRL      0x0d
213 #define MII_KSZ9031_MMD_REG_DATA        0x0e
214
215 /* Accessors to extended registers*/
216 int ksz9031_phy_extended_write(struct phy_device *phydev,
217                                int devaddr, int regnum, u16 mode, u16 val)
218 {
219         /*select register addr for mmd*/
220         phy_write(phydev, MDIO_DEVAD_NONE,
221                   MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
222         /*select register for mmd*/
223         phy_write(phydev, MDIO_DEVAD_NONE,
224                   MII_KSZ9031_MMD_REG_DATA, regnum);
225         /*setup mode*/
226         phy_write(phydev, MDIO_DEVAD_NONE,
227                   MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
228         /*write the value*/
229         return  phy_write(phydev, MDIO_DEVAD_NONE,
230                 MII_KSZ9031_MMD_REG_DATA, val);
231 }
232
233 int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
234                               int regnum, u16 mode)
235 {
236         phy_write(phydev, MDIO_DEVAD_NONE,
237                   MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
238         phy_write(phydev, MDIO_DEVAD_NONE,
239                   MII_KSZ9031_MMD_REG_DATA, regnum);
240         phy_write(phydev, MDIO_DEVAD_NONE,
241                   MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
242         return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
243 }
244
245 static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
246                                int regnum)
247 {
248         return ksz9031_phy_extended_read(phydev, devaddr, regnum,
249                                          MII_KSZ9031_MOD_DATA_NO_POST_INC);
250 };
251
252 static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
253                                 int devaddr, int regnum, u16 val)
254 {
255         return ksz9031_phy_extended_write(phydev, devaddr, regnum,
256                                          MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
257 };
258
259
260 static struct phy_driver ksz9031_driver = {
261         .name = "Micrel ksz9031",
262         .uid  = 0x221620,
263         .mask = 0xfffff0,
264         .features = PHY_GBIT_FEATURES,
265         .config   = &genphy_config,
266         .startup  = &ksz90xx_startup,
267         .shutdown = &genphy_shutdown,
268         .writeext = &ksz9031_phy_extwrite,
269         .readext = &ksz9031_phy_extread,
270 };
271
272 int phy_micrel_init(void)
273 {
274         phy_register(&KSZ804_driver);
275 #ifdef CONFIG_PHY_MICREL_KSZ9021
276         phy_register(&ksz9021_driver);
277 #else
278         phy_register(&KS8721_driver);
279 #endif
280         phy_register(&ksz9031_driver);
281         phy_register(&ksz8895_driver);
282         return 0;
283 }