GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / net / phy / adin1100.c
1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /*
3  *  Driver for Analog Devices Industrial Ethernet T1L PHYs
4  *
5  * Copyright 2020 Analog Devices Inc.
6  */
7 #include <linux/kernel.h>
8 #include <linux/bitfield.h>
9 #include <linux/delay.h>
10 #include <linux/errno.h>
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/mii.h>
14 #include <linux/phy.h>
15 #include <linux/property.h>
16
17 #define PHY_ID_ADIN1100                         0x0283bc81
18 #define PHY_ID_ADIN1110                         0x0283bc91
19 #define PHY_ID_ADIN2111                         0x0283bca1
20
21 #define ADIN_FORCED_MODE                        0x8000
22 #define   ADIN_FORCED_MODE_EN                   BIT(0)
23
24 #define ADIN_CRSM_SFT_RST                       0x8810
25 #define   ADIN_CRSM_SFT_RST_EN                  BIT(0)
26
27 #define ADIN_CRSM_SFT_PD_CNTRL                  0x8812
28 #define   ADIN_CRSM_SFT_PD_CNTRL_EN             BIT(0)
29
30 #define ADIN_AN_PHY_INST_STATUS                 0x8030
31 #define   ADIN_IS_CFG_SLV                       BIT(2)
32 #define   ADIN_IS_CFG_MST                       BIT(3)
33
34 #define ADIN_CRSM_STAT                          0x8818
35 #define   ADIN_CRSM_SFT_PD_RDY                  BIT(1)
36 #define   ADIN_CRSM_SYS_RDY                     BIT(0)
37
38 #define ADIN_MSE_VAL                            0x830B
39
40 #define ADIN_SQI_MAX    7
41
42 struct adin_mse_sqi_range {
43         u16 start;
44         u16 end;
45 };
46
47 static const struct adin_mse_sqi_range adin_mse_sqi_map[] = {
48         { 0x0A74, 0xFFFF },
49         { 0x084E, 0x0A74 },
50         { 0x0698, 0x084E },
51         { 0x053D, 0x0698 },
52         { 0x0429, 0x053D },
53         { 0x034E, 0x0429 },
54         { 0x02A0, 0x034E },
55         { 0x0000, 0x02A0 },
56 };
57
58 /**
59  * struct adin_priv - ADIN PHY driver private data
60  * @tx_level_2v4_able:          set if the PHY supports 2.4V TX levels (10BASE-T1L)
61  * @tx_level_2v4:               set if the PHY requests 2.4V TX levels (10BASE-T1L)
62  * @tx_level_prop_present:      set if the TX level is specified in DT
63  */
64 struct adin_priv {
65         unsigned int            tx_level_2v4_able:1;
66         unsigned int            tx_level_2v4:1;
67         unsigned int            tx_level_prop_present:1;
68 };
69
70 static int adin_read_status(struct phy_device *phydev)
71 {
72         int ret;
73
74         ret = genphy_c45_read_status(phydev);
75         if (ret)
76                 return ret;
77
78         ret = phy_read_mmd(phydev, MDIO_MMD_AN, ADIN_AN_PHY_INST_STATUS);
79         if (ret < 0)
80                 return ret;
81
82         if (ret & ADIN_IS_CFG_SLV)
83                 phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
84
85         if (ret & ADIN_IS_CFG_MST)
86                 phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
87
88         return 0;
89 }
90
91 static int adin_config_aneg(struct phy_device *phydev)
92 {
93         struct adin_priv *priv = phydev->priv;
94         int ret;
95
96         if (phydev->autoneg == AUTONEG_DISABLE) {
97                 ret = genphy_c45_pma_setup_forced(phydev);
98                 if (ret < 0)
99                         return ret;
100
101                 if (priv->tx_level_prop_present && priv->tx_level_2v4)
102                         ret = phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
103                                                MDIO_PMA_10T1L_CTRL_2V4_EN);
104                 else
105                         ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
106                                                  MDIO_PMA_10T1L_CTRL_2V4_EN);
107                 if (ret < 0)
108                         return ret;
109
110                 /* Force PHY to use above configurations */
111                 return phy_set_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
112         }
113
114         ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
115         if (ret < 0)
116                 return ret;
117
118         /* Request increased transmit level from LP. */
119         if (priv->tx_level_prop_present && priv->tx_level_2v4) {
120                 ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
121                                        MDIO_AN_T1_ADV_H_10L_TX_HI |
122                                        MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
123                 if (ret < 0)
124                         return ret;
125         }
126
127         /* Disable 2.4 Vpp transmit level. */
128         if ((priv->tx_level_prop_present && !priv->tx_level_2v4) || !priv->tx_level_2v4_able) {
129                 ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
130                                          MDIO_AN_T1_ADV_H_10L_TX_HI |
131                                          MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
132                 if (ret < 0)
133                         return ret;
134         }
135
136         return genphy_c45_config_aneg(phydev);
137 }
138
139 static int adin_set_powerdown_mode(struct phy_device *phydev, bool en)
140 {
141         int ret;
142         int val;
143
144         val = en ? ADIN_CRSM_SFT_PD_CNTRL_EN : 0;
145         ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
146                             ADIN_CRSM_SFT_PD_CNTRL, val);
147         if (ret < 0)
148                 return ret;
149
150         return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
151                                          (ret & ADIN_CRSM_SFT_PD_RDY) == val,
152                                          1000, 30000, true);
153 }
154
155 static int adin_suspend(struct phy_device *phydev)
156 {
157         return adin_set_powerdown_mode(phydev, true);
158 }
159
160 static int adin_resume(struct phy_device *phydev)
161 {
162         return adin_set_powerdown_mode(phydev, false);
163 }
164
165 static int adin_set_loopback(struct phy_device *phydev, bool enable)
166 {
167         if (enable)
168                 return phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
169                                         BMCR_LOOPBACK);
170
171         /* PCS loopback (according to 10BASE-T1L spec) */
172         return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
173                                  BMCR_LOOPBACK);
174 }
175
176 static int adin_soft_reset(struct phy_device *phydev)
177 {
178         int ret;
179
180         ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, ADIN_CRSM_SFT_RST, ADIN_CRSM_SFT_RST_EN);
181         if (ret < 0)
182                 return ret;
183
184         return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
185                                          (ret & ADIN_CRSM_SYS_RDY),
186                                          10000, 30000, true);
187 }
188
189 static int adin_get_features(struct phy_device *phydev)
190 {
191         struct adin_priv *priv = phydev->priv;
192         struct device *dev = &phydev->mdio.dev;
193         int ret;
194         u8 val;
195
196         ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10T1L_STAT);
197         if (ret < 0)
198                 return ret;
199
200         /* This depends on the voltage level from the power source */
201         priv->tx_level_2v4_able = !!(ret & MDIO_PMA_10T1L_STAT_2V4_ABLE);
202
203         phydev_dbg(phydev, "PHY supports 2.4V TX level: %s\n",
204                    priv->tx_level_2v4_able ? "yes" : "no");
205
206         priv->tx_level_prop_present = device_property_present(dev, "phy-10base-t1l-2.4vpp");
207         if (priv->tx_level_prop_present) {
208                 ret = device_property_read_u8(dev, "phy-10base-t1l-2.4vpp", &val);
209                 if (ret < 0)
210                         return ret;
211
212                 priv->tx_level_2v4 = val;
213                 if (!priv->tx_level_2v4 && priv->tx_level_2v4_able)
214                         phydev_info(phydev,
215                                     "PHY supports 2.4V TX level, but disabled via config\n");
216         }
217
218         linkmode_set_bit_array(phy_basic_ports_array, ARRAY_SIZE(phy_basic_ports_array),
219                                phydev->supported);
220
221         return genphy_c45_pma_read_abilities(phydev);
222 }
223
224 static int adin_get_sqi(struct phy_device *phydev)
225 {
226         u16 mse_val;
227         int sqi;
228         int ret;
229
230         ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT1);
231         if (ret < 0)
232                 return ret;
233         else if (!(ret & MDIO_STAT1_LSTATUS))
234                 return 0;
235
236         ret = phy_read_mmd(phydev, MDIO_STAT1, ADIN_MSE_VAL);
237         if (ret < 0)
238                 return ret;
239
240         mse_val = 0xFFFF & ret;
241         for (sqi = 0; sqi < ARRAY_SIZE(adin_mse_sqi_map); sqi++) {
242                 if (mse_val >= adin_mse_sqi_map[sqi].start && mse_val <= adin_mse_sqi_map[sqi].end)
243                         return sqi;
244         }
245
246         return -EINVAL;
247 }
248
249 static int adin_get_sqi_max(struct phy_device *phydev)
250 {
251         return ADIN_SQI_MAX;
252 }
253
254 static int adin_probe(struct phy_device *phydev)
255 {
256         struct device *dev = &phydev->mdio.dev;
257         struct adin_priv *priv;
258
259         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
260         if (!priv)
261                 return -ENOMEM;
262
263         phydev->priv = priv;
264
265         return 0;
266 }
267
268 static struct phy_driver adin_driver[] = {
269         {
270                 .phy_id                 = PHY_ID_ADIN1100,
271                 .phy_id_mask            = 0xffffffcf,
272                 .name                   = "ADIN1100",
273                 .get_features           = adin_get_features,
274                 .soft_reset             = adin_soft_reset,
275                 .probe                  = adin_probe,
276                 .config_aneg            = adin_config_aneg,
277                 .read_status            = adin_read_status,
278                 .set_loopback           = adin_set_loopback,
279                 .suspend                = adin_suspend,
280                 .resume                 = adin_resume,
281                 .get_sqi                = adin_get_sqi,
282                 .get_sqi_max            = adin_get_sqi_max,
283         },
284 };
285
286 module_phy_driver(adin_driver);
287
288 static struct mdio_device_id __maybe_unused adin_tbl[] = {
289         { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1100) },
290         { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1110) },
291         { PHY_ID_MATCH_MODEL(PHY_ID_ADIN2111) },
292         { }
293 };
294
295 MODULE_DEVICE_TABLE(mdio, adin_tbl);
296 MODULE_DESCRIPTION("Analog Devices Industrial Ethernet T1L PHY driver");
297 MODULE_LICENSE("Dual BSD/GPL");