...
...
13
one the firmware is loaded.
13
one the firmware is loaded.
14
14
15
In practice:
15
In practice:
16
- MMD 0x7 ID 0x7500 0x9410 -> FW LOAD -> ID 0x7500 0x9422
16
- MMD 0x7 ID 0x7500 0x9410 -> FW LOAD -> ID 0x7500 0x9422
17
17
18
To handle this, we apply a simple approach where the PHY
18
To handle this, we operate on .match_phy_device where
19
is registered a first time, with the PHY driver maching for
19
we check the PHY ID, if the ID match the generic one,
20
the generic PHY ID (0x7500 0x9410), probing and loading the fw.
20
we load the firmware and we return 0 (PHY driver doesn't
21
The PHY driver enable the new option "needs_reregister" in phy_device.
21
match). Then PHY core will try the next PHY driver in the list
22
and this time the PHY is correctly filled in and we register
23
for it.
22
24
23
This special option will detach the PHY driver from the PHY device,
25
To help in the matching and not modify part of the PHY device
24
scan the MDIO BUS for that address and attach it again. This is
26
struct, .match_phy_device is extended to provide also the
25
done entirely in one go at the phy_register_device time.
27
current phy_driver is trying to match for. This add the
28
extra benefits that some other PHY can simplify their
29
.match_phy_device OP.
26
30
27
At the second time the driver will match the more specific PHY ID
31
Changes v5:
28
(0x7500 0x9422) as the PHY now provides it now that is had the FW
32
- Add Reviewed-by tag from Rob
29
loaded.
33
- Fix subject in DT patch
30
34
- Fix wrong Suggested-by tag in patch 1
31
We can assume the PHY doesn't change Vendor or Family after
35
- Rework nxp patch to 80 column
32
the PHY is loaded (that wouldn't make sense) and in the extreme
36
Changes v4:
33
case this happen, no PHY will be matched and the generic one is
37
- Add Reviewed-by tag
34
loaded.
38
- Better handle PHY ID scan in as21xxx
35
39
- Also simplify nxp driver and fix .match_phy_device
40
Changes v3:
41
- Correct typo intergate->integrate
42
- Try to reduce to 80 column (where possible... define become
43
unreasable if split)
44
- Rework to new .match_phy_device implementation
45
- Init active_low_led and fix other minor smatch war
46
- Drop inline tag (kbot doesn't like it but not reported by checkpatch???)
36
Changes v2:
47
Changes v2:
37
- Move to RFC as net-next closed :(
48
- Move to RFC as net-next closed :(
38
- Add lock for IPC command
49
- Add lock for IPC command
39
- Better check size values from IPC
50
- Better check size values from IPC
40
- Add PHY ID for all supported PHYs
51
- Add PHY ID for all supported PHYs
...
...
45
for generic PHY ID)
56
for generic PHY ID)
46
- Better document C22 in C45
57
- Better document C22 in C45
47
- Document PHY name logic
58
- Document PHY name logic
48
- Introduce patch to load PHY 2 times
59
- Introduce patch to load PHY 2 times
49
60
50
Christian Marangi (3):
61
Christian Marangi (6):
51
net: phy: permit PHYs to register a second time
62
net: phy: pass PHY driver to .match_phy_device OP
63
net: phy: bcm87xx: simplify .match_phy_device OP
64
net: phy: nxp-c45-tja11xx: simplify .match_phy_device OP
65
net: phy: introduce genphy_match_phy_device()
52
net: phy: Add support for Aeonsemi AS21xxx PHYs
66
net: phy: Add support for Aeonsemi AS21xxx PHYs
53
dt-bindings: net: Document support for Aeonsemi PHYs
67
dt-bindings: net: Document support for Aeonsemi PHYs
54
68
55
.../bindings/net/aeonsemi,as21xxx.yaml | 122 +++
69
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++
56
MAINTAINERS | 7 +
70
MAINTAINERS | 7 +
57
drivers/net/phy/Kconfig | 12 +
71
drivers/net/phy/Kconfig | 12 +
58
drivers/net/phy/Makefile | 1 +
72
drivers/net/phy/Makefile | 1 +
59
drivers/net/phy/as21xxx.c | 973 ++++++++++++++++++
73
drivers/net/phy/as21xxx.c | 1067 +++++++++++++++++
60
drivers/net/phy/phy_device.c | 27 +
74
drivers/net/phy/bcm87xx.c | 14 +-
61
include/linux/phy.h | 5 +
75
drivers/net/phy/icplus.c | 6 +-
62
7 files changed, 1147 insertions(+)
76
drivers/net/phy/marvell10g.c | 12 +-
77
drivers/net/phy/micrel.c | 6 +-
78
drivers/net/phy/nxp-c45-tja11xx.c | 41 +-
79
drivers/net/phy/nxp-tja11xx.c | 6 +-
80
drivers/net/phy/phy_device.c | 52 +-
81
drivers/net/phy/realtek/realtek_main.c | 27 +-
82
drivers/net/phy/teranetics.c | 3 +-
83
include/linux/phy.h | 6 +-
84
15 files changed, 1316 insertions(+), 66 deletions(-)
63
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
85
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
64
create mode 100644 drivers/net/phy/as21xxx.c
86
create mode 100644 drivers/net/phy/as21xxx.c
65
87
66
--
88
--
67
2.48.1
89
2.48.1
diff view generated by jsdifflib
New patch
1
Pass PHY driver pointer to .match_phy_device OP in addition to phydev.
2
Having access to the PHY driver struct might be useful to check the
3
PHY ID of the driver is being matched for in case the PHY ID scanned in
4
the phydev is not consistent.
1
5
6
A scenario for this is a PHY that change PHY ID after a firmware is
7
loaded, in such case, the PHY ID stored in PHY device struct is not
8
valid anymore and PHY will manually scan the ID in the match_phy_device
9
function.
10
11
Having the PHY driver info is also useful for those PHY driver that
12
implement multiple simple .match_phy_device OP to match specific MMD PHY
13
ID. With this extra info if the parsing logic is the same, the matching
14
function can be generalized by using the phy_id in the PHY driver
15
instead of hardcoding.
16
17
Suggested-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
18
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
19
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
20
---
21
drivers/net/phy/bcm87xx.c | 6 ++++--
22
drivers/net/phy/icplus.c | 6 ++++--
23
drivers/net/phy/marvell10g.c | 12 ++++++++----
24
drivers/net/phy/micrel.c | 6 ++++--
25
drivers/net/phy/nxp-c45-tja11xx.c | 12 ++++++++----
26
drivers/net/phy/nxp-tja11xx.c | 6 ++++--
27
drivers/net/phy/phy_device.c | 2 +-
28
drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++---------
29
drivers/net/phy/teranetics.c | 3 ++-
30
include/linux/phy.h | 3 ++-
31
10 files changed, 55 insertions(+), 28 deletions(-)
32
33
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/drivers/net/phy/bcm87xx.c
36
+++ b/drivers/net/phy/bcm87xx.c
37
@@ -XXX,XX +XXX,XX @@ static irqreturn_t bcm87xx_handle_interrupt(struct phy_device *phydev)
38
    return IRQ_HANDLED;
39
}
40
41
-static int bcm8706_match_phy_device(struct phy_device *phydev)
42
+static int bcm8706_match_phy_device(struct phy_device *phydev,
43
+                 const struct phy_driver *phydrv)
44
{
45
    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706;
46
}
47
48
-static int bcm8727_match_phy_device(struct phy_device *phydev)
49
+static int bcm8727_match_phy_device(struct phy_device *phydev,
50
+                 const struct phy_driver *phydrv)
51
{
52
    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727;
53
}
54
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/drivers/net/phy/icplus.c
57
+++ b/drivers/net/phy/icplus.c
58
@@ -XXX,XX +XXX,XX @@ static int ip101a_g_match_phy_device(struct phy_device *phydev, bool ip101a)
59
    return ip101a == !ret;
60
}
61
62
-static int ip101a_match_phy_device(struct phy_device *phydev)
63
+static int ip101a_match_phy_device(struct phy_device *phydev,
64
+                 const struct phy_driver *phydrv)
65
{
66
    return ip101a_g_match_phy_device(phydev, true);
67
}
68
69
-static int ip101g_match_phy_device(struct phy_device *phydev)
70
+static int ip101g_match_phy_device(struct phy_device *phydev,
71
+                 const struct phy_driver *phydrv)
72
{
73
    return ip101a_g_match_phy_device(phydev, false);
74
}
75
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/drivers/net/phy/marvell10g.c
78
+++ b/drivers/net/phy/marvell10g.c
79
@@ -XXX,XX +XXX,XX @@ static int mv3310_get_number_of_ports(struct phy_device *phydev)
80
    return ret + 1;
