]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/phy/micrel.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[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
29  * Shame Micrel, Shame!!!!!
30  */
31 static 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 };
40 #endif
41
42
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
53 static 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 }
72 #ifdef CONFIG_PHY_MICREL_KSZ9021
73
74 /*
75  * KSZ9021
76  */
77
78 /* PHY Registers */
79 #define MII_KSZ9021_EXTENDED_CTRL       0x0b
80 #define MII_KSZ9021_EXTENDED_DATAW      0x0c
81 #define MII_KSZ9021_EXTENDED_DATAR      0x0d
82
83 #define CTRL1000_PREFER_MASTER          (1 << 10)
84 #define CTRL1000_CONFIG_MASTER          (1 << 11)
85 #define CTRL1000_MANUAL_CONFIG          (1 << 12)
86
87 int 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
96 int 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
104 static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
105                               int regnum)
106 {
107         return ksz9021_phy_extended_read(phydev, regnum);
108 }
109
110 static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
111                                int devaddr, int regnum, u16 val)
112 {
113         return ksz9021_phy_extended_write(phydev, regnum, val);
114 }
115
116 /* Micrel ksz9021 */
117 static int ksz9021_config(struct phy_device *phydev)
118 {
119         unsigned ctrl1000 = 0;
120         const unsigned master = CTRL1000_PREFER_MASTER |
121                         CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
122         unsigned features = phydev->drv->features;
123
124         if (getenv("disable_giga"))
125                 features &= ~(SUPPORTED_1000baseT_Half |
126                                 SUPPORTED_1000baseT_Full);
127         /* force master mode for 1000BaseT due to chip errata */
128         if (features & SUPPORTED_1000baseT_Half)
129                 ctrl1000 |= ADVERTISE_1000HALF | master;
130         if (features & SUPPORTED_1000baseT_Full)
131                 ctrl1000 |= ADVERTISE_1000FULL | master;
132         phydev->advertising = phydev->supported = features;
133         phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
134         genphy_config_aneg(phydev);
135         genphy_restart_aneg(phydev);
136         return 0;
137 }
138
139 static struct phy_driver ksz9021_driver = {
140         .name = "Micrel ksz9021",
141         .uid  = 0x221610,
142         .mask = 0xfffff0,
143         .features = PHY_GBIT_FEATURES,
144         .config = &ksz9021_config,
145         .startup = &ksz90xx_startup,
146         .shutdown = &genphy_shutdown,
147         .writeext = &ksz9021_phy_extwrite,
148         .readext = &ksz9021_phy_extread,
149 };
150 #endif
151
152 /**
153  * KSZ9031
154  */
155 /* PHY Registers */
156 #define MII_KSZ9031_MMD_ACCES_CTRL      0x0d
157 #define MII_KSZ9031_MMD_REG_DATA        0x0e
158
159 /* Accessors to extended registers*/
160 int ksz9031_phy_extended_write(struct phy_device *phydev,
161                                int devaddr, int regnum, u16 mode, u16 val)
162 {
163         /*select register addr for mmd*/
164         phy_write(phydev, MDIO_DEVAD_NONE,
165                   MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
166         /*select register for mmd*/
167         phy_write(phydev, MDIO_DEVAD_NONE,
168                   MII_KSZ9031_MMD_REG_DATA, regnum);
169         /*setup mode*/
170         phy_write(phydev, MDIO_DEVAD_NONE,
171                   MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
172         /*write the value*/
173         return  phy_write(phydev, MDIO_DEVAD_NONE,
174                 MII_KSZ9031_MMD_REG_DATA, val);
175 }
176
177 int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
178                               int regnum, u16 mode)
179 {
180         phy_write(phydev, MDIO_DEVAD_NONE,
181                   MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
182         phy_write(phydev, MDIO_DEVAD_NONE,
183                   MII_KSZ9031_MMD_REG_DATA, regnum);
184         phy_write(phydev, MDIO_DEVAD_NONE,
185                   MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
186         return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
187 }
188
189 static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
190                                int regnum)
191 {
192         return ksz9031_phy_extended_read(phydev, devaddr, regnum,
193                                          MII_KSZ9031_MOD_DATA_NO_POST_INC);
194 };
195
196 static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
197                                 int devaddr, int regnum, u16 val)
198 {
199         return ksz9031_phy_extended_write(phydev, devaddr, regnum,
200                                          MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
201 };
202
203
204 static struct phy_driver ksz9031_driver = {
205         .name = "Micrel ksz9031",
206         .uid  = 0x221620,
207         .mask = 0xfffff0,
208         .features = PHY_GBIT_FEATURES,
209         .config   = &genphy_config,
210         .startup  = &ksz90xx_startup,
211         .shutdown = &genphy_shutdown,
212         .writeext = &ksz9031_phy_extwrite,
213         .readext = &ksz9031_phy_extread,
214 };
215
216 int phy_micrel_init(void)
217 {
218         phy_register(&KSZ804_driver);
219 #ifdef CONFIG_PHY_MICREL_KSZ9021
220         phy_register(&ksz9021_driver);
221 #else
222         phy_register(&KS8721_driver);
223 #endif
224         phy_register(&ksz9031_driver);
225         return 0;
226 }