81
}
82
83
-static int mv3310_match_phy_device(struct phy_device *phydev)
84
+static int mv3310_match_phy_device(struct phy_device *phydev,
85
+                 const struct phy_driver *phydrv)
86
{
87
    if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
88
     MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
89
@@ -XXX,XX +XXX,XX @@ static int mv3310_match_phy_device(struct phy_device *phydev)
90
    return mv3310_get_number_of_ports(phydev) == 1;
91
}
92
93
-static int mv3340_match_phy_device(struct phy_device *phydev)
94
+static int mv3340_match_phy_device(struct phy_device *phydev,
95
+                 const struct phy_driver *phydrv)
96
{
97
    if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
98
     MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
99
@@ -XXX,XX +XXX,XX @@ static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
100
    return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
101
}
102
103
-static int mv2110_match_phy_device(struct phy_device *phydev)
104
+static int mv2110_match_phy_device(struct phy_device *phydev,
105
+                 const struct phy_driver *phydrv)
106
{
107
    return mv211x_match_phy_device(phydev, true);
108
}
109
110
-static int mv2111_match_phy_device(struct phy_device *phydev)
111
+static int mv2111_match_phy_device(struct phy_device *phydev,
112
+                 const struct phy_driver *phydrv)
113
{
114
    return mv211x_match_phy_device(phydev, false);
115
}
116
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/drivers/net/phy/micrel.c
119
+++ b/drivers/net/phy/micrel.c
120
@@ -XXX,XX +XXX,XX @@ static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev,
121
        return !ret;
122
}
123
124
-static int ksz8051_match_phy_device(struct phy_device *phydev)
125
+static int ksz8051_match_phy_device(struct phy_device *phydev,
126
+                 const struct phy_driver *phydrv)
127
{
128
    return ksz8051_ksz8795_match_phy_device(phydev, true);
129
}
130
@@ -XXX,XX +XXX,XX @@ static int ksz8061_config_init(struct phy_device *phydev)
131
    return kszphy_config_init(phydev);
132
}
133
134
-static int ksz8795_match_phy_device(struct phy_device *phydev)
135
+static int ksz8795_match_phy_device(struct phy_device *phydev,
136
+                 const struct phy_driver *phydrv)
137
{
138
    return ksz8051_ksz8795_match_phy_device(phydev, false);
139
}
140
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/drivers/net/phy/nxp-c45-tja11xx.c
143
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
144
@@ -XXX,XX +XXX,XX @@ static int nxp_c45_macsec_ability(struct phy_device *phydev)
145
    return macsec_ability;
146
}
147
148
-static int tja1103_match_phy_device(struct phy_device *phydev)
149
+static int tja1103_match_phy_device(struct phy_device *phydev,
150
+                 const struct phy_driver *phydrv)
151
{
152
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
153
     !nxp_c45_macsec_ability(phydev);
154
}
155
156
-static int tja1104_match_phy_device(struct phy_device *phydev)
157
+static int tja1104_match_phy_device(struct phy_device *phydev,
158
+                 const struct phy_driver *phydrv)
159
{
160
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
161
     nxp_c45_macsec_ability(phydev);
162
}
163
164
-static int tja1120_match_phy_device(struct phy_device *phydev)
165
+static int tja1120_match_phy_device(struct phy_device *phydev,
166
+                 const struct phy_driver *phydrv)
167
{
168
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
169
     !nxp_c45_macsec_ability(phydev);
170
}
171
172
-static int tja1121_match_phy_device(struct phy_device *phydev)
173
+static int tja1121_match_phy_device(struct phy_device *phydev,
174
+                 const struct phy_driver *phydrv)
175
{
176
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
177
     nxp_c45_macsec_ability(phydev);
178
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/drivers/net/phy/nxp-tja11xx.c
181
+++ b/drivers/net/phy/nxp-tja11xx.c
182
@@ -XXX,XX +XXX,XX @@ static int tja1102_match_phy_device(struct phy_device *phydev, bool port0)
183
    return !ret;
184
}
185
186
-static int tja1102_p0_match_phy_device(struct phy_device *phydev)
187
+static int tja1102_p0_match_phy_device(struct phy_device *phydev,
188
+                 const struct phy_driver *phydrv)
189
{
190
    return tja1102_match_phy_device(phydev, true);
191
}
192
193
-static int tja1102_p1_match_phy_device(struct phy_device *phydev)
194
+static int tja1102_p1_match_phy_device(struct phy_device *phydev,
195
+                 const struct phy_driver *phydrv)
196
{
197
    return tja1102_match_phy_device(phydev, false);
198
}
199
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/drivers/net/phy/phy_device.c
202
+++ b/drivers/net/phy/phy_device.c
203
@@ -XXX,XX +XXX,XX @@ static int phy_bus_match(struct device *dev, const struct device_driver *drv)
204
        return 0;
205
206
    if (phydrv->match_phy_device)
207
-        return phydrv->match_phy_device(phydev);
208
+        return phydrv->match_phy_device(phydev, phydrv);
209
210
    if (phydev->is_c45) {
211
        for (i = 1; i < num_ids; i++) {
212
diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/drivers/net/phy/realtek/realtek_main.c
215
+++ b/drivers/net/phy/realtek/realtek_main.c
216
@@ -XXX,XX +XXX,XX @@ static bool rtlgen_supports_mmd(struct phy_device *phydev)
217
    return val > 0;
218
}
219
220
-static int rtlgen_match_phy_device(struct phy_device *phydev)
221
+static int rtlgen_match_phy_device(struct phy_device *phydev,
222
+                 const struct phy_driver *phydrv)
223
{
224
    return phydev->phy_id == RTL_GENERIC_PHYID &&
225
     !rtlgen_supports_2_5gbps(phydev);
226
}
227
228
-static int rtl8226_match_phy_device(struct phy_device *phydev)
229
+static int rtl8226_match_phy_device(struct phy_device *phydev,
230
+                 const struct phy_driver *phydrv)
231
{
232
    return phydev->phy_id == RTL_GENERIC_PHYID &&
233
     rtlgen_supports_2_5gbps(phydev) &&
234
@@ -XXX,XX +XXX,XX @@ static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
235
        return !is_c45 && (id == phydev->phy_id);
236
}
237
238
-static int rtl8221b_match_phy_device(struct phy_device *phydev)
239
+static int rtl8221b_match_phy_device(struct phy_device *phydev,
240
+                 const struct phy_driver *phydrv)
241
{
242
    return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev);
243
}
244
245
-static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
246
+static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev,
247
+                     const struct phy_driver *phydrv)
248
{
249
    return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
250
}
251
252
-static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev)
253
+static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev,
254
+                     const struct phy_driver *phydrv)
255
{
256
    return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
257
}
258
259
-static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev)
260
+static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev,
261
+                     const struct phy_driver *phydrv)
262
{
263
    return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false);
264
}
265
266
-static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev)
267
+static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev,
268
+                     const struct phy_driver *phydrv)
269
{
270
    return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
271
}
272
273
-static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev)
274
+static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev,
275
+                        const struct phy_driver *phydrv)
276
{
277
    if (phydev->is_c45)
278
        return false;
279
@@ -XXX,XX +XXX,XX @@ static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev)
280
    return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev);
281
}
282
283
-static int rtl8251b_c45_match_phy_device(struct phy_device *phydev)
284
+static int rtl8251b_c45_match_phy_device(struct phy_device *phydev,
285
+                     const struct phy_driver *phydrv)
286
{
287
    return rtlgen_is_c45_match(phydev, RTL_8251B, true);
288
}
289
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/drivers/net/phy/teranetics.c
292
+++ b/drivers/net/phy/teranetics.c
293
@@ -XXX,XX +XXX,XX @@ static int teranetics_read_status(struct phy_device *phydev)
294
    return 0;
295
}
296
297
-static int teranetics_match_phy_device(struct phy_device *phydev)
298
+static int teranetics_match_phy_device(struct phy_device *phydev,
299
+                 const struct phy_driver *phydrv)
300
{
301
    return phydev->c45_ids.device_ids[3] == PHY_ID_TN2020;
302
}
303
diff --git a/include/linux/phy.h b/include/linux/phy.h
304
index XXXXXXX..XXXXXXX 100644
305
--- a/include/linux/phy.h
306
+++ b/include/linux/phy.h
307
@@ -XXX,XX +XXX,XX @@ struct phy_driver {
308
     * driver for the given phydev.     If NULL, matching is based on
309
     * phy_id and phy_id_mask.
310
     */
311
-    int (*match_phy_device)(struct phy_device *phydev);
312
+    int (*match_phy_device)(struct phy_device *phydev,
313
+                const struct phy_driver *phydrv);
314
315
    /**
316
     * @set_wol: Some devices (e.g. qnap TS-119P II) require PHY
317
--
318
2.48.1
diff view generated by jsdifflib
New patch
1
Simplify .match_phy_device OP by using a generic function and using the
2
new phy_id PHY driver info instead of hardcoding the matching PHY ID.
1
3
4
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
5
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
6
---
7
drivers/net/phy/bcm87xx.c | 14 ++++----------
8
1 file changed, 4 insertions(+), 10 deletions(-)
9
10
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/drivers/net/phy/bcm87xx.c
13
+++ b/drivers/net/phy/bcm87xx.c
14
@@ -XXX,XX +XXX,XX @@ static irqreturn_t bcm87xx_handle_interrupt(struct phy_device *phydev)
15
    return IRQ_HANDLED;
16
}
17
18
-static int bcm8706_match_phy_device(struct phy_device *phydev,
19
+static int bcm87xx_match_phy_device(struct phy_device *phydev,
20
                 const struct phy_driver *phydrv)
21
{
22
-    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706;
23
-}
24
-
25
-static int bcm8727_match_phy_device(struct phy_device *phydev,
26
-                 const struct phy_driver *phydrv)
27
-{
28
-    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727;
29
+    return phydev->c45_ids.device_ids[4] == phydrv->phy_id;
30
}
31
32
static struct phy_driver bcm87xx_driver[] = {
33
@@ -XXX,XX +XXX,XX @@ static struct phy_driver bcm87xx_driver[] = {
34
    .read_status    = bcm87xx_read_status,
35
    .config_intr    = bcm87xx_config_intr,
36
    .handle_interrupt = bcm87xx_handle_interrupt,
37
-    .match_phy_device = bcm8706_match_phy_device,
38
+    .match_phy_device = bcm87xx_match_phy_device,
39
}, {
40
    .phy_id        = PHY_ID_BCM8727,
41
    .phy_id_mask    = 0xffffffff,
42
@@ -XXX,XX +XXX,XX @@ static struct phy_driver bcm87xx_driver[] = {
43
    .read_status    = bcm87xx_read_status,
44
    .config_intr    = bcm87xx_config_intr,
45
    .handle_interrupt = bcm87xx_handle_interrupt,
46
-    .match_phy_device = bcm8727_match_phy_device,
47
+    .match_phy_device = bcm87xx_match_phy_device,
48
} };
49
50
module_phy_driver(bcm87xx_driver);
51
--
52
2.48.1
diff view generated by jsdifflib
New patch
1
Simplify .match_phy_device OP by using a generic function and using the
2
new phy_id PHY driver info instead of hardcoding the matching PHY ID
3
with new variant for macsec and no_macsec PHYs.
1
4
5
Also make use of PHY_ID_MATCH_MODEL macro and drop PHY_ID_MASK define to
6
introduce phy_id and phy_id_mask again in phy_driver struct.
7
8
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
9
---
10
drivers/net/phy/nxp-c45-tja11xx.c | 45 ++++++++++++++-----------------
11
1 file changed, 20 insertions(+), 25 deletions(-)
12
13
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/drivers/net/phy/nxp-c45-tja11xx.c
16
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
17
@@ -XXX,XX +XXX,XX @@
18
19
#include "nxp-c45-tja11xx.h"
20
21
-#define PHY_ID_MASK            GENMASK(31, 4)
22
/* Same id: TJA1103, TJA1104 */
23
#define PHY_ID_TJA_1103            0x001BB010
24
/* Same id: TJA1120, TJA1121 */
25
@@ -XXX,XX +XXX,XX @@ static int nxp_c45_macsec_ability(struct phy_device *phydev)
26
    return macsec_ability;
27
}
28
29
-static int tja1103_match_phy_device(struct phy_device *phydev,
30
-                 const struct phy_driver *phydrv)
31
+static int tja11xx_no_macsec_match_phy_device(struct phy_device *phydev,
32
+                     const struct phy_driver *phydrv)
33
{
34
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
35
-     !nxp_c45_macsec_ability(phydev);
36
-}
37
+    if (!phy_id_compare(phydev->phy_id, phydrv->phy_id,
38
+             phydrv->phy_id_mask))
39
+        return 0;
40
41
-static int tja1104_match_phy_device(struct phy_device *phydev,
42
-                 const struct phy_driver *phydrv)
43
-{
44
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
45
-     nxp_c45_macsec_ability(phydev);
46
+    return !nxp_c45_macsec_ability(phydev);
47
}
48
49
-static int tja1120_match_phy_device(struct phy_device *phydev,
50
-                 const struct phy_driver *phydrv)
51
+static int tja11xx_macsec_match_phy_device(struct phy_device *phydev,
52
+                     const struct phy_driver *phydrv)
53
{
54
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
55
-     !nxp_c45_macsec_ability(phydev);
56
-}
57
+    if (!phy_id_compare(phydev->phy_id, phydrv->phy_id,
58
+             phydrv->phy_id_mask))
59
+        return 0;
60
61
-static int tja1121_match_phy_device(struct phy_device *phydev,
62
-                 const struct phy_driver *phydrv)
63
-{
64
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
65
-     nxp_c45_macsec_ability(phydev);
66
+    return nxp_c45_macsec_ability(phydev);
67
}
68
69
static const struct nxp_c45_regmap tja1120_regmap = {
70
@@ -XXX,XX +XXX,XX @@ static const struct nxp_c45_phy_data tja1120_phy_data = {
71
72
static struct phy_driver nxp_c45_driver[] = {
73
    {
74
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
75
        .name            = "NXP C45 TJA1103",
76
        .get_features        = nxp_c45_get_features,
77
        .driver_data        = &tja1103_phy_data,
78
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
79
        .get_sqi        = nxp_c45_get_sqi,
80
        .get_sqi_max        = nxp_c45_get_sqi_max,
81
        .remove            = nxp_c45_remove,
82
-        .match_phy_device    = tja1103_match_phy_device,
83
+        .match_phy_device    = tja11xx_no_macsec_match_phy_device,
84
    },
85
    {
86
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
87
        .name            = "NXP C45 TJA1104",
88
        .get_features        = nxp_c45_get_features,
89
        .driver_data        = &tja1103_phy_data,
90
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
91
        .get_sqi        = nxp_c45_get_sqi,
92
        .get_sqi_max        = nxp_c45_get_sqi_max,
93
        .remove            = nxp_c45_remove,
94
-        .match_phy_device    = tja1104_match_phy_device,
95
+        .match_phy_device    = tja11xx_macsec_match_phy_device,
96
    },
97
    {
98
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120),
99
        .name            = "NXP C45 TJA1120",
100
        .get_features        = nxp_c45_get_features,
101
        .driver_data        = &tja1120_phy_data,
102
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
103
        .get_sqi        = nxp_c45_get_sqi,
104
        .get_sqi_max        = nxp_c45_get_sqi_max,
105
        .remove            = nxp_c45_remove,
106
-        .match_phy_device    = tja1120_match_phy_device,
107
+        .match_phy_device    = tja11xx_no_macsec_match_phy_device,
108
    },
109
    {
110
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120),
111
        .name            = "NXP C45 TJA1121",
112
        .get_features        = nxp_c45_get_features,
113
        .driver_data        = &tja1120_phy_data,
114
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
115
        .get_sqi        = nxp_c45_get_sqi,
116
        .get_sqi_max        = nxp_c45_get_sqi_max,
117
        .remove            = nxp_c45_remove,
118
-        .match_phy_device    = tja1121_match_phy_device,
119
+        .match_phy_device    = tja11xx_macsec_match_phy_device,
120
    },
121
};
122
123
--
124
2.48.1
diff view generated by jsdifflib
1
Some PHY might needs to register AGAIN after a firmware is loaded to
1
Introduce new API, genphy_match_phy_device(), to provide a way to check
2
correctly provide the real PHY ID.
2
to match a PHY driver for a PHY device based on the info stored in the
3
PHY device struct.
3
4
4
It was found that some PHY expose on the BUS with a PHY ID that change
5
The function generalize the logic used in phy_bus_match() to check the
5
as soon as the PHY firmware is loaded and started.
6
PHY ID whether if C45 or C22 ID should be used for matching.
6
7
7
To better handle this case and provide to the system correct info on
8
This is useful for custom .match_phy_device function that wants to use
8
what PHY is actually present on the BUS, introduce a new option for PHY
9
the generic logic under some condition. (example a PHY is already setup
9
device, needs_reregister, that register the PHY device 2 times.
10
and provide the correct PHY ID)
10
11
With needs_reregister enabled, in phy_device_register() the PHY is first
12
registered with the driver detected for the PHY ID. The PHY driver is
13
then released and the PHY ID for the PHY address is rescanned.
14
The phy_id and c45_ids entry are updated for the PHY device and finally
15
the PHY is registered again with the more specific PHY driver. (matching
16
the new PHY ID)
17
18
It's assumed that loading the firmware doesn't cause the PHY ID to change
19
to different vendor or PHY of different family (provided by different
20
drivers)
21
11
22
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
12
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
23
---
13
---
24
drivers/net/phy/phy_device.c | 27 +++++++++++++++++++++++++++
14
drivers/net/phy/phy_device.c | 52 +++++++++++++++++++++++++-----------
25
include/linux/phy.h | 5 +++++
15
include/linux/phy.h | 3 +++
26
2 files changed, 32 insertions(+)
16
2 files changed, 40 insertions(+), 15 deletions(-)
27
17
28
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
18
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
29
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
30
--- a/drivers/net/phy/phy_device.c
20
--- a/drivers/net/phy/phy_device.c
31
+++ b/drivers/net/phy/phy_device.c
21
+++ b/drivers/net/phy/phy_device.c
32
@@ -XXX,XX +XXX,XX @@ int phy_device_register(struct phy_device *phydev)
22
@@ -XXX,XX +XXX,XX @@ static int phy_scan_fixups(struct phy_device *phydev)
33
        goto out;
23
    return 0;
24
}
25
26
-static int phy_bus_match(struct device *dev, const struct device_driver *drv)
27
+/**
28
+ * genphy_match_phy_device - match a PHY device with a PHY driver
29
+ * @phydev: target phy_device struct
30
+ * @phydrv: target phy_driver struct
31
+ *
32
+ * Description: Checks whether the given PHY device matches the specified
33
+ * PHY driver. For Clause 45 PHYs, iterates over the available device
34
+ * identifiers and compares them against the driver's expected PHY ID,
35
+ * applying the provided mask. For Clause 22 PHYs, a direct ID comparison
36
+ * is performed.
37
+ *
38
+ * Return: 1 if the PHY device matches the driver, 0 otherwise.
39
+ */
40
+int genphy_match_phy_device(struct phy_device *phydev,
41
+             const struct phy_driver *phydrv)
42
{
43
-    struct phy_device *phydev = to_phy_device(dev);
44
-    const struct phy_driver *phydrv = to_phy_driver(drv);
45
-    const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
46
-    int i;
47
-
48
-    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
49
-        return 0;
50
-
51
-    if (phydrv->match_phy_device)
52
-        return phydrv->match_phy_device(phydev, phydrv);
53
-
54
    if (phydev->is_c45) {
55
+        const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
56
+        int i;
57
+
58
        for (i = 1; i < num_ids; i++) {
59
            if (phydev->c45_ids.device_ids[i] == 0xffffffff)
60
                continue;
61
@@ -XXX,XX +XXX,XX @@ static int phy_bus_match(struct device *dev, const struct device_driver *drv)
62
                     phydrv->phy_id, phydrv->phy_id_mask))
63
                return 1;
64
        }
65
+
66
        return 0;
67
-    } else {
68
-        return phy_id_compare(phydev->phy_id, phydrv->phy_id,
69
-                 phydrv->phy_id_mask);
34
    }
70
    }
35
36
+    /* Some PHY might needs to register AGAIN after a firmware
37
+     * is loaded to correctly provide the real PHY ID.
38
+     * For PHY that needs this, release the PHY driver, rescan
39
+     * the MDIO bus for the PHY address and attach a driver
40
+     * again.
41
+     * This second time, the real PHY is provided and the
42
+     * more specific PHY driver OPs are used.
43
+     */
44
+    if (phydev->needs_reregister) {
45
+        device_release_driver(&phydev->mdio.dev);
46
+
71
+
47
+        if (phydev->is_c45)
72
+    return phy_id_compare(phydev->phy_id, phydrv->phy_id,
48
+            get_phy_c45_ids(phydev->mdio.bus,
73
+             phydrv->phy_id_mask);
49
+                    phydev->mdio.addr,
74
+}
50
+                    &phydev->c45_ids);
75
+EXPORT_SYMBOL_GPL(genphy_match_phy_device);
51
+        else
52
+            get_phy_c22_id(phydev->mdio.bus,
53
+                 phydev->mdio.addr,
54
+                 &phydev->phy_id);
55
+
76
+
56
+        err = device_attach(&phydev->mdio.dev);
77
+static int phy_bus_match(struct device *dev, const struct device_driver *drv)
57
+        if (err <= 0) {
78
+{
58
+            phydev_err(phydev, "failed to reattach\n");
79
+    struct phy_device *phydev = to_phy_device(dev);
59
+            goto out;
80
+    const struct phy_driver *phydrv = to_phy_driver(drv);
60
+        }
61
+    }
62
+
81
+
63
    return 0;
82
+    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
64
83
+        return 0;
65
out:
84
+
85
+    if (phydrv->match_phy_device)
86
+        return phydrv->match_phy_device(phydev, phydrv);
87
+
88
+    return genphy_match_phy_device(phydev, phydrv);
89
}
90
91
static ssize_t
66
diff --git a/include/linux/phy.h b/include/linux/phy.h
92
diff --git a/include/linux/phy.h b/include/linux/phy.h
67
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
68
--- a/include/linux/phy.h
94
--- a/include/linux/phy.h
69
+++ b/include/linux/phy.h
95
+++ b/include/linux/phy.h
70
@@ -XXX,XX +XXX,XX @@ struct macsec_ops;
96
@@ -XXX,XX +XXX,XX @@ char *phy_attached_info_irq(struct phy_device *phydev)
71
* @mac_managed_pm: Set true if MAC driver takes of suspending/resuming PHY
97
    __malloc;
72
* @wol_enabled: Set to true if the PHY or the attached MAC have Wake-on-LAN
98
void phy_attached_info(struct phy_device *phydev);
73
*          enabled.
99
74
+ * @needs_reregister: Set to true if the PHY needs to register AGAIN after
100
+int genphy_match_phy_device(struct phy_device *phydev,
75
+ *         first registration. This is to handle special case where the
101
+             const struct phy_driver *phydrv);
76
+ *         PHY needs to load a firmware to correctly communicate the
102
+
77
+ *         specific PHY ID.
103
/* Clause 22 PHY */
78
* @state: State of the PHY for management purposes
104
int genphy_read_abilities(struct phy_device *phydev);
79
* @dev_flags: Device-specific flags used by the PHY driver.
105
int genphy_setup_forced(struct phy_device *phydev);
80
*
81
@@ -XXX,XX +XXX,XX @@ struct phy_device {
82
    unsigned is_on_sfp_module:1;
83
    unsigned mac_managed_pm:1;
84
    unsigned wol_enabled:1;
85
+    unsigned needs_reregister;
86
87
    unsigned autoneg:1;
88
    /* The most recently read link state */
89
--
106
--
90
2.48.1
107
2.48.1
diff view generated by jsdifflib
1
Add support for Aeonsemi AS21xxx 10G C45 PHYs. These PHYs intergate
1
Add support for Aeonsemi AS21xxx 10G C45 PHYs. These PHYs integrate
2
an IPC to setup some configuration and require special handling to
2
an IPC to setup some configuration and require special handling to
3
sync with the parity bit. The parity bit is a way the IPC use to
3
sync with the parity bit. The parity bit is a way the IPC use to
4
follow correct order of command sent.
4
follow correct order of command sent.
5
5
6
Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
6
Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
...
...
25
5: 5G, 2.5G
25
5: 5G, 2.5G
26
2: 2.5G
26
2: 2.5G
27
27
28
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
28
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
29
---
29
---
30
MAINTAINERS | 6 +
30
MAINTAINERS | 6 +
31
drivers/net/phy/Kconfig | 12 +
31
drivers/net/phy/Kconfig | 12 +
32
drivers/net/phy/Makefile | 1 +
32
drivers/net/phy/Makefile | 1 +
33
drivers/net/phy/as21xxx.c | 973 ++++++++++++++++++++++++++++++++++++++
33
drivers/net/phy/as21xxx.c | 1067 +++++++++++++++++++++++++++++++++++++
34
4 files changed, 992 insertions(+)
34
4 files changed, 1086 insertions(+)
35
create mode 100644 drivers/net/phy/as21xxx.c
35
create mode 100644 drivers/net/phy/as21xxx.c
36
36
37
diff --git a/MAINTAINERS b/MAINTAINERS
37
diff --git a/MAINTAINERS b/MAINTAINERS
38
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
39
--- a/MAINTAINERS
39
--- a/MAINTAINERS
...
...
385
+             BIT(TRIGGER_NETDEV_RX),
385
+             BIT(TRIGGER_NETDEV_RX),
386
+        .val = VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT
386
+        .val = VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT
387
+    }
387
+    }
388
+};
388
+};
389
+
389
+
390
+static int aeon_firmware_boot(struct phy_device *phydev, const u8 *data, size_t size)
390
+static int aeon_firmware_boot(struct phy_device *phydev, const u8 *data,
391
+             size_t size)
391
+{
392
+{
392
+    int i, ret;
393
+    int i, ret;
393
+    u16 val;
394
+    u16 val;
394
+
395
+
395
+    ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL,
396
+    ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL,
...
...
400
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_FW_START_ADDR,
401
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_FW_START_ADDR,
401
+             AEON_BOOT_ADDR);
402
+             AEON_BOOT_ADDR);
402
+    if (ret)
403
+    if (ret)
403
+        return ret;
404
+        return ret;
404
+
405
+
405
+    ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD,
406
+    ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1,
407
+             VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD,
406
+             0x3ffc, 0xc000);
408
+             0x3ffc, 0xc000);
407
+    if (ret)
409
+    if (ret)
408
+        return ret;
410
+        return ret;
409
+
411
+
410
+    val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_MDIO_INDIRECT_STATUS);
412
+    val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
413
+             VEND1_GLB_REG_MDIO_INDIRECT_STATUS);
411
+    if (val > 1) {
414
+    if (val > 1) {
412
+        phydev_err(phydev, "wrong origin mdio_indirect_status: %x\n", val);
415
+        phydev_err(phydev, "wrong origin mdio_indirect_status: %x\n", val);
413
+        return -EINVAL;
416
+        return -EINVAL;
414
+    }
417
+    }
415
+
418
+
416
+    /* Firmware is always aligned to u16 */
419
+    /* Firmware is always aligned to u16 */
417
+    for (i = 0; i < size; i += 2) {
420
+    for (i = 0; i < size; i += 2) {
418
+        val = data[i + 1] << 8 | data[i];
421
+        val = data[i + 1] << 8 | data[i];
419
+
422
+
420
+        ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_MDIO_INDIRECT_LOAD, val);
423
+        ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
424
+                 VEND1_GLB_REG_MDIO_INDIRECT_LOAD, val);
421
+        if (ret)
425
+        if (ret)
422
+            return ret;
426
+            return ret;
423
+    }
427
+    }
424
+
428
+
425
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR,
429
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
430
+             VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR,
426
+             lower_16_bits(AEON_CPU_BOOT_ADDR));
431
+             lower_16_bits(AEON_CPU_BOOT_ADDR));
427
+    if (ret)
432
+    if (ret)
428
+        return ret;
433
+        return ret;
429
+
434
+
430
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR,
435
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
436
+             VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR,
431
+             upper_16_bits(AEON_CPU_BOOT_ADDR));
437
+             upper_16_bits(AEON_CPU_BOOT_ADDR));
432
+    if (ret)
438
+    if (ret)
433
+        return ret;
439
+        return ret;
434
+
440
+
435
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL,
441
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL,
...
...
460
+    release_firmware(fw);
466
+    release_firmware(fw);
461
+
467
+
462
+    return ret;
468
+    return ret;
463
+}
469
+}
464
+
470
+
465
+static inline int aeon_ipcs_wait_cmd(struct phy_device *phydev, bool parity_status)
471
+static int aeon_ipcs_wait_cmd(struct phy_device *phydev, bool parity_status)
466
+{
472
+{
467
+    u16 val;
473
+    u16 val;
468
+
474
+
469
+    /* Exit condition logic:
475
+    /* Exit condition logic:
470
+     * - Wait for parity bit equal
476
+     * - Wait for parity bit equal
...
...
476
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_PROCESS &&
482
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_PROCESS &&
477
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_BUSY,
483
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_BUSY,
478
+                     AEON_IPC_DELAY, AEON_IPC_TIMEOUT, false);
484
+                     AEON_IPC_DELAY, AEON_IPC_TIMEOUT, false);
479
+}
485
+}
480
+
486
+
481
+static int aeon_ipc_send_cmd(struct phy_device *phydev, u32 cmd,
487
+static int aeon_ipc_send_cmd(struct phy_device *phydev,
482
+             u16 *ret_sts)
488
+             struct as21xxx_priv *priv,
483
+{
489
+             u16 cmd, u16 *ret_sts)
484
+    struct as21xxx_priv *priv = phydev->priv;
490
+{
485
+    bool curr_parity;
491
+    bool curr_parity;
486
+    int ret;
492
+    int ret;
487
+
493
+
488
+    /* The IPC sync by using a single parity bit.
494
+    /* The IPC sync by using a single parity bit.
489
+     * Each CMD have alternately this bit set or clear
495
+     * Each CMD have alternately this bit set or clear
...
...
517
+    if (ret < 0)
523
+    if (ret < 0)
518
+        return ret;
524
+        return ret;
519
+
525
+
520
+    *ret_sts = ret;
526
+    *ret_sts = ret;
521
+    if ((*ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_SUCCESS)
527
+    if ((*ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_SUCCESS)
522
+        return -EFAULT;
528
+        return -EINVAL;
523
+
529
+
524
+    return 0;
530
+    return 0;
525
+}
531
+}
526
+
532
+
527
+static int aeon_ipc_send_msg(struct phy_device *phydev, u16 opcode,
533
+static int aeon_ipc_send_msg(struct phy_device *phydev,
528
+             u16 *data, unsigned int data_len, u16 *ret_sts)
534
+             u16 opcode, u16 *data, unsigned int data_len,
535
+             u16 *ret_sts)
529
+{
536
+{
530
+    struct as21xxx_priv *priv = phydev->priv;
537
+    struct as21xxx_priv *priv = phydev->priv;
531
+    u32 cmd;
538
+    u16 cmd;
532
+    int ret;
539
+    int ret;
533
+    int i;
540
+    int i;
534
+
541
+
535
+    /* IPC have a max of 8 register to transfer data,
542
+    /* IPC have a max of 8 register to transfer data,
536
+     * make sure we never exceed this.
543
+     * make sure we never exceed this.
...
...
544
+        phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i),
551
+        phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i),
545
+             data[i]);
552
+             data[i]);
546
+
553
+
547
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, data_len) |
554
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, data_len) |
548
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, opcode);
555
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, opcode);
549
+    ret = aeon_ipc_send_cmd(phydev, cmd, ret_sts);
556
+    ret = aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
550
+    if (ret)
557
+    if (ret)
551
+        phydev_err(phydev, "failed to send ipc msg for %x: %d\n", opcode, ret);
558
+        phydev_err(phydev, "failed to send ipc msg for %x: %d\n",
559
+             opcode, ret);
552
+
560
+
553
+    mutex_unlock(&priv->ipc_lock);
561
+    mutex_unlock(&priv->ipc_lock);
554
+
562
+
555
+    return ret;
563
+    return ret;
556
+}
564
+}
557
+
565
+
558
+static int aeon_ipc_rcv_msg(struct phy_device *phydev, u16 ret_sts,
566
+static int aeon_ipc_rcv_msg(struct phy_device *phydev,
559
+             u16 *data)
567
+             u16 ret_sts, u16 *data)
560
+{
568
+{
561
+    unsigned int size = FIELD_GET(AEON_IPC_STS_SIZE, ret_sts);
562
+    struct as21xxx_priv *priv = phydev->priv;
569
+    struct as21xxx_priv *priv = phydev->priv;
570
+    unsigned int size;
563
+    int ret;
571
+    int ret;
564
+    int i;
572
+    int i;
565
+
573
+
566
+    if ((ret_sts & AEON_IPC_STS_STATUS) == AEON_IPC_STS_STATUS_ERROR)
574
+    if ((ret_sts & AEON_IPC_STS_STATUS) == AEON_IPC_STS_STATUS_ERROR)
567
+        return -EINVAL;
575
+        return -EINVAL;
568
+
576
+
569
+    /* Prevent IPC from stack smashing the kernel */
577
+    /* Prevent IPC from stack smashing the kernel */
578
+    size = FIELD_GET(AEON_IPC_STS_SIZE, ret_sts);
570
+    if (size > AEON_IPC_DATA_MAX)
579
+    if (size > AEON_IPC_DATA_MAX)
571
+        return -EINVAL;
580
+        return -EINVAL;
572
+
581
+
573
+    mutex_lock(&priv->ipc_lock);
582
+    mutex_lock(&priv->ipc_lock);
574
+
583
+
...
...
586
+    mutex_unlock(&priv->ipc_lock);
595
+    mutex_unlock(&priv->ipc_lock);
587
+
596
+
588
+    return size;
597
+    return size;
589
+}
598
+}
590
+
599
+
600
+static int aeon_ipc_noop(struct phy_device *phydev,
601
+             struct as21xxx_priv *priv, u16 *ret_sts)
602
+{
603
+    u16 cmd;
604
+
605
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) |
606
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP);
607
+
608
+    return aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
609
+}
610
+
591
+/* Logic to sync parity bit with IPC.
611
+/* Logic to sync parity bit with IPC.
592
+ * We send 2 NOP cmd with same partity and we wait for IPC
612
+ * We send 2 NOP cmd with same partity and we wait for IPC
593
+ * to handle the packet only for the second one. This way
613
+ * to handle the packet only for the second one. This way
594
+ * we make sure we are sync for every next cmd.
614
+ * we make sure we are sync for every next cmd.
595
+ */
615
+ */
596
+static int aeon_ipc_sync_parity(struct phy_device *phydev)
616
+static int aeon_ipc_sync_parity(struct phy_device *phydev,
597
+{
617
+                struct as21xxx_priv *priv)
598
+    struct as21xxx_priv *priv = phydev->priv;
618
+{
599
+    u16 ret_sts;
619
+    u16 ret_sts;
600
+    u32 cmd;
601
+    int ret;
620
+    int ret;
602
+
621
+
603
+    mutex_lock(&priv->ipc_lock);
622
+    mutex_lock(&priv->ipc_lock);
604
+
623
+
605
+    /* Send NOP with no parity */
624
+    /* Send NOP with no parity */
606
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) |
625
+    aeon_ipc_noop(phydev, priv, NULL);
607
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP);
608
+    aeon_ipc_send_cmd(phydev, cmd, NULL);
609
+
626
+
610
+    /* Reset packet parity */
627
+    /* Reset packet parity */
611
+    priv->parity_status = false;
628
+    priv->parity_status = false;
612
+
629
+
613
+    /* Send second NOP with no parity */
630
+    /* Send second NOP with no parity */
614
+    ret = aeon_ipc_send_cmd(phydev, cmd, &ret_sts);
631
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
615
+
632
+
616
+    mutex_unlock(&priv->ipc_lock);
633
+    mutex_unlock(&priv->ipc_lock);
617
+
634
+
618
+    /* We expect to return -EFAULT */
635
+    /* We expect to return -EINVAL */
619
+    if (ret != -EFAULT)
636
+    if (ret != -EINVAL)
620
+        return ret;
637
+        return ret;
621
+
638
+
622
+    if ((ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_READY)
639
+    if ((ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_READY) {
640
+        phydev_err(phydev, "Invalid IPC status on sync parity: %x\n",
641
+             ret_sts);
623
+        return -EINVAL;
642
+        return -EINVAL;
643
+    }
624
+
644
+
625
+    return 0;
645
+    return 0;
626
+}
646
+}
627
+
647
+
628
+static int aeon_ipc_get_fw_version(struct phy_device *phydev)
648
+static int aeon_ipc_get_fw_version(struct phy_device *phydev)
629
+{
649
+{
630
+    u16 ret_data[8], data[1];
650
+    u16 ret_data[8], data[1];
631
+    u16 ret_sts;
651
+    u16 ret_sts;
632
+    int ret;
652
+    int ret;
633
+
653
+
634
+    data[0] = IPC_INFO_VERSION;
654
+    data[0] = IPC_INFO_VERSION;
635
+    ret = aeon_ipc_send_msg(phydev, IPC_CMD_INFO, data, sizeof(data),
655
+    ret = aeon_ipc_send_msg(phydev, IPC_CMD_INFO, data,
636
+                &ret_sts);
656
+                sizeof(data), &ret_sts);
637
+    if (ret)
657
+    if (ret)
638
+        return ret;
658
+        return ret;
639
+
659
+
640
+    ret = aeon_ipc_rcv_msg(phydev, ret_sts, ret_data);
660
+    ret = aeon_ipc_rcv_msg(phydev, ret_sts, ret_data);
641
+    if (ret < 0)
661
+    if (ret < 0)
...
...
672
+    ret = devm_mutex_init(&phydev->mdio.dev,
692
+    ret = devm_mutex_init(&phydev->mdio.dev,
673
+             &priv->ipc_lock);
693
+             &priv->ipc_lock);
674
+    if (ret)
694
+    if (ret)
675
+        return ret;
695
+        return ret;
676
+
696
+
677
+    ret = aeon_firmware_load(phydev);
697
+    ret = aeon_ipc_sync_parity(phydev, priv);
678
+    if (ret)
698
+    if (ret)
679
+        return ret;
699
+        return ret;
680
+
700
+
681
+    ret = aeon_ipc_sync_parity(phydev);
701
+    ret = aeon_ipc_get_fw_version(phydev);
682
+    if (ret)
702
+    if (ret)
683
+        return ret;
703
+        return ret;
684
+
704
+
705
+    /* Enable PTP clk if not already Enabled */
685
+    ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK,
706
+    ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK,
686
+             VEND1_PTP_CLK_EN);
707
+             VEND1_PTP_CLK_EN);
687
+    if (ret)
708
+    if (ret)
688
+        return ret;
709
+        return ret;
689
+
710
+
690
+    ret = aeon_dpc_ra_enable(phydev);
711
+    return aeon_dpc_ra_enable(phydev);
691
+    if (ret)
692
+        return ret;
693
+
694
+    ret = aeon_ipc_get_fw_version(phydev);
695
+    if (ret)
696
+        return ret;
697
+
698
+    phydev->needs_reregister = true;
699
+
700
+    return 0;
701
+}
712
+}
702
+
713
+
703
+static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
714
+static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
704
+{
715
+{
705
+    int status;
716
+    int status;
...
...
868
+}
879
+}
869
+
880
+
870
+static int as21xxx_led_hw_control_get(struct phy_device *phydev, u8 index,
881
+static int as21xxx_led_hw_control_get(struct phy_device *phydev, u8 index,
871
+                 unsigned long *rules)
882
+                 unsigned long *rules)
872
+{
883
+{
873
+    u16 val;
884
+    int i, val;
874
+    int i;
875
+
885
+
876
+    if (index > AEON_MAX_LDES)
886
+    if (index > AEON_MAX_LDES)
877
+        return -EINVAL;
887
+        return -EINVAL;
878
+
888
+
879
+    val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_LED_REG(index));
889
+    val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_LED_REG(index));
...
...
913
+}
923
+}
914
+
924
+
915
+static int as21xxx_led_polarity_set(struct phy_device *phydev, int index,
925
+static int as21xxx_led_polarity_set(struct phy_device *phydev, int index,
916
+                 unsigned long modes)
926
+                 unsigned long modes)
917
+{
927
+{
918
+    bool led_active_low;
928
+    bool led_active_low = false;
919
+    u16 mask, val = 0;
929
+    u16 mask, val = 0;
920
+    u32 mode;
930
+    u32 mode;
921
+
931
+
922
+    if (index > AEON_MAX_LDES)
932
+    if (index > AEON_MAX_LDES)
923
+        return -EINVAL;
933
+        return -EINVAL;
...
...
942
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
952
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
943
+             VEND1_GLB_REG_CPU_CTRL,
953
+             VEND1_GLB_REG_CPU_CTRL,
944
+             mask, val);
954
+             mask, val);
945
+}
955
+}
946
+
956
+
957
+static int as21xxx_match_phy_device(struct phy_device *phydev,
958
+                 const struct phy_driver *phydrv)
959
+{
960
+    struct as21xxx_priv *priv;
961
+    u16 ret_sts;
962
+    u32 phy_id;
963
+    int ret;
964
+
965
+    /* Skip PHY that are not AS21xxx or already have firmware loaded */
966
+    if (phydev->c45_ids.device_ids[MDIO_MMD_PCS] != PHY_ID_AS21XXX)
967
+        return genphy_match_phy_device(phydev, phydrv);
968
+
969
+    /* Read PHY ID to handle firmware just loaded */
970
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1);
971
+    if (ret < 0)
972
+        return ret;
973
+    phy_id = ret << 16;
974
+
975
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID2);
976
+    if (ret < 0)
977
+        return ret;
978
+    phy_id |= ret;
979
+
980
+    /* With PHY ID not the generic AS21xxx one assume
981
+     * the firmware just loaded
982
+     */
983
+    if (phy_id != PHY_ID_AS21XXX)
984
+        return phy_id == phydrv->phy_id;
985
+
986
+    /* Allocate temp priv and load the firmware */
987
+    priv = kzalloc(sizeof(*priv), GFP_KERNEL);
988
+    if (!priv)
989
+        return -ENOMEM;
990
+
991
+    mutex_init(&priv->ipc_lock);
992
+
993
+    ret = aeon_firmware_load(phydev);
994
+    if (ret)
995
+        goto out;
996
+
997
+    /* Sync parity... */
998
+    ret = aeon_ipc_sync_parity(phydev, priv);
999
+    if (ret)
1000
+        goto out;
1001
+
1002
+    /* ...and send a third NOOP cmd to wait for firmware finish loading */
1003
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
1004
+    if (ret)
1005
+        goto out;
1006
+
1007
+out:
1008
+    mutex_destroy(&priv->ipc_lock);
1009
+    kfree(priv);
1010
+
1011
+    /* Return not maching anyway as PHY ID will change after
1012
+     * firmware is loaded. This relies on the driver probe
1013
+     * order where the first PHY driver probed is the
1014
+     * generic one.
1015
+     */
1016
+    return ret;
1017
+}
1018
+
947
+static struct phy_driver as21xxx_drivers[] = {
1019
+static struct phy_driver as21xxx_drivers[] = {
948
+    {
1020
+    {
949
+        /* PHY expose in C45 as 0x7500 0x9410
1021
+        /* PHY expose in C45 as 0x7500 0x9410
950
+         * before firmware is loaded.
1022
+         * before firmware is loaded.
1023
+         * This driver entry must be attempted first to load
1024
+         * the firmware and thus update the ID registers.
951
+         */
1025
+         */
952
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX),
1026
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX),
953
+        .name        = "Aeonsemi AS21xxx",
1027
+        .name        = "Aeonsemi AS21xxx",
954
+        .probe        = as21xxx_probe,
1028
+        .match_phy_device = as21xxx_match_phy_device,
955
+    },
1029
+    },
956
+    {
1030
+    {
957
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011JB1),
1031
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011JB1),
958
+        .name        = "Aeonsemi AS21011JB1",
1032
+        .name        = "Aeonsemi AS21011JB1",
1033
+        .probe        = as21xxx_probe,
1034
+        .match_phy_device = as21xxx_match_phy_device,
959
+        .read_status    = as21xxx_read_status,
1035
+        .read_status    = as21xxx_read_status,
960
+        .led_brightness_set = as21xxx_led_brightness_set,
1036
+        .led_brightness_set = as21xxx_led_brightness_set,
961
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1037
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
962
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1038
+        .led_hw_control_set = as21xxx_led_hw_control_set,
963
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1039
+        .led_hw_control_get = as21xxx_led_hw_control_get,
964
+        .led_polarity_set = as21xxx_led_polarity_set,
1040
+        .led_polarity_set = as21xxx_led_polarity_set,
965
+    },
1041
+    },
966
+    {
1042
+    {
967
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
1043
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
968
+        .name        = "Aeonsemi AS21011PB1",
1044
+        .name        = "Aeonsemi AS21011PB1",
1045
+        .probe        = as21xxx_probe,
1046
+        .match_phy_device = as21xxx_match_phy_device,
969
+        .read_status    = as21xxx_read_status,
1047
+        .read_status    = as21xxx_read_status,
970
+        .led_brightness_set = as21xxx_led_brightness_set,
1048
+        .led_brightness_set = as21xxx_led_brightness_set,
971
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1049
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
972
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1050
+        .led_hw_control_set = as21xxx_led_hw_control_set,
973
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1051
+        .led_hw_control_get = as21xxx_led_hw_control_get,
974
+        .led_polarity_set = as21xxx_led_polarity_set,
1052
+        .led_polarity_set = as21xxx_led_polarity_set,
975
+    },
1053
+    },
976
+    {
1054
+    {
977
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
1055
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
978
+        .name        = "Aeonsemi AS21010PB1",
1056
+        .name        = "Aeonsemi AS21010PB1",
1057
+        .probe        = as21xxx_probe,
1058
+        .match_phy_device = as21xxx_match_phy_device,
979
+        .read_status    = as21xxx_read_status,
1059
+        .read_status    = as21xxx_read_status,
980
+        .led_brightness_set = as21xxx_led_brightness_set,
1060
+        .led_brightness_set = as21xxx_led_brightness_set,
981
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1061
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
982
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1062
+        .led_hw_control_set = as21xxx_led_hw_control_set,
983
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1063
+        .led_hw_control_get = as21xxx_led_hw_control_get,
984
+        .led_polarity_set = as21xxx_led_polarity_set,
1064
+        .led_polarity_set = as21xxx_led_polarity_set,
985
+    },
1065
+    },
986
+    {
1066
+    {
987
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
1067
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
988
+        .name        = "Aeonsemi AS21010JB1",
1068
+        .name        = "Aeonsemi AS21010JB1",
1069
+        .probe        = as21xxx_probe,
1070
+        .match_phy_device = as21xxx_match_phy_device,
989
+        .read_status    = as21xxx_read_status,
1071
+        .read_status    = as21xxx_read_status,
990
+        .led_brightness_set = as21xxx_led_brightness_set,
1072
+        .led_brightness_set = as21xxx_led_brightness_set,
991
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1073
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
992
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1074
+        .led_hw_control_set = as21xxx_led_hw_control_set,
993
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1075
+        .led_hw_control_get = as21xxx_led_hw_control_get,
994
+        .led_polarity_set = as21xxx_led_polarity_set,
1076
+        .led_polarity_set = as21xxx_led_polarity_set,
995
+    },
1077
+    },
996
+    {
1078
+    {
997
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
1079
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
998
+        .name        = "Aeonsemi AS21210PB1",
1080
+        .name        = "Aeonsemi AS21210PB1",
1081
+        .probe        = as21xxx_probe,
1082
+        .match_phy_device = as21xxx_match_phy_device,
999
+        .read_status    = as21xxx_read_status,
1083
+        .read_status    = as21xxx_read_status,
1000
+        .led_brightness_set = as21xxx_led_brightness_set,
1084
+        .led_brightness_set = as21xxx_led_brightness_set,
1001
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1085
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1002
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1086
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1003
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1087
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1004
+        .led_polarity_set = as21xxx_led_polarity_set,
1088
+        .led_polarity_set = as21xxx_led_polarity_set,
1005
+    },
1089
+    },
1006
+    {
1090
+    {
1007
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
1091
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
1008
+        .name        = "Aeonsemi AS21510JB1",
1092
+        .name        = "Aeonsemi AS21510JB1",
1093
+        .probe        = as21xxx_probe,
1094
+        .match_phy_device = as21xxx_match_phy_device,
1009
+        .read_status    = as21xxx_read_status,
1095
+        .read_status    = as21xxx_read_status,
1010
+        .led_brightness_set = as21xxx_led_brightness_set,
1096
+        .led_brightness_set = as21xxx_led_brightness_set,
1011
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1097
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1012
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1098
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1013
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1099
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1014
+        .led_polarity_set = as21xxx_led_polarity_set,
1100
+        .led_polarity_set = as21xxx_led_polarity_set,
1015
+    },
1101
+    },
1016
+    {
1102
+    {
1017
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
1103
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
1018
+        .name        = "Aeonsemi AS21510PB1",
1104
+        .name        = "Aeonsemi AS21510PB1",
1105
+        .probe        = as21xxx_probe,
1106
+        .match_phy_device = as21xxx_match_phy_device,
1019
+        .read_status    = as21xxx_read_status,
1107
+        .read_status    = as21xxx_read_status,
1020
+        .led_brightness_set = as21xxx_led_brightness_set,
1108
+        .led_brightness_set = as21xxx_led_brightness_set,
1021
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1109
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1022
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1110
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1023
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1111
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1024
+        .led_polarity_set = as21xxx_led_polarity_set,
1112
+        .led_polarity_set = as21xxx_led_polarity_set,
1025
+    },
1113
+    },
1026
+    {
1114
+    {
1027
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
1115
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
1028
+        .name        = "Aeonsemi AS21511JB1",
1116
+        .name        = "Aeonsemi AS21511JB1",
1117
+        .probe        = as21xxx_probe,
1118
+        .match_phy_device = as21xxx_match_phy_device,
1029
+        .read_status    = as21xxx_read_status,
1119
+        .read_status    = as21xxx_read_status,
1030
+        .led_brightness_set = as21xxx_led_brightness_set,
1120
+        .led_brightness_set = as21xxx_led_brightness_set,
1031
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1121
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1032
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1122
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1033
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1123
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1034
+        .led_polarity_set = as21xxx_led_polarity_set,
1124
+        .led_polarity_set = as21xxx_led_polarity_set,
1035
+    },
1125
+    },
1036
+    {
1126
+    {
1037
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
1127
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
1038
+        .name        = "Aeonsemi AS21210JB1",
1128
+        .name        = "Aeonsemi AS21210JB1",
1129
+        .probe        = as21xxx_probe,
1130
+        .match_phy_device = as21xxx_match_phy_device,
1039
+        .read_status    = as21xxx_read_status,
1131
+        .read_status    = as21xxx_read_status,
1040
+        .led_brightness_set = as21xxx_led_brightness_set,
1132
+        .led_brightness_set = as21xxx_led_brightness_set,
1041
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1133
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1042
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1134
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1043
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1135
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1044
+        .led_polarity_set = as21xxx_led_polarity_set,
1136
+        .led_polarity_set = as21xxx_led_polarity_set,
1045
+    },
1137
+    },
1046
+    {
1138
+    {
1047
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
1139
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
1048
+        .name        = "Aeonsemi AS21511PB1",
1140
+        .name        = "Aeonsemi AS21511PB1",
1141
+        .probe        = as21xxx_probe,
1142
+        .match_phy_device = as21xxx_match_phy_device,
1049
+        .read_status    = as21xxx_read_status,
1143
+        .read_status    = as21xxx_read_status,
1050
+        .led_brightness_set = as21xxx_led_brightness_set,
1144
+        .led_brightness_set = as21xxx_led_brightness_set,
1051
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1145
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1052
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1146
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1053
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1147
+        .led_hw_control_get = as21xxx_led_hw_control_get,
...
...
diff view generated by jsdifflib
1
Document support for Aeonsemi PHYs and the requirement of a firmware to
1
Add Aeonsemi PHYs and the requirement of a firmware to correctly work.
2
correctly work. Also document the max number of LEDs supported and what
2
Also document the max number of LEDs supported and what PHY ID expose
3
PHY ID expose when no firmware is loaded.
3
when no firmware is loaded.
4
4
5
Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
5
Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
6
AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
6
AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
7
AS21210PB1 that all register with the PHY ID 0x7500 0x9410 on C45
7
AS21210PB1 that all register with the PHY ID 0x7500 0x9410 on C45
8
registers before the firmware is loaded.
8
registers before the firmware is loaded.
9
9
10
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
10
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
11
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
11
---
12
---
12
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++++++++++++++++++
13
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++++++++++++++++++
13
MAINTAINERS | 1 +
14
MAINTAINERS | 1 +
14
2 files changed, 123 insertions(+)
15
2 files changed, 123 insertions(+)
...
...
diff view generated by jsdifflib