...
...
26
struct, .match_phy_device is extended to provide also the
26
struct, .match_phy_device is extended to provide also the
27
current phy_driver is trying to match for. This add the
27
current phy_driver is trying to match for. This add the
28
extra benefits that some other PHY can simplify their
28
extra benefits that some other PHY can simplify their
29
.match_phy_device OP.
29
.match_phy_device OP.
30
30
31
Changes v6:
32
- Out of RFC
33
- Add Reviewed-by tag from Russell
31
Changes v5:
34
Changes v5:
32
- Add Reviewed-by tag from Rob
35
- Add Reviewed-by tag from Rob
33
- Fix subject in DT patch
36
- Fix subject in DT patch
34
- Fix wrong Suggested-by tag in patch 1
37
- Fix wrong Suggested-by tag in patch 1
35
- Rework nxp patch to 80 column
38
- Rework nxp patch to 80 column
...
...
diff view generated by jsdifflib
1
Pass PHY driver pointer to .match_phy_device OP in addition to phydev.
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
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
3
PHY ID of the driver is being matched for in case the PHY ID scanned in
4
the phydev is not consistent.
4
the phydev is not consistent.
5
5
6
A scenario for this is a PHY that change PHY ID after a firmware is
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
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
8
valid anymore and PHY will manually scan the ID in the match_phy_device
9
function.
9
function.
10
10
11
Having the PHY driver info is also useful for those PHY driver that
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
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
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
14
function can be generalized by using the phy_id in the PHY driver
15
instead of hardcoding.
15
instead of hardcoding.
16
16
17
Suggested-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
17
Suggested-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
18
Reviewed-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>
19
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
20
---
20
---
21
drivers/net/phy/bcm87xx.c | 6 ++++--
21
drivers/net/phy/bcm87xx.c | 6 ++++--
22
drivers/net/phy/icplus.c | 6 ++++--
22
drivers/net/phy/icplus.c | 6 ++++--
23
drivers/net/phy/marvell10g.c | 12 ++++++++----
23
drivers/net/phy/marvell10g.c | 12 ++++++++----
24
drivers/net/phy/micrel.c | 6 ++++--
24
drivers/net/phy/micrel.c | 6 ++++--
25
drivers/net/phy/nxp-c45-tja11xx.c | 12 ++++++++----
25
drivers/net/phy/nxp-c45-tja11xx.c | 12 ++++++++----
26
drivers/net/phy/nxp-tja11xx.c | 6 ++++--
26
drivers/net/phy/nxp-tja11xx.c | 6 ++++--
27
drivers/net/phy/phy_device.c | 2 +-
27
drivers/net/phy/phy_device.c | 2 +-
28
drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++---------
28
drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++---------
29
drivers/net/phy/teranetics.c | 3 ++-
29
drivers/net/phy/teranetics.c | 3 ++-
30
include/linux/phy.h | 3 ++-
30
include/linux/phy.h | 3 ++-
31
10 files changed, 55 insertions(+), 28 deletions(-)
31
10 files changed, 55 insertions(+), 28 deletions(-)
32
32
33
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
33
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
34
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
35
--- a/drivers/net/phy/bcm87xx.c
35
--- a/drivers/net/phy/bcm87xx.c
36
+++ b/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)
37
@@ -XXX,XX +XXX,XX @@ static irqreturn_t bcm87xx_handle_interrupt(struct phy_device *phydev)
38
    return IRQ_HANDLED;
38
    return IRQ_HANDLED;
39
}
39
}
40
40
41
-static int bcm8706_match_phy_device(struct phy_device *phydev)
41
-static int bcm8706_match_phy_device(struct phy_device *phydev)
42
+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)
43
+                 const struct phy_driver *phydrv)
44
{
44
{
45
    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706;
45
    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706;
46
}
46
}
47
47
48
-static int bcm8727_match_phy_device(struct phy_device *phydev)
48
-static int bcm8727_match_phy_device(struct phy_device *phydev)
49
+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)
50
+                 const struct phy_driver *phydrv)
51
{
51
{
52
    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727;
52
    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727;
53
}
53
}
54
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
54
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
55
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
56
--- a/drivers/net/phy/icplus.c
56
--- a/drivers/net/phy/icplus.c
57
+++ b/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)
58
@@ -XXX,XX +XXX,XX @@ static int ip101a_g_match_phy_device(struct phy_device *phydev, bool ip101a)
59
    return ip101a == !ret;
59
    return ip101a == !ret;
60
}
60
}
61
61
62
-static int ip101a_match_phy_device(struct phy_device *phydev)
62
-static int ip101a_match_phy_device(struct phy_device *phydev)
63
+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)
64
+                 const struct phy_driver *phydrv)
65
{
65
{
66
    return ip101a_g_match_phy_device(phydev, true);
66
    return ip101a_g_match_phy_device(phydev, true);
67
}
67
}
68
68
69
-static int ip101g_match_phy_device(struct phy_device *phydev)
69
-static int ip101g_match_phy_device(struct phy_device *phydev)
70
+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)
71
+                 const struct phy_driver *phydrv)
72
{
72
{
73
    return ip101a_g_match_phy_device(phydev, false);
73
    return ip101a_g_match_phy_device(phydev, false);
74
}
74
}
75
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
75
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
76
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
77
--- a/drivers/net/phy/marvell10g.c
77
--- a/drivers/net/phy/marvell10g.c
78
+++ b/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)
79
@@ -XXX,XX +XXX,XX @@ static int mv3310_get_number_of_ports(struct phy_device *phydev)
80
    return ret + 1;
80
    return ret + 1;
81
}
81
}
82
82
83
-static int mv3310_match_phy_device(struct phy_device *phydev)
83
-static int mv3310_match_phy_device(struct phy_device *phydev)
84
+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)
85
+                 const struct phy_driver *phydrv)
86
{
86
{
87
    if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
87
    if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
88
     MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
88
     MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
89
@@ -XXX,XX +XXX,XX @@ static int mv3310_match_phy_device(struct phy_device *phydev)
89
@@ -XXX,XX +XXX,XX @@ static int mv3310_match_phy_device(struct phy_device *phydev)
90
    return mv3310_get_number_of_ports(phydev) == 1;
90
    return mv3310_get_number_of_ports(phydev) == 1;
91
}
91
}
92
92
93
-static int mv3340_match_phy_device(struct phy_device *phydev)
93
-static int mv3340_match_phy_device(struct phy_device *phydev)
94
+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)
95
+                 const struct phy_driver *phydrv)
96
{
96
{
97
    if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
97
    if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
98
     MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
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)
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;
100
    return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
101
}
101
}
102
102
103
-static int mv2110_match_phy_device(struct phy_device *phydev)
103
-static int mv2110_match_phy_device(struct phy_device *phydev)
104
+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)
105
+                 const struct phy_driver *phydrv)
106
{
106
{
107
    return mv211x_match_phy_device(phydev, true);
107
    return mv211x_match_phy_device(phydev, true);
108
}
108
}
109
109
110
-static int mv2111_match_phy_device(struct phy_device *phydev)
110
-static int mv2111_match_phy_device(struct phy_device *phydev)
111
+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)
112
+                 const struct phy_driver *phydrv)
113
{
113
{
114
    return mv211x_match_phy_device(phydev, false);
114
    return mv211x_match_phy_device(phydev, false);
115
}
115
}
116
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
116
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
117
index XXXXXXX..XXXXXXX 100644
117
index XXXXXXX..XXXXXXX 100644
118
--- a/drivers/net/phy/micrel.c
118
--- a/drivers/net/phy/micrel.c
119
+++ b/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,
120
@@ -XXX,XX +XXX,XX @@ static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev,
121
        return !ret;
121
        return !ret;
122
}
122
}
123
123
124
-static int ksz8051_match_phy_device(struct phy_device *phydev)
124
-static int ksz8051_match_phy_device(struct phy_device *phydev)
125
+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)
126
+                 const struct phy_driver *phydrv)
127
{
127
{
128
    return ksz8051_ksz8795_match_phy_device(phydev, true);
128
    return ksz8051_ksz8795_match_phy_device(phydev, true);
129
}
129
}
130
@@ -XXX,XX +XXX,XX @@ static int ksz8061_config_init(struct phy_device *phydev)
130
@@ -XXX,XX +XXX,XX @@ static int ksz8061_config_init(struct phy_device *phydev)
131
    return kszphy_config_init(phydev);
131
    return kszphy_config_init(phydev);
132
}
132
}
133
133
134
-static int ksz8795_match_phy_device(struct phy_device *phydev)
134
-static int ksz8795_match_phy_device(struct phy_device *phydev)
135
+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)
136
+                 const struct phy_driver *phydrv)
137
{
137
{
138
    return ksz8051_ksz8795_match_phy_device(phydev, false);
138
    return ksz8051_ksz8795_match_phy_device(phydev, false);
139
}
139
}
140
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
140
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
141
index XXXXXXX..XXXXXXX 100644
141
index XXXXXXX..XXXXXXX 100644
142
--- a/drivers/net/phy/nxp-c45-tja11xx.c
142
--- a/drivers/net/phy/nxp-c45-tja11xx.c
143
+++ b/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)
144
@@ -XXX,XX +XXX,XX @@ static int nxp_c45_macsec_ability(struct phy_device *phydev)
145
    return macsec_ability;
145
    return macsec_ability;
146
}
146
}
147
147
148
-static int tja1103_match_phy_device(struct phy_device *phydev)
148
-static int tja1103_match_phy_device(struct phy_device *phydev)
149
+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)
150
+                 const struct phy_driver *phydrv)
151
{
151
{
152
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
152
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
153
     !nxp_c45_macsec_ability(phydev);
153
     !nxp_c45_macsec_ability(phydev);
154
}
154
}
155
155
156
-static int tja1104_match_phy_device(struct phy_device *phydev)
156
-static int tja1104_match_phy_device(struct phy_device *phydev)
157
+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)
158
+                 const struct phy_driver *phydrv)
159
{
159
{
160
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
160
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
161
     nxp_c45_macsec_ability(phydev);
161
     nxp_c45_macsec_ability(phydev);
162
}
162
}
163
163
164
-static int tja1120_match_phy_device(struct phy_device *phydev)
164
-static int tja1120_match_phy_device(struct phy_device *phydev)
165
+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)
166
+                 const struct phy_driver *phydrv)
167
{
167
{
168
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
168
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
169
     !nxp_c45_macsec_ability(phydev);
169
     !nxp_c45_macsec_ability(phydev);
170
}
170
}
171
171
172
-static int tja1121_match_phy_device(struct phy_device *phydev)
172
-static int tja1121_match_phy_device(struct phy_device *phydev)
173
+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)
174
+                 const struct phy_driver *phydrv)
175
{
175
{
176
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
176
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
177
     nxp_c45_macsec_ability(phydev);
177
     nxp_c45_macsec_ability(phydev);
178
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
178
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
179
index XXXXXXX..XXXXXXX 100644
179
index XXXXXXX..XXXXXXX 100644
180
--- a/drivers/net/phy/nxp-tja11xx.c
180
--- a/drivers/net/phy/nxp-tja11xx.c
181
+++ b/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)
182
@@ -XXX,XX +XXX,XX @@ static int tja1102_match_phy_device(struct phy_device *phydev, bool port0)
183
    return !ret;
183
    return !ret;
184
}
184
}
185
185
186
-static int tja1102_p0_match_phy_device(struct phy_device *phydev)
186
-static int tja1102_p0_match_phy_device(struct phy_device *phydev)
187
+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)
188
+                 const struct phy_driver *phydrv)
189
{
189
{
190
    return tja1102_match_phy_device(phydev, true);
190
    return tja1102_match_phy_device(phydev, true);
191
}
191
}
192
192
193
-static int tja1102_p1_match_phy_device(struct phy_device *phydev)
193
-static int tja1102_p1_match_phy_device(struct phy_device *phydev)
194
+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)
195
+                 const struct phy_driver *phydrv)
196
{
196
{
197
    return tja1102_match_phy_device(phydev, false);
197
    return tja1102_match_phy_device(phydev, false);
198
}
198
}
199
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
199
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
200
index XXXXXXX..XXXXXXX 100644
200
index XXXXXXX..XXXXXXX 100644
201
--- a/drivers/net/phy/phy_device.c
201
--- a/drivers/net/phy/phy_device.c
202
+++ b/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)
203
@@ -XXX,XX +XXX,XX @@ static int phy_bus_match(struct device *dev, const struct device_driver *drv)
204
        return 0;
204
        return 0;
205
205
206
    if (phydrv->match_phy_device)
206
    if (phydrv->match_phy_device)
207
-        return phydrv->match_phy_device(phydev);
207
-        return phydrv->match_phy_device(phydev);
208
+        return phydrv->match_phy_device(phydev, phydrv);
208
+        return phydrv->match_phy_device(phydev, phydrv);
209
209
210
    if (phydev->is_c45) {
210
    if (phydev->is_c45) {
211
        for (i = 1; i < num_ids; i++) {
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
212
diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
213
index XXXXXXX..XXXXXXX 100644
213
index XXXXXXX..XXXXXXX 100644
214
--- a/drivers/net/phy/realtek/realtek_main.c
214
--- a/drivers/net/phy/realtek/realtek_main.c
215
+++ b/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)
216
@@ -XXX,XX +XXX,XX @@ static bool rtlgen_supports_mmd(struct phy_device *phydev)
217
    return val > 0;
217
    return val > 0;
218
}
218
}
219
219
220
-static int rtlgen_match_phy_device(struct phy_device *phydev)
220
-static int rtlgen_match_phy_device(struct phy_device *phydev)
221
+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)
222
+                 const struct phy_driver *phydrv)
223
{
223
{
224
    return phydev->phy_id == RTL_GENERIC_PHYID &&
224
    return phydev->phy_id == RTL_GENERIC_PHYID &&
225
     !rtlgen_supports_2_5gbps(phydev);
225
     !rtlgen_supports_2_5gbps(phydev);
226
}
226
}
227
227
228
-static int rtl8226_match_phy_device(struct phy_device *phydev)
228
-static int rtl8226_match_phy_device(struct phy_device *phydev)
229
+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)
230
+                 const struct phy_driver *phydrv)
231
{
231
{
232
    return phydev->phy_id == RTL_GENERIC_PHYID &&
232
    return phydev->phy_id == RTL_GENERIC_PHYID &&
233
     rtlgen_supports_2_5gbps(phydev) &&
233
     rtlgen_supports_2_5gbps(phydev) &&
234
@@ -XXX,XX +XXX,XX @@ static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
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);
235
        return !is_c45 && (id == phydev->phy_id);
236
}
236
}
237
237
238
-static int rtl8221b_match_phy_device(struct phy_device *phydev)
238
-static int rtl8221b_match_phy_device(struct phy_device *phydev)
239
+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)
240
+                 const struct phy_driver *phydrv)
241
{
241
{
242
    return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev);
242
    return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev);
243
}
243
}
244
244
245
-static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
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,
246
+static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev,
247
+                     const struct phy_driver *phydrv)
247
+                     const struct phy_driver *phydrv)
248
{
248
{
249
    return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
249
    return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
250
}
250
}
251
251
252
-static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev)
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,
253
+static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev,
254
+                     const struct phy_driver *phydrv)
254
+                     const struct phy_driver *phydrv)
255
{
255
{
256
    return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
256
    return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
257
}
257
}
258
258
259
-static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev)
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,
260
+static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev,
261
+                     const struct phy_driver *phydrv)
261
+                     const struct phy_driver *phydrv)
262
{
262
{
263
    return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false);
263
    return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false);
264
}
264
}
265
265
266
-static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev)
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,
267
+static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev,
268
+                     const struct phy_driver *phydrv)
268
+                     const struct phy_driver *phydrv)
269
{
269
{
270
    return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
270
    return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
271
}
271
}
272
272
273
-static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev)
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,
274
+static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev,
275
+                        const struct phy_driver *phydrv)
275
+                        const struct phy_driver *phydrv)
276
{
276
{
277
    if (phydev->is_c45)
277
    if (phydev->is_c45)
278
        return false;
278
        return false;
279
@@ -XXX,XX +XXX,XX @@ static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev)
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);
280
    return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev);
281
}
281
}
282
282
283
-static int rtl8251b_c45_match_phy_device(struct phy_device *phydev)
283
-static int rtl8251b_c45_match_phy_device(struct phy_device *phydev)
284
+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)
285
+                     const struct phy_driver *phydrv)
286
{
286
{
287
    return rtlgen_is_c45_match(phydev, RTL_8251B, true);
287
    return rtlgen_is_c45_match(phydev, RTL_8251B, true);
288
}
288
}
289
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
289
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
290
index XXXXXXX..XXXXXXX 100644
290
index XXXXXXX..XXXXXXX 100644
291
--- a/drivers/net/phy/teranetics.c
291
--- a/drivers/net/phy/teranetics.c
292
+++ b/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)
293
@@ -XXX,XX +XXX,XX @@ static int teranetics_read_status(struct phy_device *phydev)
294
    return 0;
294
    return 0;
295
}
295
}
296
296
297
-static int teranetics_match_phy_device(struct phy_device *phydev)
297
-static int teranetics_match_phy_device(struct phy_device *phydev)
298
+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)
299
+                 const struct phy_driver *phydrv)
300
{
300
{
301
    return phydev->c45_ids.device_ids[3] == PHY_ID_TN2020;
301
    return phydev->c45_ids.device_ids[3] == PHY_ID_TN2020;
302
}
302
}
303
diff --git a/include/linux/phy.h b/include/linux/phy.h
303
diff --git a/include/linux/phy.h b/include/linux/phy.h
304
index XXXXXXX..XXXXXXX 100644
304
index XXXXXXX..XXXXXXX 100644
305
--- a/include/linux/phy.h
305
--- a/include/linux/phy.h
306
+++ b/include/linux/phy.h
306
+++ b/include/linux/phy.h
307
@@ -XXX,XX +XXX,XX @@ struct phy_driver {
307
@@ -XXX,XX +XXX,XX @@ struct phy_driver {
308
     * driver for the given phydev.     If NULL, matching is based on
308
     * driver for the given phydev.     If NULL, matching is based on
309
     * phy_id and phy_id_mask.
309
     * phy_id and phy_id_mask.
310
     */
310
     */
311
-    int (*match_phy_device)(struct phy_device *phydev);
311
-    int (*match_phy_device)(struct phy_device *phydev);
312
+    int (*match_phy_device)(struct phy_device *phydev,
312
+    int (*match_phy_device)(struct phy_device *phydev,
313
+                const struct phy_driver *phydrv);
313
+                const struct phy_driver *phydrv);
314
314
315
    /**
315
    /**
316
     * @set_wol: Some devices (e.g. qnap TS-119P II) require PHY
316
     * @set_wol: Some devices (e.g. qnap TS-119P II) require PHY
317
--
317
--
318
2.48.1
318
2.48.1
diff view generated by jsdifflib
1
Simplify .match_phy_device OP by using a generic function and using the
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.
2
new phy_id PHY driver info instead of hardcoding the matching PHY ID.
3
3
4
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
4
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
5
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
5
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
6
---
6
---
7
drivers/net/phy/bcm87xx.c | 14 ++++----------
7
drivers/net/phy/bcm87xx.c | 14 ++++----------
8
1 file changed, 4 insertions(+), 10 deletions(-)
8
1 file changed, 4 insertions(+), 10 deletions(-)
9
9
10
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
10
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
11
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
12
--- a/drivers/net/phy/bcm87xx.c
12
--- a/drivers/net/phy/bcm87xx.c
13
+++ b/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)
14
@@ -XXX,XX +XXX,XX @@ static irqreturn_t bcm87xx_handle_interrupt(struct phy_device *phydev)
15
    return IRQ_HANDLED;
15
    return IRQ_HANDLED;
16
}
16
}
17
17
18
-static int bcm8706_match_phy_device(struct phy_device *phydev,
18
-static int bcm8706_match_phy_device(struct phy_device *phydev,
19
+static int bcm87xx_match_phy_device(struct phy_device *phydev,
19
+static int bcm87xx_match_phy_device(struct phy_device *phydev,
20
                 const struct phy_driver *phydrv)
20
                 const struct phy_driver *phydrv)
21
{
21
{
22
-    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706;
22
-    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706;
23
-}
23
-}
24
-
24
-
25
-static int bcm8727_match_phy_device(struct phy_device *phydev,
25
-static int bcm8727_match_phy_device(struct phy_device *phydev,
26
-                 const struct phy_driver *phydrv)
26
-                 const struct phy_driver *phydrv)
27
-{
27
-{
28
-    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727;
28
-    return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727;
29
+    return phydev->c45_ids.device_ids[4] == phydrv->phy_id;
29
+    return phydev->c45_ids.device_ids[4] == phydrv->phy_id;
30
}
30
}
31
31
32
static struct phy_driver bcm87xx_driver[] = {
32
static struct phy_driver bcm87xx_driver[] = {
33
@@ -XXX,XX +XXX,XX @@ static struct phy_driver bcm87xx_driver[] = {
33
@@ -XXX,XX +XXX,XX @@ static struct phy_driver bcm87xx_driver[] = {
34
    .read_status    = bcm87xx_read_status,
34
    .read_status    = bcm87xx_read_status,
35
    .config_intr    = bcm87xx_config_intr,
35
    .config_intr    = bcm87xx_config_intr,
36
    .handle_interrupt = bcm87xx_handle_interrupt,
36
    .handle_interrupt = bcm87xx_handle_interrupt,
37
-    .match_phy_device = bcm8706_match_phy_device,
37
-    .match_phy_device = bcm8706_match_phy_device,
38
+    .match_phy_device = bcm87xx_match_phy_device,
38
+    .match_phy_device = bcm87xx_match_phy_device,
39
}, {
39
}, {
40
    .phy_id        = PHY_ID_BCM8727,
40
    .phy_id        = PHY_ID_BCM8727,
41
    .phy_id_mask    = 0xffffffff,
41
    .phy_id_mask    = 0xffffffff,
42
@@ -XXX,XX +XXX,XX @@ static struct phy_driver bcm87xx_driver[] = {
42
@@ -XXX,XX +XXX,XX @@ static struct phy_driver bcm87xx_driver[] = {
43
    .read_status    = bcm87xx_read_status,
43
    .read_status    = bcm87xx_read_status,
44
    .config_intr    = bcm87xx_config_intr,
44
    .config_intr    = bcm87xx_config_intr,
45
    .handle_interrupt = bcm87xx_handle_interrupt,
45
    .handle_interrupt = bcm87xx_handle_interrupt,
46
-    .match_phy_device = bcm8727_match_phy_device,
46
-    .match_phy_device = bcm8727_match_phy_device,
47
+    .match_phy_device = bcm87xx_match_phy_device,
47
+    .match_phy_device = bcm87xx_match_phy_device,
48
} };
48
} };
49
49
50
module_phy_driver(bcm87xx_driver);
50
module_phy_driver(bcm87xx_driver);
51
--
51
--
52
2.48.1
52
2.48.1
diff view generated by jsdifflib
...
...
3
with new variant for macsec and no_macsec PHYs.
3
with new variant for macsec and no_macsec PHYs.
4
4
5
Also make use of PHY_ID_MATCH_MODEL macro and drop PHY_ID_MASK define to
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.
6
introduce phy_id and phy_id_mask again in phy_driver struct.
7
7
8
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
8
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
9
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
9
---
10
---
10
drivers/net/phy/nxp-c45-tja11xx.c | 45 ++++++++++++++-----------------
11
drivers/net/phy/nxp-c45-tja11xx.c | 45 ++++++++++++++-----------------
11
1 file changed, 20 insertions(+), 25 deletions(-)
12
1 file changed, 20 insertions(+), 25 deletions(-)
12
13
...
...
diff view generated by jsdifflib
...
...
7
7
8
This is useful for custom .match_phy_device function that wants to use
8
This is useful for custom .match_phy_device function that wants to use
9
the generic logic under some condition. (example a PHY is already setup
9
the generic logic under some condition. (example a PHY is already setup
10
and provide the correct PHY ID)
10
and provide the correct PHY ID)
11
11
12
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
12
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
13
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
13
---
14
---
14
drivers/net/phy/phy_device.c | 52 +++++++++++++++++++++++++-----------
15
drivers/net/phy/phy_device.c | 52 +++++++++++++++++++++++++-----------
15
include/linux/phy.h | 3 +++
16
include/linux/phy.h | 3 +++
16
2 files changed, 40 insertions(+), 15 deletions(-)
17
2 files changed, 40 insertions(+), 15 deletions(-)
...
...
diff view generated by jsdifflib
1
Add support for Aeonsemi AS21xxx 10G C45 PHYs. These PHYs integrate
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,
7
AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
7
AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
8
AS21210PB1 that all register with the PHY ID 0x7500 0x7510
8
AS21210PB1 that all register with the PHY ID 0x7500 0x7510
9
before the firmware is loaded.
9
before the firmware is loaded.
10
10
11
They all support up to 5 LEDs with various HW mode supported.
11
They all support up to 5 LEDs with various HW mode supported.
12
12
13
While implementing it was found some strange coincidence with using the
13
While implementing it was found some strange coincidence with using the
14
same logic for implementing C22 in MMD regs in Broadcom PHYs.
14
same logic for implementing C22 in MMD regs in Broadcom PHYs.
15
15
16
For reference here the AS21xxx PHY name logic:
16
For reference here the AS21xxx PHY name logic:
17
17
18
AS21x1xxB1
18
AS21x1xxB1
19
^ ^^
19
^ ^^
20
| |J: Supports SyncE/PTP
20
| |J: Supports SyncE/PTP
21
| |P: No SyncE/PTP support
21
| |P: No SyncE/PTP support
22
| 1: Supports 2nd Serdes
22
| 1: Supports 2nd Serdes
23
| 2: Not 2nd Serdes support
23
| 2: Not 2nd Serdes support
24
0: 10G, 5G, 2.5G
24
0: 10G, 5G, 2.5G
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 | 1067 +++++++++++++++++++++++++++++++++++++
33
drivers/net/phy/as21xxx.c | 1067 +++++++++++++++++++++++++++++++++++++
34
4 files changed, 1086 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
40
+++ b/MAINTAINERS
40
+++ b/MAINTAINERS
41
@@ -XXX,XX +XXX,XX @@ F:    drivers/iio/accel/adxl380.h
41
@@ -XXX,XX +XXX,XX @@ F:    drivers/iio/accel/adxl380.h
42
F:    drivers/iio/accel/adxl380_i2c.c
42
F:    drivers/iio/accel/adxl380_i2c.c
43
F:    drivers/iio/accel/adxl380_spi.c
43
F:    drivers/iio/accel/adxl380_spi.c
44
44
45
+AEONSEMI PHY DRIVER
45
+AEONSEMI PHY DRIVER
46
+M:    Christian Marangi <ansuelsmth@gmail.com>
46
+M:    Christian Marangi <ansuelsmth@gmail.com>
47
+L:    netdev@vger.kernel.org
47
+L:    netdev@vger.kernel.org
48
+S:    Maintained
48
+S:    Maintained
49
+F:    drivers/net/phy/as21xxx.c
49
+F:    drivers/net/phy/as21xxx.c
50
+
50
+
51
AF8133J THREE-AXIS MAGNETOMETER DRIVER
51
AF8133J THREE-AXIS MAGNETOMETER DRIVER
52
M:    Ondřej Jirman <megi@xff.cz>
52
M:    Ondřej Jirman <megi@xff.cz>
53
S:    Maintained
53
S:    Maintained
54
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
54
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
55
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
56
--- a/drivers/net/phy/Kconfig
56
--- a/drivers/net/phy/Kconfig
57
+++ b/drivers/net/phy/Kconfig
57
+++ b/drivers/net/phy/Kconfig
58
@@ -XXX,XX +XXX,XX @@ config AMCC_QT2025_PHY
58
@@ -XXX,XX +XXX,XX @@ config AMCC_QT2025_PHY
59
    help
59
    help
60
     Adds support for the Applied Micro Circuits Corporation QT2025 PHY.
60
     Adds support for the Applied Micro Circuits Corporation QT2025 PHY.
61
61
62
+config AS21XXX_PHY
62
+config AS21XXX_PHY
63
+    tristate "Aeonsemi AS21xxx PHYs"
63
+    tristate "Aeonsemi AS21xxx PHYs"
64
+    help
64
+    help
65
+     Currently supports the Aeonsemi AS21xxx PHY.
65
+     Currently supports the Aeonsemi AS21xxx PHY.
66
+
66
+
67
+     These are C45 PHYs 10G that require all a generic firmware.
67
+     These are C45 PHYs 10G that require all a generic firmware.
68
+
68
+
69
+     Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
69
+     Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
70
+     AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
70
+     AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
71
+     AS21210PB1 that all register with the PHY ID 0x7500 0x7500
71
+     AS21210PB1 that all register with the PHY ID 0x7500 0x7500
72
+     before the firmware is loaded.
72
+     before the firmware is loaded.
73
+
73
+
74
source "drivers/net/phy/aquantia/Kconfig"
74
source "drivers/net/phy/aquantia/Kconfig"
75
75
76
config AX88796B_PHY
76
config AX88796B_PHY
77
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
77
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
78
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
79
--- a/drivers/net/phy/Makefile
79
--- a/drivers/net/phy/Makefile
80
+++ b/drivers/net/phy/Makefile
80
+++ b/drivers/net/phy/Makefile
81
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o
81
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o
82
obj-$(CONFIG_AMD_PHY)        += amd.o
82
obj-$(CONFIG_AMD_PHY)        += amd.o
83
obj-$(CONFIG_AMCC_QT2025_PHY)    += qt2025.o
83
obj-$(CONFIG_AMCC_QT2025_PHY)    += qt2025.o
84
obj-$(CONFIG_AQUANTIA_PHY)    += aquantia/
84
obj-$(CONFIG_AQUANTIA_PHY)    += aquantia/
85
+obj-$(CONFIG_AS21XXX_PHY)    += as21xxx.o
85
+obj-$(CONFIG_AS21XXX_PHY)    += as21xxx.o
86
ifdef CONFIG_AX88796B_RUST_PHY
86
ifdef CONFIG_AX88796B_RUST_PHY
87
obj-$(CONFIG_AX88796B_PHY)    += ax88796b_rust.o
87
obj-$(CONFIG_AX88796B_PHY)    += ax88796b_rust.o
88
else
88
else
89
diff --git a/drivers/net/phy/as21xxx.c b/drivers/net/phy/as21xxx.c
89
diff --git a/drivers/net/phy/as21xxx.c b/drivers/net/phy/as21xxx.c
90
new file mode 100644
90
new file mode 100644
91
index XXXXXXX..XXXXXXX
91
index XXXXXXX..XXXXXXX
92
--- /dev/null
92
--- /dev/null
93
+++ b/drivers/net/phy/as21xxx.c
93
+++ b/drivers/net/phy/as21xxx.c
94
@@ -XXX,XX +XXX,XX @@
94
@@ -XXX,XX +XXX,XX @@
95
+// SPDX-License-Identifier: GPL-2.0
95
+// SPDX-License-Identifier: GPL-2.0
96
+/*
96
+/*
97
+ * Aeonsemi AS21XXxX PHY Driver
97
+ * Aeonsemi AS21XXxX PHY Driver
98
+ *
98
+ *
99
+ * Author: Christian Marangi <ansuelsmth@gmail.com>
99
+ * Author: Christian Marangi <ansuelsmth@gmail.com>
100
+ */
100
+ */
101
+
101
+
102
+#include <linux/bitfield.h>
102
+#include <linux/bitfield.h>
103
+#include <linux/firmware.h>
103
+#include <linux/firmware.h>
104
+#include <linux/module.h>
104
+#include <linux/module.h>
105
+#include <linux/of.h>
105
+#include <linux/of.h>
106
+#include <linux/phy.h>
106
+#include <linux/phy.h>
107
+
107
+
108
+#define VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR 0x3
108
+#define VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR 0x3
109
+#define VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR 0x4
109
+#define VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR 0x4
110
+
110
+
111
+#define VEND1_GLB_REG_CPU_CTRL        0xe
111
+#define VEND1_GLB_REG_CPU_CTRL        0xe
112
+#define VEND1_GLB_CPU_CTRL_MASK    GENMASK(4, 0)
112
+#define VEND1_GLB_CPU_CTRL_MASK    GENMASK(4, 0)
113
+#define VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK GENMASK(12, 8)
113
+#define VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK GENMASK(12, 8)
114
+#define VEND1_GLB_CPU_CTRL_LED_POLARITY(_n) FIELD_PREP(VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK, \
114
+#define VEND1_GLB_CPU_CTRL_LED_POLARITY(_n) FIELD_PREP(VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK, \
115
+                             BIT(_n))
115
+                             BIT(_n))
116
+
116
+
117
+#define VEND1_FW_START_ADDR        0x100
117
+#define VEND1_FW_START_ADDR        0x100
118
+
118
+
119
+#define VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD 0x101
119
+#define VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD 0x101
120
+#define VEND1_GLB_REG_MDIO_INDIRECT_LOAD 0x102
120
+#define VEND1_GLB_REG_MDIO_INDIRECT_LOAD 0x102
121
+
121
+
122
+#define VEND1_GLB_REG_MDIO_INDIRECT_STATUS 0x103
122
+#define VEND1_GLB_REG_MDIO_INDIRECT_STATUS 0x103
123
+
123
+
124
+#define VEND1_PTP_CLK            0x142
124
+#define VEND1_PTP_CLK            0x142
125
+#define VEND1_PTP_CLK_EN        BIT(6)
125
+#define VEND1_PTP_CLK_EN        BIT(6)
126
+
126
+
127
+/* 5 LED at step of 0x20
127
+/* 5 LED at step of 0x20
128
+ * FE: Fast-Ethernet (10/100)
128
+ * FE: Fast-Ethernet (10/100)
129
+ * GE: Gigabit-Ethernet (1000)
129
+ * GE: Gigabit-Ethernet (1000)
130
+ * NG: New-Generation (2500/5000/10000)
130
+ * NG: New-Generation (2500/5000/10000)
131
+ */
131
+ */
132
+#define VEND1_LED_REG(_n)        (0x1800 + ((_n) * 0x10))
132
+#define VEND1_LED_REG(_n)        (0x1800 + ((_n) * 0x10))
133
+#define VEND1_LED_REG_A_EVENT        GENMASK(15, 11)
133
+#define VEND1_LED_REG_A_EVENT        GENMASK(15, 11)
134
+#define VEND1_LED_CONF            0x1881
134
+#define VEND1_LED_CONF            0x1881
135
+#define VEND1_LED_CONFG_BLINK        GENMASK(7, 0)
135
+#define VEND1_LED_CONFG_BLINK        GENMASK(7, 0)
136
+
136
+
137
+#define VEND1_SPEED_STATUS        0x4002
137
+#define VEND1_SPEED_STATUS        0x4002
138
+#define VEND1_SPEED_MASK        GENMASK(7, 0)
138
+#define VEND1_SPEED_MASK        GENMASK(7, 0)
139
+#define VEND1_SPEED_10000        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x3)
139
+#define VEND1_SPEED_10000        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x3)
140
+#define VEND1_SPEED_5000        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x5)
140
+#define VEND1_SPEED_5000        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x5)
141
+#define VEND1_SPEED_2500        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x9)
141
+#define VEND1_SPEED_2500        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x9)
142
+#define VEND1_SPEED_1000        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x10)
142
+#define VEND1_SPEED_1000        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x10)
143
+#define VEND1_SPEED_100        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x20)
143
+#define VEND1_SPEED_100        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x20)
144
+#define VEND1_SPEED_10        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x0)
144
+#define VEND1_SPEED_10        FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x0)
145
+
145
+
146
+#define VEND1_IPC_CMD            0x5801
146
+#define VEND1_IPC_CMD            0x5801
147
+#define AEON_IPC_CMD_PARITY        BIT(15)
147
+#define AEON_IPC_CMD_PARITY        BIT(15)
148
+#define AEON_IPC_CMD_SIZE        GENMASK(10, 6)
148
+#define AEON_IPC_CMD_SIZE        GENMASK(10, 6)
149
+#define AEON_IPC_CMD_OPCODE        GENMASK(5, 0)
149
+#define AEON_IPC_CMD_OPCODE        GENMASK(5, 0)
150
+
150
+
151
+#define IPC_CMD_NOOP            0x0 /* Do nothing */
151
+#define IPC_CMD_NOOP            0x0 /* Do nothing */
152
+#define IPC_CMD_INFO            0x1 /* Get Firmware Version */
152
+#define IPC_CMD_INFO            0x1 /* Get Firmware Version */
153
+#define IPC_CMD_SYS_CPU            0x2 /* SYS_CPU */
153
+#define IPC_CMD_SYS_CPU            0x2 /* SYS_CPU */
154
+#define IPC_CMD_BULK_DATA        0xa /* Pass bulk data in ipc registers. */
154
+#define IPC_CMD_BULK_DATA        0xa /* Pass bulk data in ipc registers. */
155
+#define IPC_CMD_BULK_WRITE        0xc /* Write bulk data to memory */
155
+#define IPC_CMD_BULK_WRITE        0xc /* Write bulk data to memory */
156
+#define IPC_CMD_CFG_PARAM        0x1a /* Write config parameters to memory */
156
+#define IPC_CMD_CFG_PARAM        0x1a /* Write config parameters to memory */
157
+#define IPC_CMD_NG_TESTMODE        0x1b /* Set NG test mode and tone */
157
+#define IPC_CMD_NG_TESTMODE        0x1b /* Set NG test mode and tone */
158
+#define IPC_CMD_TEMP_MON        0x15 /* Temperature monitoring function */
158
+#define IPC_CMD_TEMP_MON        0x15 /* Temperature monitoring function */
159
+#define IPC_CMD_SET_LED            0x23 /* Set led */
159
+#define IPC_CMD_SET_LED            0x23 /* Set led */
160
+
160
+
161
+#define VEND1_IPC_STS            0x5802
161
+#define VEND1_IPC_STS            0x5802
162
+#define AEON_IPC_STS_PARITY        BIT(15)
162
+#define AEON_IPC_STS_PARITY        BIT(15)
163
+#define AEON_IPC_STS_SIZE        GENMASK(14, 10)
163
+#define AEON_IPC_STS_SIZE        GENMASK(14, 10)
164
+#define AEON_IPC_STS_OPCODE        GENMASK(9, 4)
164
+#define AEON_IPC_STS_OPCODE        GENMASK(9, 4)
165
+#define AEON_IPC_STS_STATUS        GENMASK(3, 0)
165
+#define AEON_IPC_STS_STATUS        GENMASK(3, 0)
166
+#define AEON_IPC_STS_STATUS_RCVD    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x1)
166
+#define AEON_IPC_STS_STATUS_RCVD    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x1)
167
+#define AEON_IPC_STS_STATUS_PROCESS    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x2)
167
+#define AEON_IPC_STS_STATUS_PROCESS    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x2)
168
+#define AEON_IPC_STS_STATUS_SUCCESS    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x4)
168
+#define AEON_IPC_STS_STATUS_SUCCESS    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x4)
169
+#define AEON_IPC_STS_STATUS_ERROR    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x8)
169
+#define AEON_IPC_STS_STATUS_ERROR    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x8)
170
+#define AEON_IPC_STS_STATUS_BUSY    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xe)
170
+#define AEON_IPC_STS_STATUS_BUSY    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xe)
171
+#define AEON_IPC_STS_STATUS_READY    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xf)
171
+#define AEON_IPC_STS_STATUS_READY    FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xf)
172
+
172
+
173
+#define VEND1_IPC_DATA0            0x5808
173
+#define VEND1_IPC_DATA0            0x5808
174
+#define VEND1_IPC_DATA1            0x5809
174
+#define VEND1_IPC_DATA1            0x5809
175
+#define VEND1_IPC_DATA2            0x580a
175
+#define VEND1_IPC_DATA2            0x580a
176
+#define VEND1_IPC_DATA3            0x580b
176
+#define VEND1_IPC_DATA3            0x580b
177
+#define VEND1_IPC_DATA4            0x580c
177
+#define VEND1_IPC_DATA4            0x580c
178
+#define VEND1_IPC_DATA5            0x580d
178
+#define VEND1_IPC_DATA5            0x580d
179
+#define VEND1_IPC_DATA6            0x580e
179
+#define VEND1_IPC_DATA6            0x580e
180
+#define VEND1_IPC_DATA7            0x580f
180
+#define VEND1_IPC_DATA7            0x580f
181
+#define VEND1_IPC_DATA(_n)        (VEND1_IPC_DATA0 + (_n))
181
+#define VEND1_IPC_DATA(_n)        (VEND1_IPC_DATA0 + (_n))
182
+
182
+
183
+/* Sub command of CMD_INFO */
183
+/* Sub command of CMD_INFO */
184
+#define IPC_INFO_VERSION        0x1
184
+#define IPC_INFO_VERSION        0x1
185
+
185
+
186
+/* Sub command of CMD_SYS_CPU */
186
+/* Sub command of CMD_SYS_CPU */
187
+#define IPC_SYS_CPU_REBOOT        0x3
187
+#define IPC_SYS_CPU_REBOOT        0x3
188
+#define IPC_SYS_CPU_IMAGE_OFST        0x4
188
+#define IPC_SYS_CPU_IMAGE_OFST        0x4
189
+#define IPC_SYS_CPU_IMAGE_CHECK        0x5
189
+#define IPC_SYS_CPU_IMAGE_CHECK        0x5
190
+#define IPC_SYS_CPU_PHY_ENABLE        0x6
190
+#define IPC_SYS_CPU_PHY_ENABLE        0x6
191
+
191
+
192
+/* Sub command of CMD_CFG_PARAM */
192
+/* Sub command of CMD_CFG_PARAM */
193
+#define IPC_CFG_PARAM_DIRECT        0x4
193
+#define IPC_CFG_PARAM_DIRECT        0x4
194
+
194
+
195
+/* CFG DIRECT sub command */
195
+/* CFG DIRECT sub command */
196
+#define IPC_CFG_PARAM_DIRECT_NG_PHYCTRL    0x1
196
+#define IPC_CFG_PARAM_DIRECT_NG_PHYCTRL    0x1
197
+#define IPC_CFG_PARAM_DIRECT_CU_AN    0x2
197
+#define IPC_CFG_PARAM_DIRECT_CU_AN    0x2
198
+#define IPC_CFG_PARAM_DIRECT_SDS_PCS    0x3
198
+#define IPC_CFG_PARAM_DIRECT_SDS_PCS    0x3
199
+#define IPC_CFG_PARAM_DIRECT_AUTO_EEE    0x4
199
+#define IPC_CFG_PARAM_DIRECT_AUTO_EEE    0x4
200
+#define IPC_CFG_PARAM_DIRECT_SDS_PMA    0x5
200
+#define IPC_CFG_PARAM_DIRECT_SDS_PMA    0x5
201
+#define IPC_CFG_PARAM_DIRECT_DPC_RA    0x6
201
+#define IPC_CFG_PARAM_DIRECT_DPC_RA    0x6
202
+#define IPC_CFG_PARAM_DIRECT_DPC_PKT_CHK 0x7
202
+#define IPC_CFG_PARAM_DIRECT_DPC_PKT_CHK 0x7
203
+#define IPC_CFG_PARAM_DIRECT_DPC_SDS_WAIT_ETH 0x8
203
+#define IPC_CFG_PARAM_DIRECT_DPC_SDS_WAIT_ETH 0x8
204
+#define IPC_CFG_PARAM_DIRECT_WDT    0x9
204
+#define IPC_CFG_PARAM_DIRECT_WDT    0x9
205
+#define IPC_CFG_PARAM_DIRECT_SDS_RESTART_AN 0x10
205
+#define IPC_CFG_PARAM_DIRECT_SDS_RESTART_AN 0x10
206
+#define IPC_CFG_PARAM_DIRECT_TEMP_MON    0x11
206
+#define IPC_CFG_PARAM_DIRECT_TEMP_MON    0x11
207
+#define IPC_CFG_PARAM_DIRECT_WOL    0x12
207
+#define IPC_CFG_PARAM_DIRECT_WOL    0x12
208
+
208
+
209
+/* Sub command of CMD_TEMP_MON */
209
+/* Sub command of CMD_TEMP_MON */
210
+#define IPC_CMD_TEMP_MON_GET        0x4
210
+#define IPC_CMD_TEMP_MON_GET        0x4
211
+
211
+
212
+#define AS21XXX_MDIO_AN_C22        0xffe0
212
+#define AS21XXX_MDIO_AN_C22        0xffe0
213
+
213
+
214
+#define PHY_ID_AS21XXX            0x75009410
214
+#define PHY_ID_AS21XXX            0x75009410
215
+/* AS21xxx ID Legend
215
+/* AS21xxx ID Legend
216
+ * AS21x1xxB1
216
+ * AS21x1xxB1
217
+ * ^ ^^
217
+ * ^ ^^
218
+ * | |J: Supports SyncE/PTP
218
+ * | |J: Supports SyncE/PTP
219
+ * | |P: No SyncE/PTP support
219
+ * | |P: No SyncE/PTP support
220
+ * | 1: Supports 2nd Serdes
220
+ * | 1: Supports 2nd Serdes
221
+ * | 2: Not 2nd Serdes support
221
+ * | 2: Not 2nd Serdes support
222
+ * 0: 10G, 5G, 2.5G
222
+ * 0: 10G, 5G, 2.5G
223
+ * 5: 5G, 2.5G
223
+ * 5: 5G, 2.5G
224
+ * 2: 2.5G
224
+ * 2: 2.5G
225
+ */
225
+ */
226
+#define PHY_ID_AS21011JB1        0x75009402
226
+#define PHY_ID_AS21011JB1        0x75009402
227
+#define PHY_ID_AS21011PB1        0x75009412
227
+#define PHY_ID_AS21011PB1        0x75009412
228
+#define PHY_ID_AS21010JB1        0x75009422
228
+#define PHY_ID_AS21010JB1        0x75009422
229
+#define PHY_ID_AS21010PB1        0x75009432
229
+#define PHY_ID_AS21010PB1        0x75009432
230
+#define PHY_ID_AS21511JB1        0x75009442
230
+#define PHY_ID_AS21511JB1        0x75009442
231
+#define PHY_ID_AS21511PB1        0x75009452
231
+#define PHY_ID_AS21511PB1        0x75009452
232
+#define PHY_ID_AS21510JB1        0x75009462
232
+#define PHY_ID_AS21510JB1        0x75009462
233
+#define PHY_ID_AS21510PB1        0x75009472
233
+#define PHY_ID_AS21510PB1        0x75009472
234
+#define PHY_ID_AS21210JB1        0x75009482
234
+#define PHY_ID_AS21210JB1        0x75009482
235
+#define PHY_ID_AS21210PB1        0x75009492
235
+#define PHY_ID_AS21210PB1        0x75009492
236
+#define PHY_VENDOR_AEONSEMI        0x75009400
236
+#define PHY_VENDOR_AEONSEMI        0x75009400
237
+
237
+
238
+#define AEON_MAX_LDES            5
238
+#define AEON_MAX_LDES            5
239
+#define AEON_IPC_DELAY            10000
239
+#define AEON_IPC_DELAY            10000
240
+#define AEON_IPC_TIMEOUT        (AEON_IPC_DELAY * 100)
240
+#define AEON_IPC_TIMEOUT        (AEON_IPC_DELAY * 100)
241
+#define AEON_IPC_DATA_MAX        (8 * sizeof(u16))
241
+#define AEON_IPC_DATA_MAX        (8 * sizeof(u16))
242
+
242
+
243
+#define AEON_BOOT_ADDR            0x1000
243
+#define AEON_BOOT_ADDR            0x1000
244
+#define AEON_CPU_BOOT_ADDR        0x2000
244
+#define AEON_CPU_BOOT_ADDR        0x2000
245
+#define AEON_CPU_CTRL_FW_LOAD        (BIT(4) | BIT(2) | BIT(1) | BIT(0))
245
+#define AEON_CPU_CTRL_FW_LOAD        (BIT(4) | BIT(2) | BIT(1) | BIT(0))
246
+#define AEON_CPU_CTRL_FW_START        BIT(0)
246
+#define AEON_CPU_CTRL_FW_START        BIT(0)
247
+
247
+
248
+enum as21xxx_led_event {
248
+enum as21xxx_led_event {
249
+    VEND1_LED_REG_A_EVENT_ON_10 = 0x0,
249
+    VEND1_LED_REG_A_EVENT_ON_10 = 0x0,
250
+    VEND1_LED_REG_A_EVENT_ON_100,
250
+    VEND1_LED_REG_A_EVENT_ON_100,
251
+    VEND1_LED_REG_A_EVENT_ON_1000,
251
+    VEND1_LED_REG_A_EVENT_ON_1000,
252
+    VEND1_LED_REG_A_EVENT_ON_2500,
252
+    VEND1_LED_REG_A_EVENT_ON_2500,
253
+    VEND1_LED_REG_A_EVENT_ON_5000,
253
+    VEND1_LED_REG_A_EVENT_ON_5000,
254
+    VEND1_LED_REG_A_EVENT_ON_10000,
254
+    VEND1_LED_REG_A_EVENT_ON_10000,
255
+    VEND1_LED_REG_A_EVENT_ON_FE_GE,
255
+    VEND1_LED_REG_A_EVENT_ON_FE_GE,
256
+    VEND1_LED_REG_A_EVENT_ON_NG,
256
+    VEND1_LED_REG_A_EVENT_ON_NG,
257
+    VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX,
257
+    VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX,
258
+    VEND1_LED_REG_A_EVENT_ON_COLLISION,
258
+    VEND1_LED_REG_A_EVENT_ON_COLLISION,
259
+    VEND1_LED_REG_A_EVENT_BLINK_TX,
259
+    VEND1_LED_REG_A_EVENT_BLINK_TX,
260
+    VEND1_LED_REG_A_EVENT_BLINK_RX,
260
+    VEND1_LED_REG_A_EVENT_BLINK_RX,
261
+    VEND1_LED_REG_A_EVENT_BLINK_ACT,
261
+    VEND1_LED_REG_A_EVENT_BLINK_ACT,
262
+    VEND1_LED_REG_A_EVENT_ON_LINK,
262
+    VEND1_LED_REG_A_EVENT_ON_LINK,
263
+    VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT,
263
+    VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT,
264
+    VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX,
264
+    VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX,
265
+    VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT,
265
+    VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT,
266
+    VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT,
266
+    VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT,
267
+    VEND1_LED_REG_A_EVENT_ON_NG_BLINK_FE_GE,
267
+    VEND1_LED_REG_A_EVENT_ON_NG_BLINK_FE_GE,
268
+    VEND1_LED_REG_A_EVENT_ON_FD_BLINK_COLLISION,
268
+    VEND1_LED_REG_A_EVENT_ON_FD_BLINK_COLLISION,
269
+    VEND1_LED_REG_A_EVENT_ON,
269
+    VEND1_LED_REG_A_EVENT_ON,
270
+    VEND1_LED_REG_A_EVENT_OFF,
270
+    VEND1_LED_REG_A_EVENT_OFF,
271
+};
271
+};
272
+
272
+
273
+struct as21xxx_led_pattern_info {
273
+struct as21xxx_led_pattern_info {
274
+    unsigned int pattern;
274
+    unsigned int pattern;
275
+    u16 val;
275
+    u16 val;
276
+};
276
+};
277
+
277
+
278
+struct as21xxx_priv {
278
+struct as21xxx_priv {
279
+    bool parity_status;
279
+    bool parity_status;
280
+    /* Protect concurrent IPC access */
280
+    /* Protect concurrent IPC access */
281
+    struct mutex ipc_lock;
281
+    struct mutex ipc_lock;
282
+};
282
+};
283
+
283
+
284
+static struct as21xxx_led_pattern_info as21xxx_led_supported_pattern[] = {
284
+static struct as21xxx_led_pattern_info as21xxx_led_supported_pattern[] = {
285
+    {
285
+    {
286
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10),
286
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10),
287
+        .val = VEND1_LED_REG_A_EVENT_ON_10
287
+        .val = VEND1_LED_REG_A_EVENT_ON_10
288
+    },
288
+    },
289
+    {
289
+    {
290
+        .pattern = BIT(TRIGGER_NETDEV_LINK_100),
290
+        .pattern = BIT(TRIGGER_NETDEV_LINK_100),
291
+        .val = VEND1_LED_REG_A_EVENT_ON_100
291
+        .val = VEND1_LED_REG_A_EVENT_ON_100
292
+    },
292
+    },
293
+    {
293
+    {
294
+        .pattern = BIT(TRIGGER_NETDEV_LINK_1000),
294
+        .pattern = BIT(TRIGGER_NETDEV_LINK_1000),
295
+        .val = VEND1_LED_REG_A_EVENT_ON_1000
295
+        .val = VEND1_LED_REG_A_EVENT_ON_1000
296
+    },
296
+    },
297
+    {
297
+    {
298
+        .pattern = BIT(TRIGGER_NETDEV_LINK_2500),
298
+        .pattern = BIT(TRIGGER_NETDEV_LINK_2500),
299
+        .val = VEND1_LED_REG_A_EVENT_ON_2500
299
+        .val = VEND1_LED_REG_A_EVENT_ON_2500
300
+    },
300
+    },
301
+    {
301
+    {
302
+        .pattern = BIT(TRIGGER_NETDEV_LINK_5000),
302
+        .pattern = BIT(TRIGGER_NETDEV_LINK_5000),
303
+        .val = VEND1_LED_REG_A_EVENT_ON_5000
303
+        .val = VEND1_LED_REG_A_EVENT_ON_5000
304
+    },
304
+    },
305
+    {
305
+    {
306
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10000),
306
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10000),
307
+        .val = VEND1_LED_REG_A_EVENT_ON_10000
307
+        .val = VEND1_LED_REG_A_EVENT_ON_10000
308
+    },
308
+    },
309
+    {
309
+    {
310
+        .pattern = BIT(TRIGGER_NETDEV_LINK),
310
+        .pattern = BIT(TRIGGER_NETDEV_LINK),
311
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK
311
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK
312
+    },
312
+    },
313
+    {
313
+    {
314
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
314
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
315
+             BIT(TRIGGER_NETDEV_LINK_100) |
315
+             BIT(TRIGGER_NETDEV_LINK_100) |
316
+             BIT(TRIGGER_NETDEV_LINK_1000),
316
+             BIT(TRIGGER_NETDEV_LINK_1000),
317
+        .val = VEND1_LED_REG_A_EVENT_ON_FE_GE
317
+        .val = VEND1_LED_REG_A_EVENT_ON_FE_GE
318
+    },
318
+    },
319
+    {
319
+    {
320
+        .pattern = BIT(TRIGGER_NETDEV_LINK_2500) |
320
+        .pattern = BIT(TRIGGER_NETDEV_LINK_2500) |
321
+             BIT(TRIGGER_NETDEV_LINK_5000) |
321
+             BIT(TRIGGER_NETDEV_LINK_5000) |
322
+             BIT(TRIGGER_NETDEV_LINK_10000),
322
+             BIT(TRIGGER_NETDEV_LINK_10000),
323
+        .val = VEND1_LED_REG_A_EVENT_ON_NG
323
+        .val = VEND1_LED_REG_A_EVENT_ON_NG
324
+    },
324
+    },
325
+    {
325
+    {
326
+        .pattern = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
326
+        .pattern = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
327
+        .val = VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX
327
+        .val = VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX
328
+    },
328
+    },
329
+    {
329
+    {
330
+        .pattern = BIT(TRIGGER_NETDEV_TX),
330
+        .pattern = BIT(TRIGGER_NETDEV_TX),
331
+        .val = VEND1_LED_REG_A_EVENT_BLINK_TX
331
+        .val = VEND1_LED_REG_A_EVENT_BLINK_TX
332
+    },
332
+    },
333
+    {
333
+    {
334
+        .pattern = BIT(TRIGGER_NETDEV_RX),
334
+        .pattern = BIT(TRIGGER_NETDEV_RX),
335
+        .val = VEND1_LED_REG_A_EVENT_BLINK_RX
335
+        .val = VEND1_LED_REG_A_EVENT_BLINK_RX
336
+    },
336
+    },
337
+    {
337
+    {
338
+        .pattern = BIT(TRIGGER_NETDEV_TX) |
338
+        .pattern = BIT(TRIGGER_NETDEV_TX) |
339
+             BIT(TRIGGER_NETDEV_RX),
339
+             BIT(TRIGGER_NETDEV_RX),
340
+        .val = VEND1_LED_REG_A_EVENT_BLINK_ACT
340
+        .val = VEND1_LED_REG_A_EVENT_BLINK_ACT
341
+    },
341
+    },
342
+    {
342
+    {
343
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
343
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
344
+             BIT(TRIGGER_NETDEV_LINK_100) |
344
+             BIT(TRIGGER_NETDEV_LINK_100) |
345
+             BIT(TRIGGER_NETDEV_LINK_1000) |
345
+             BIT(TRIGGER_NETDEV_LINK_1000) |
346
+             BIT(TRIGGER_NETDEV_LINK_2500) |
346
+             BIT(TRIGGER_NETDEV_LINK_2500) |
347
+             BIT(TRIGGER_NETDEV_LINK_5000) |
347
+             BIT(TRIGGER_NETDEV_LINK_5000) |
348
+             BIT(TRIGGER_NETDEV_LINK_10000),
348
+             BIT(TRIGGER_NETDEV_LINK_10000),
349
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK
349
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK
350
+    },
350
+    },
351
+    {
351
+    {
352
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
352
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
353
+             BIT(TRIGGER_NETDEV_LINK_100) |
353
+             BIT(TRIGGER_NETDEV_LINK_100) |
354
+             BIT(TRIGGER_NETDEV_LINK_1000) |
354
+             BIT(TRIGGER_NETDEV_LINK_1000) |
355
+             BIT(TRIGGER_NETDEV_LINK_2500) |
355
+             BIT(TRIGGER_NETDEV_LINK_2500) |
356
+             BIT(TRIGGER_NETDEV_LINK_5000) |
356
+             BIT(TRIGGER_NETDEV_LINK_5000) |
357
+             BIT(TRIGGER_NETDEV_LINK_10000) |
357
+             BIT(TRIGGER_NETDEV_LINK_10000) |
358
+             BIT(TRIGGER_NETDEV_TX) |
358
+             BIT(TRIGGER_NETDEV_TX) |
359
+             BIT(TRIGGER_NETDEV_RX),
359
+             BIT(TRIGGER_NETDEV_RX),
360
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT
360
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT
361
+    },
361
+    },
362
+    {
362
+    {
363
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
363
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
364
+             BIT(TRIGGER_NETDEV_LINK_100) |
364
+             BIT(TRIGGER_NETDEV_LINK_100) |
365
+             BIT(TRIGGER_NETDEV_LINK_1000) |
365
+             BIT(TRIGGER_NETDEV_LINK_1000) |
366
+             BIT(TRIGGER_NETDEV_LINK_2500) |
366
+             BIT(TRIGGER_NETDEV_LINK_2500) |
367
+             BIT(TRIGGER_NETDEV_LINK_5000) |
367
+             BIT(TRIGGER_NETDEV_LINK_5000) |
368
+             BIT(TRIGGER_NETDEV_LINK_10000) |
368
+             BIT(TRIGGER_NETDEV_LINK_10000) |
369
+             BIT(TRIGGER_NETDEV_RX),
369
+             BIT(TRIGGER_NETDEV_RX),
370
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX
370
+        .val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX
371
+    },
371
+    },
372
+    {
372
+    {
373
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
373
+        .pattern = BIT(TRIGGER_NETDEV_LINK_10) |
374
+             BIT(TRIGGER_NETDEV_LINK_100) |
374
+             BIT(TRIGGER_NETDEV_LINK_100) |
375
+             BIT(TRIGGER_NETDEV_LINK_1000) |
375
+             BIT(TRIGGER_NETDEV_LINK_1000) |
376
+             BIT(TRIGGER_NETDEV_TX) |
376
+             BIT(TRIGGER_NETDEV_TX) |
377
+             BIT(TRIGGER_NETDEV_RX),
377
+             BIT(TRIGGER_NETDEV_RX),
378
+        .val = VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT
378
+        .val = VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT
379
+    },
379
+    },
380
+    {
380
+    {
381
+        .pattern = BIT(TRIGGER_NETDEV_LINK_2500) |
381
+        .pattern = BIT(TRIGGER_NETDEV_LINK_2500) |
382
+             BIT(TRIGGER_NETDEV_LINK_5000) |
382
+             BIT(TRIGGER_NETDEV_LINK_5000) |
383
+             BIT(TRIGGER_NETDEV_LINK_10000) |
383
+             BIT(TRIGGER_NETDEV_LINK_10000) |
384
+             BIT(TRIGGER_NETDEV_TX) |
384
+             BIT(TRIGGER_NETDEV_TX) |
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,
390
+static int aeon_firmware_boot(struct phy_device *phydev, const u8 *data,
391
+             size_t size)
391
+             size_t size)
392
+{
392
+{
393
+    int i, ret;
393
+    int i, ret;
394
+    u16 val;
394
+    u16 val;
395
+
395
+
396
+    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,
397
+             VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_LOAD);
397
+             VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_LOAD);
398
+    if (ret)
398
+    if (ret)
399
+        return ret;
399
+        return ret;
400
+
400
+
401
+    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,
402
+             AEON_BOOT_ADDR);
402
+             AEON_BOOT_ADDR);
403
+    if (ret)
403
+    if (ret)
404
+        return ret;
404
+        return ret;
405
+
405
+
406
+    ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1,
406
+    ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1,
407
+             VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD,
407
+             VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD,
408
+             0x3ffc, 0xc000);
408
+             0x3ffc, 0xc000);
409
+    if (ret)
409
+    if (ret)
410
+        return ret;
410
+        return ret;
411
+
411
+
412
+    val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
412
+    val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
413
+             VEND1_GLB_REG_MDIO_INDIRECT_STATUS);
413
+             VEND1_GLB_REG_MDIO_INDIRECT_STATUS);
414
+    if (val > 1) {
414
+    if (val > 1) {
415
+        phydev_err(phydev, "wrong origin mdio_indirect_status: %x\n", val);
415
+        phydev_err(phydev, "wrong origin mdio_indirect_status: %x\n", val);
416
+        return -EINVAL;
416
+        return -EINVAL;
417
+    }
417
+    }
418
+
418
+
419
+    /* Firmware is always aligned to u16 */
419
+    /* Firmware is always aligned to u16 */
420
+    for (i = 0; i < size; i += 2) {
420
+    for (i = 0; i < size; i += 2) {
421
+        val = data[i + 1] << 8 | data[i];
421
+        val = data[i + 1] << 8 | data[i];
422
+
422
+
423
+        ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
423
+        ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
424
+                 VEND1_GLB_REG_MDIO_INDIRECT_LOAD, val);
424
+                 VEND1_GLB_REG_MDIO_INDIRECT_LOAD, val);
425
+        if (ret)
425
+        if (ret)
426
+            return ret;
426
+            return ret;
427
+    }
427
+    }
428
+
428
+
429
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
429
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
430
+             VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR,
430
+             VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR,
431
+             lower_16_bits(AEON_CPU_BOOT_ADDR));
431
+             lower_16_bits(AEON_CPU_BOOT_ADDR));
432
+    if (ret)
432
+    if (ret)
433
+        return ret;
433
+        return ret;
434
+
434
+
435
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
435
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
436
+             VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR,
436
+             VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR,
437
+             upper_16_bits(AEON_CPU_BOOT_ADDR));
437
+             upper_16_bits(AEON_CPU_BOOT_ADDR));
438
+    if (ret)
438
+    if (ret)
439
+        return ret;
439
+        return ret;
440
+
440
+
441
+    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,
442
+             VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_START);
442
+             VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_START);
443
+}
443
+}
444
+
444
+
445
+static int aeon_firmware_load(struct phy_device *phydev)
445
+static int aeon_firmware_load(struct phy_device *phydev)
446
+{
446
+{
447
+    struct device *dev = &phydev->mdio.dev;
447
+    struct device *dev = &phydev->mdio.dev;
448
+    const struct firmware *fw;
448
+    const struct firmware *fw;
449
+    const char *fw_name;
449
+    const char *fw_name;
450
+    int ret;
450
+    int ret;
451
+
451
+
452
+    ret = of_property_read_string(dev->of_node, "firmware-name",
452
+    ret = of_property_read_string(dev->of_node, "firmware-name",
453
+                 &fw_name);
453
+                 &fw_name);
454
+    if (ret)
454
+    if (ret)
455
+        return ret;
455
+        return ret;
456
+
456
+
457
+    ret = request_firmware(&fw, fw_name, dev);
457
+    ret = request_firmware(&fw, fw_name, dev);
458
+    if (ret) {
458
+    if (ret) {
459
+        phydev_err(phydev, "failed to find FW file %s (%d)\n",
459
+        phydev_err(phydev, "failed to find FW file %s (%d)\n",
460
+             fw_name, ret);
460
+             fw_name, ret);
461
+        return ret;
461
+        return ret;
462
+    }
462
+    }
463
+
463
+
464
+    ret = aeon_firmware_boot(phydev, fw->data, fw->size);
464
+    ret = aeon_firmware_boot(phydev, fw->data, fw->size);
465
+
465
+
466
+    release_firmware(fw);
466
+    release_firmware(fw);
467
+
467
+
468
+    return ret;
468
+    return ret;
469
+}
469
+}
470
+
470
+
471
+static 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)
472
+{
472
+{
473
+    u16 val;
473
+    u16 val;
474
+
474
+
475
+    /* Exit condition logic:
475
+    /* Exit condition logic:
476
+     * - Wait for parity bit equal
476
+     * - Wait for parity bit equal
477
+     * - Wait for status success, error OR ready
477
+     * - Wait for status success, error OR ready
478
+     */
478
+     */
479
+    return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS, val,
479
+    return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS, val,
480
+                     FIELD_GET(AEON_IPC_STS_PARITY, val) == parity_status &&
480
+                     FIELD_GET(AEON_IPC_STS_PARITY, val) == parity_status &&
481
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_RCVD &&
481
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_RCVD &&
482
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_PROCESS &&
482
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_PROCESS &&
483
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_BUSY,
483
+                     (val & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_BUSY,
484
+                     AEON_IPC_DELAY, AEON_IPC_TIMEOUT, false);
484
+                     AEON_IPC_DELAY, AEON_IPC_TIMEOUT, false);
485
+}
485
+}
486
+
486
+
487
+static int aeon_ipc_send_cmd(struct phy_device *phydev,
487
+static int aeon_ipc_send_cmd(struct phy_device *phydev,
488
+             struct as21xxx_priv *priv,
488
+             struct as21xxx_priv *priv,
489
+             u16 cmd, u16 *ret_sts)
489
+             u16 cmd, u16 *ret_sts)
490
+{
490
+{
491
+    bool curr_parity;
491
+    bool curr_parity;
492
+    int ret;
492
+    int ret;
493
+
493
+
494
+    /* The IPC sync by using a single parity bit.
494
+    /* The IPC sync by using a single parity bit.
495
+     * Each CMD have alternately this bit set or clear
495
+     * Each CMD have alternately this bit set or clear
496
+     * to understand correct flow and packet order.
496
+     * to understand correct flow and packet order.
497
+     */
497
+     */
498
+    curr_parity = priv->parity_status;
498
+    curr_parity = priv->parity_status;
499
+    if (priv->parity_status)
499
+    if (priv->parity_status)
500
+        cmd |= AEON_IPC_CMD_PARITY;
500
+        cmd |= AEON_IPC_CMD_PARITY;
501
+
501
+
502
+    /* Always update parity for next packet */
502
+    /* Always update parity for next packet */
503
+    priv->parity_status = !priv->parity_status;
503
+    priv->parity_status = !priv->parity_status;
504
+
504
+
505
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_CMD, cmd);
505
+    ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_CMD, cmd);
506
+    if (ret)
506
+    if (ret)
507
+        return ret;
507
+        return ret;
508
+
508
+
509
+    /* Wait for packet to be processed */
509
+    /* Wait for packet to be processed */
510
+    usleep_range(AEON_IPC_DELAY, AEON_IPC_DELAY + 5000);
510
+    usleep_range(AEON_IPC_DELAY, AEON_IPC_DELAY + 5000);
511
+
511
+
512
+    /* With no ret_sts, ignore waiting for packet completion
512
+    /* With no ret_sts, ignore waiting for packet completion
513
+     * (ipc parity bit sync)
513
+     * (ipc parity bit sync)
514
+     */
514
+     */
515
+    if (!ret_sts)
515
+    if (!ret_sts)
516
+        return 0;
516
+        return 0;
517
+
517
+
518
+    ret = aeon_ipcs_wait_cmd(phydev, curr_parity);
518
+    ret = aeon_ipcs_wait_cmd(phydev, curr_parity);
519
+    if (ret)
519
+    if (ret)
520
+        return ret;
520
+        return ret;
521
+
521
+
522
+    ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS);
522
+    ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS);
523
+    if (ret < 0)
523
+    if (ret < 0)
524
+        return ret;
524
+        return ret;
525
+
525
+
526
+    *ret_sts = ret;
526
+    *ret_sts = ret;
527
+    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)
528
+        return -EINVAL;
528
+        return -EINVAL;
529
+
529
+
530
+    return 0;
530
+    return 0;
531
+}
531
+}
532
+
532
+
533
+static int aeon_ipc_send_msg(struct phy_device *phydev,
533
+static int aeon_ipc_send_msg(struct phy_device *phydev,
534
+             u16 opcode, u16 *data, unsigned int data_len,
534
+             u16 opcode, u16 *data, unsigned int data_len,
535
+             u16 *ret_sts)
535
+             u16 *ret_sts)
536
+{
536
+{
537
+    struct as21xxx_priv *priv = phydev->priv;
537
+    struct as21xxx_priv *priv = phydev->priv;
538
+    u16 cmd;
538
+    u16 cmd;
539
+    int ret;
539
+    int ret;
540
+    int i;
540
+    int i;
541
+
541
+
542
+    /* IPC have a max of 8 register to transfer data,
542
+    /* IPC have a max of 8 register to transfer data,
543
+     * make sure we never exceed this.
543
+     * make sure we never exceed this.
544
+     */
544
+     */
545
+    if (data_len > AEON_IPC_DATA_MAX)
545
+    if (data_len > AEON_IPC_DATA_MAX)
546
+        return -EINVAL;
546
+        return -EINVAL;
547
+
547
+
548
+    mutex_lock(&priv->ipc_lock);
548
+    mutex_lock(&priv->ipc_lock);
549
+
549
+
550
+    for (i = 0; i < data_len / sizeof(u16); i++)
550
+    for (i = 0; i < data_len / sizeof(u16); i++)
551
+        phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i),
551
+        phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i),
552
+             data[i]);
552
+             data[i]);
553
+
553
+
554
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, data_len) |
554
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, data_len) |
555
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, opcode);
555
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, opcode);
556
+    ret = aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
556
+    ret = aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
557
+    if (ret)
557
+    if (ret)
558
+        phydev_err(phydev, "failed to send ipc msg for %x: %d\n",
558
+        phydev_err(phydev, "failed to send ipc msg for %x: %d\n",
559
+             opcode, ret);
559
+             opcode, ret);
560
+
560
+
561
+    mutex_unlock(&priv->ipc_lock);
561
+    mutex_unlock(&priv->ipc_lock);
562
+
562
+
563
+    return ret;
563
+    return ret;
564
+}
564
+}
565
+
565
+
566
+static int aeon_ipc_rcv_msg(struct phy_device *phydev,
566
+static int aeon_ipc_rcv_msg(struct phy_device *phydev,
567
+             u16 ret_sts, u16 *data)
567
+             u16 ret_sts, u16 *data)
568
+{
568
+{
569
+    struct as21xxx_priv *priv = phydev->priv;
569
+    struct as21xxx_priv *priv = phydev->priv;
570
+    unsigned int size;
570
+    unsigned int size;
571
+    int ret;
571
+    int ret;
572
+    int i;
572
+    int i;
573
+
573
+
574
+    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)
575
+        return -EINVAL;
575
+        return -EINVAL;
576
+
576
+
577
+    /* 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);
578
+    size = FIELD_GET(AEON_IPC_STS_SIZE, ret_sts);
579
+    if (size > AEON_IPC_DATA_MAX)
579
+    if (size > AEON_IPC_DATA_MAX)
580
+        return -EINVAL;
580
+        return -EINVAL;
581
+
581
+
582
+    mutex_lock(&priv->ipc_lock);
582
+    mutex_lock(&priv->ipc_lock);
583
+
583
+
584
+    for (i = 0; i < DIV_ROUND_UP(size, sizeof(u16)); i++) {
584
+    for (i = 0; i < DIV_ROUND_UP(size, sizeof(u16)); i++) {
585
+        ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i));
585
+        ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i));
586
+        if (ret < 0) {
586
+        if (ret < 0) {
587
+            size = ret;
587
+            size = ret;
588
+            goto out;
588
+            goto out;
589
+        }
589
+        }
590
+
590
+
591
+        data[i] = ret;
591
+        data[i] = ret;
592
+    }
592
+    }
593
+
593
+
594
+out:
594
+out:
595
+    mutex_unlock(&priv->ipc_lock);
595
+    mutex_unlock(&priv->ipc_lock);
596
+
596
+
597
+    return size;
597
+    return size;
598
+}
598
+}
599
+
599
+
600
+static int aeon_ipc_noop(struct phy_device *phydev,
600
+static int aeon_ipc_noop(struct phy_device *phydev,
601
+             struct as21xxx_priv *priv, u16 *ret_sts)
601
+             struct as21xxx_priv *priv, u16 *ret_sts)
602
+{
602
+{
603
+    u16 cmd;
603
+    u16 cmd;
604
+
604
+
605
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) |
605
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) |
606
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP);
606
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP);
607
+
607
+
608
+    return aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
608
+    return aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
609
+}
609
+}
610
+
610
+
611
+/* Logic to sync parity bit with IPC.
611
+/* Logic to sync parity bit with IPC.
612
+ * 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
613
+ * to handle the packet only for the second one. This way
613
+ * to handle the packet only for the second one. This way
614
+ * we make sure we are sync for every next cmd.
614
+ * we make sure we are sync for every next cmd.
615
+ */
615
+ */
616
+static int aeon_ipc_sync_parity(struct phy_device *phydev,
616
+static int aeon_ipc_sync_parity(struct phy_device *phydev,
617
+                struct as21xxx_priv *priv)
617
+                struct as21xxx_priv *priv)
618
+{
618
+{
619
+    u16 ret_sts;
619
+    u16 ret_sts;
620
+    int ret;
620
+    int ret;
621
+
621
+
622
+    mutex_lock(&priv->ipc_lock);
622
+    mutex_lock(&priv->ipc_lock);
623
+
623
+
624
+    /* Send NOP with no parity */
624
+    /* Send NOP with no parity */
625
+    aeon_ipc_noop(phydev, priv, NULL);
625
+    aeon_ipc_noop(phydev, priv, NULL);
626
+
626
+
627
+    /* Reset packet parity */
627
+    /* Reset packet parity */
628
+    priv->parity_status = false;
628
+    priv->parity_status = false;
629
+
629
+
630
+    /* Send second NOP with no parity */
630
+    /* Send second NOP with no parity */
631
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
631
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
632
+
632
+
633
+    mutex_unlock(&priv->ipc_lock);
633
+    mutex_unlock(&priv->ipc_lock);
634
+
634
+
635
+    /* We expect to return -EINVAL */
635
+    /* We expect to return -EINVAL */
636
+    if (ret != -EINVAL)
636
+    if (ret != -EINVAL)
637
+        return ret;
637
+        return ret;
638
+
638
+
639
+    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",
640
+        phydev_err(phydev, "Invalid IPC status on sync parity: %x\n",
641
+             ret_sts);
641
+             ret_sts);
642
+        return -EINVAL;
642
+        return -EINVAL;
643
+    }
643
+    }
644
+
644
+
645
+    return 0;
645
+    return 0;
646
+}
646
+}
647
+
647
+
648
+static int aeon_ipc_get_fw_version(struct phy_device *phydev)
648
+static int aeon_ipc_get_fw_version(struct phy_device *phydev)
649
+{
649
+{
650
+    u16 ret_data[8], data[1];
650
+    u16 ret_data[8], data[1];
651
+    u16 ret_sts;
651
+    u16 ret_sts;
652
+    int ret;
652
+    int ret;
653
+
653
+
654
+    data[0] = IPC_INFO_VERSION;
654
+    data[0] = IPC_INFO_VERSION;
655
+    ret = aeon_ipc_send_msg(phydev, IPC_CMD_INFO, data,
655
+    ret = aeon_ipc_send_msg(phydev, IPC_CMD_INFO, data,
656
+                sizeof(data), &ret_sts);
656
+                sizeof(data), &ret_sts);
657
+    if (ret)
657
+    if (ret)
658
+        return ret;
658
+        return ret;
659
+
659
+
660
+    ret = aeon_ipc_rcv_msg(phydev, ret_sts, ret_data);
660
+    ret = aeon_ipc_rcv_msg(phydev, ret_sts, ret_data);
661
+    if (ret < 0)
661
+    if (ret < 0)
662
+        return ret;
662
+        return ret;
663
+
663
+
664
+    phydev_info(phydev, "Firmware Version: %s\n", (char *)ret_data);
664
+    phydev_info(phydev, "Firmware Version: %s\n", (char *)ret_data);
665
+
665
+
666
+    return 0;
666
+    return 0;
667
+}
667
+}
668
+
668
+
669
+static int aeon_dpc_ra_enable(struct phy_device *phydev)
669
+static int aeon_dpc_ra_enable(struct phy_device *phydev)
670
+{
670
+{
671
+    u16 data[2];
671
+    u16 data[2];
672
+    u16 ret_sts;
672
+    u16 ret_sts;
673
+
673
+
674
+    data[0] = IPC_CFG_PARAM_DIRECT;
674
+    data[0] = IPC_CFG_PARAM_DIRECT;
675
+    data[1] = IPC_CFG_PARAM_DIRECT_DPC_RA;
675
+    data[1] = IPC_CFG_PARAM_DIRECT_DPC_RA;
676
+
676
+
677
+    return aeon_ipc_send_msg(phydev, IPC_CMD_CFG_PARAM, data,
677
+    return aeon_ipc_send_msg(phydev, IPC_CMD_CFG_PARAM, data,
678
+                 sizeof(data), &ret_sts);
678
+                 sizeof(data), &ret_sts);
679
+}
679
+}
680
+
680
+
681
+static int as21xxx_probe(struct phy_device *phydev)
681
+static int as21xxx_probe(struct phy_device *phydev)
682
+{
682
+{
683
+    struct as21xxx_priv *priv;
683
+    struct as21xxx_priv *priv;
684
+    int ret;
684
+    int ret;
685
+
685
+
686
+    priv = devm_kzalloc(&phydev->mdio.dev,
686
+    priv = devm_kzalloc(&phydev->mdio.dev,
687
+             sizeof(*priv), GFP_KERNEL);
687
+             sizeof(*priv), GFP_KERNEL);
688
+    if (!priv)
688
+    if (!priv)
689
+        return -ENOMEM;
689
+        return -ENOMEM;
690
+    phydev->priv = priv;
690
+    phydev->priv = priv;
691
+
691
+
692
+    ret = devm_mutex_init(&phydev->mdio.dev,
692
+    ret = devm_mutex_init(&phydev->mdio.dev,
693
+             &priv->ipc_lock);
693
+             &priv->ipc_lock);
694
+    if (ret)
694
+    if (ret)
695
+        return ret;
695
+        return ret;
696
+
696
+
697
+    ret = aeon_ipc_sync_parity(phydev, priv);
697
+    ret = aeon_ipc_sync_parity(phydev, priv);
698
+    if (ret)
698
+    if (ret)
699
+        return ret;
699
+        return ret;
700
+
700
+
701
+    ret = aeon_ipc_get_fw_version(phydev);
701
+    ret = aeon_ipc_get_fw_version(phydev);
702
+    if (ret)
702
+    if (ret)
703
+        return ret;
703
+        return ret;
704
+
704
+
705
+    /* Enable PTP clk if not already Enabled */
705
+    /* Enable PTP clk if not already Enabled */
706
+    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,
707
+             VEND1_PTP_CLK_EN);
707
+             VEND1_PTP_CLK_EN);
708
+    if (ret)
708
+    if (ret)
709
+        return ret;
709
+        return ret;
710
+
710
+
711
+    return aeon_dpc_ra_enable(phydev);
711
+    return aeon_dpc_ra_enable(phydev);
712
+}
712
+}
713
+
713
+
714
+static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
714
+static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
715
+{
715
+{
716
+    int status;
716
+    int status;
717
+
717
+
718
+    /* Normal C22 BMCR report inconsistent data, use
718
+    /* Normal C22 BMCR report inconsistent data, use
719
+     * the mapped C22 in C45 to have more consistent link info.
719
+     * the mapped C22 in C45 to have more consistent link info.
720
+     */
720
+     */
721
+    *bmcr = phy_read_mmd(phydev, MDIO_MMD_AN,
721
+    *bmcr = phy_read_mmd(phydev, MDIO_MMD_AN,
722
+             AS21XXX_MDIO_AN_C22 + MII_BMCR);
722
+             AS21XXX_MDIO_AN_C22 + MII_BMCR);
723
+    if (*bmcr < 0)
723
+    if (*bmcr < 0)
724
+        return *bmcr;
724
+        return *bmcr;
725
+
725
+
726
+    /* Autoneg is being started, therefore disregard current
726
+    /* Autoneg is being started, therefore disregard current
727
+     * link status and report link as down.
727
+     * link status and report link as down.
728
+     */
728
+     */
729
+    if (*bmcr & BMCR_ANRESTART) {
729
+    if (*bmcr & BMCR_ANRESTART) {
730
+        phydev->link = 0;
730
+        phydev->link = 0;
731
+        return 0;
731
+        return 0;
732
+    }
732
+    }
733
+
733
+
734
+    status = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
734
+    status = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
735
+    if (status < 0)
735
+    if (status < 0)
736
+        return status;
736
+        return status;
737
+
737
+
738
+    phydev->link = !!(status & MDIO_STAT1_LSTATUS);
738
+    phydev->link = !!(status & MDIO_STAT1_LSTATUS);
739
+
739
+
740
+    return 0;
740
+    return 0;
741
+}
741
+}
742
+
742
+
743
+static int as21xxx_read_c22_lpa(struct phy_device *phydev)
743
+static int as21xxx_read_c22_lpa(struct phy_device *phydev)
744
+{
744
+{
745
+    int lpagb;
745
+    int lpagb;
746
+
746
+
747
+    /* MII_STAT1000 are only filled in the mapped C22
747
+    /* MII_STAT1000 are only filled in the mapped C22
748
+     * in C45, use that to fill lpagb values and check.
748
+     * in C45, use that to fill lpagb values and check.
749
+     */
749
+     */
750
+    lpagb = phy_read_mmd(phydev, MDIO_MMD_AN,
750
+    lpagb = phy_read_mmd(phydev, MDIO_MMD_AN,
751
+             AS21XXX_MDIO_AN_C22 + MII_STAT1000);
751
+             AS21XXX_MDIO_AN_C22 + MII_STAT1000);
752
+    if (lpagb < 0)
752
+    if (lpagb < 0)
753
+        return lpagb;
753
+        return lpagb;
754
+
754
+
755
+    if (lpagb & LPA_1000MSFAIL) {
755
+    if (lpagb & LPA_1000MSFAIL) {
756
+        int adv = phy_read_mmd(phydev, MDIO_MMD_AN,
756
+        int adv = phy_read_mmd(phydev, MDIO_MMD_AN,
757
+                 AS21XXX_MDIO_AN_C22 + MII_CTRL1000);
757
+                 AS21XXX_MDIO_AN_C22 + MII_CTRL1000);
758
+
758
+
759
+        if (adv < 0)
759
+        if (adv < 0)
760
+            return adv;
760
+            return adv;
761
+
761
+
762
+        if (adv & CTL1000_ENABLE_MASTER)
762
+        if (adv & CTL1000_ENABLE_MASTER)
763
+            phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n");
763
+            phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n");
764
+        else
764
+        else
765
+            phydev_err(phydev, "Master/Slave resolution failed\n");
765
+            phydev_err(phydev, "Master/Slave resolution failed\n");
766
+        return -ENOLINK;
766
+        return -ENOLINK;
767
+    }
767
+    }
768
+
768
+
769
+    mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
769
+    mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
770
+                    lpagb);
770
+                    lpagb);
771
+
771
+
772
+    return 0;
772
+    return 0;
773
+}
773
+}
774
+
774
+
775
+static int as21xxx_read_status(struct phy_device *phydev)
775
+static int as21xxx_read_status(struct phy_device *phydev)
776
+{
776
+{
777
+    int bmcr, old_link = phydev->link;
777
+    int bmcr, old_link = phydev->link;
778
+    int ret;
778
+    int ret;
779
+
779
+
780
+    ret = as21xxx_read_link(phydev, &bmcr);
780
+    ret = as21xxx_read_link(phydev, &bmcr);
781
+    if (ret)
781
+    if (ret)
782
+        return ret;
782
+        return ret;
783
+
783
+
784
+    /* why bother the PHY if nothing can have changed */
784
+    /* why bother the PHY if nothing can have changed */
785
+    if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
785
+    if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
786
+        return 0;
786
+        return 0;
787
+
787
+
788
+    phydev->speed = SPEED_UNKNOWN;
788
+    phydev->speed = SPEED_UNKNOWN;
789
+    phydev->duplex = DUPLEX_UNKNOWN;
789
+    phydev->duplex = DUPLEX_UNKNOWN;
790
+    phydev->pause = 0;
790
+    phydev->pause = 0;
791
+    phydev->asym_pause = 0;
791
+    phydev->asym_pause = 0;
792
+
792
+
793
+    if (phydev->autoneg == AUTONEG_ENABLE) {
793
+    if (phydev->autoneg == AUTONEG_ENABLE) {
794
+        ret = genphy_c45_read_lpa(phydev);
794
+        ret = genphy_c45_read_lpa(phydev);
795
+        if (ret)
795
+        if (ret)
796
+            return ret;
796
+            return ret;
797
+
797
+
798
+        ret = as21xxx_read_c22_lpa(phydev);
798
+        ret = as21xxx_read_c22_lpa(phydev);
799
+        if (ret)
799
+        if (ret)
800
+            return ret;
800
+            return ret;
801
+
801
+
802
+        phy_resolve_aneg_linkmode(phydev);
802
+        phy_resolve_aneg_linkmode(phydev);
803
+    } else {
803
+    } else {
804
+        int speed;
804
+        int speed;
805
+
805
+
806
+        linkmode_zero(phydev->lp_advertising);
806
+        linkmode_zero(phydev->lp_advertising);
807
+
807
+
808
+        speed = phy_read_mmd(phydev, MDIO_MMD_VEND1,
808
+        speed = phy_read_mmd(phydev, MDIO_MMD_VEND1,
809
+                 VEND1_SPEED_STATUS);
809
+                 VEND1_SPEED_STATUS);
810
+        if (speed < 0)
810
+        if (speed < 0)
811
+            return speed;
811
+            return speed;
812
+
812
+
813
+        switch (speed & VEND1_SPEED_STATUS) {
813
+        switch (speed & VEND1_SPEED_STATUS) {
814
+        case VEND1_SPEED_10000:
814
+        case VEND1_SPEED_10000:
815
+            phydev->speed = SPEED_10000;
815
+            phydev->speed = SPEED_10000;
816
+            phydev->duplex = DUPLEX_FULL;
816
+            phydev->duplex = DUPLEX_FULL;
817
+            break;
817
+            break;
818
+        case VEND1_SPEED_5000:
818
+        case VEND1_SPEED_5000:
819
+            phydev->speed = SPEED_5000;
819
+            phydev->speed = SPEED_5000;
820
+            phydev->duplex = DUPLEX_FULL;
820
+            phydev->duplex = DUPLEX_FULL;
821
+            break;
821
+            break;
822
+        case VEND1_SPEED_2500:
822
+        case VEND1_SPEED_2500:
823
+            phydev->speed = SPEED_2500;
823
+            phydev->speed = SPEED_2500;
824
+            phydev->duplex = DUPLEX_FULL;
824
+            phydev->duplex = DUPLEX_FULL;
825
+            break;
825
+            break;
826
+        case VEND1_SPEED_1000:
826
+        case VEND1_SPEED_1000:
827
+            phydev->speed = SPEED_1000;
827
+            phydev->speed = SPEED_1000;
828
+            if (bmcr & BMCR_FULLDPLX)
828
+            if (bmcr & BMCR_FULLDPLX)
829
+                phydev->duplex = DUPLEX_FULL;
829
+                phydev->duplex = DUPLEX_FULL;
830
+            else
830
+            else
831
+                phydev->duplex = DUPLEX_HALF;
831
+                phydev->duplex = DUPLEX_HALF;
832
+            break;
832
+            break;
833
+        case VEND1_SPEED_100:
833
+        case VEND1_SPEED_100:
834
+            phydev->speed = SPEED_100;
834
+            phydev->speed = SPEED_100;
835
+            phydev->duplex = DUPLEX_FULL;
835
+            phydev->duplex = DUPLEX_FULL;
836
+            break;
836
+            break;
837
+        case VEND1_SPEED_10:
837
+        case VEND1_SPEED_10:
838
+            phydev->speed = SPEED_10;
838
+            phydev->speed = SPEED_10;
839
+            phydev->duplex = DUPLEX_FULL;
839
+            phydev->duplex = DUPLEX_FULL;
840
+            break;
840
+            break;
841
+        default:
841
+        default:
842
+            return -EINVAL;
842
+            return -EINVAL;
843
+        }
843
+        }
844
+    }
844
+    }
845
+
845
+
846
+    return 0;
846
+    return 0;
847
+}
847
+}
848
+
848
+
849
+static int as21xxx_led_brightness_set(struct phy_device *phydev,
849
+static int as21xxx_led_brightness_set(struct phy_device *phydev,
850
+                 u8 index, enum led_brightness value)
850
+                 u8 index, enum led_brightness value)
851
+{
851
+{
852
+    u16 val = VEND1_LED_REG_A_EVENT_OFF;
852
+    u16 val = VEND1_LED_REG_A_EVENT_OFF;
853
+
853
+
854
+    if (index > AEON_MAX_LDES)
854
+    if (index > AEON_MAX_LDES)
855
+        return -EINVAL;
855
+        return -EINVAL;
856
+
856
+
857
+    if (value)
857
+    if (value)
858
+        val = VEND1_LED_REG_A_EVENT_ON;
858
+        val = VEND1_LED_REG_A_EVENT_ON;
859
+
859
+
860
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
860
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
861
+             VEND1_LED_REG(index),
861
+             VEND1_LED_REG(index),
862
+             VEND1_LED_REG_A_EVENT,
862
+             VEND1_LED_REG_A_EVENT,
863
+             FIELD_PREP(VEND1_LED_REG_A_EVENT, val));
863
+             FIELD_PREP(VEND1_LED_REG_A_EVENT, val));
864
+}
864
+}
865
+
865
+
866
+static int as21xxx_led_hw_is_supported(struct phy_device *phydev, u8 index,
866
+static int as21xxx_led_hw_is_supported(struct phy_device *phydev, u8 index,
867
+                 unsigned long rules)
867
+                 unsigned long rules)
868
+{
868
+{
869
+    int i;
869
+    int i;
870
+
870
+
871
+    if (index > AEON_MAX_LDES)
871
+    if (index > AEON_MAX_LDES)
872
+        return -EINVAL;
872
+        return -EINVAL;
873
+
873
+
874
+    for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
874
+    for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
875
+        if (rules == as21xxx_led_supported_pattern[i].pattern)
875
+        if (rules == as21xxx_led_supported_pattern[i].pattern)
876
+            return 0;
876
+            return 0;
877
+
877
+
878
+    return -EOPNOTSUPP;
878
+    return -EOPNOTSUPP;
879
+}
879
+}
880
+
880
+
881
+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,
882
+                 unsigned long *rules)
882
+                 unsigned long *rules)
883
+{
883
+{
884
+    int i, val;
884
+    int i, val;
885
+
885
+
886
+    if (index > AEON_MAX_LDES)
886
+    if (index > AEON_MAX_LDES)
887
+        return -EINVAL;
887
+        return -EINVAL;
888
+
888
+
889
+    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));
890
+    if (val < 0)
890
+    if (val < 0)
891
+        return val;
891
+        return val;
892
+
892
+
893
+    val = FIELD_GET(VEND1_LED_REG_A_EVENT, val);
893
+    val = FIELD_GET(VEND1_LED_REG_A_EVENT, val);
894
+    for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
894
+    for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
895
+        if (val == as21xxx_led_supported_pattern[i].val) {
895
+        if (val == as21xxx_led_supported_pattern[i].val) {
896
+            *rules = as21xxx_led_supported_pattern[i].pattern;
896
+            *rules = as21xxx_led_supported_pattern[i].pattern;
897
+            return 0;
897
+            return 0;
898
+        }
898
+        }
899
+
899
+
900
+    /* Should be impossible */
900
+    /* Should be impossible */
901
+    return -EINVAL;
901
+    return -EINVAL;
902
+}
902
+}
903
+
903
+
904
+static int as21xxx_led_hw_control_set(struct phy_device *phydev, u8 index,
904
+static int as21xxx_led_hw_control_set(struct phy_device *phydev, u8 index,
905
+                 unsigned long rules)
905
+                 unsigned long rules)
906
+{
906
+{
907
+    u16 val = 0;
907
+    u16 val = 0;
908
+    int i;
908
+    int i;
909
+
909
+
910
+    if (index > AEON_MAX_LDES)
910
+    if (index > AEON_MAX_LDES)
911
+        return -EINVAL;
911
+        return -EINVAL;
912
+
912
+
913
+    for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
913
+    for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
914
+        if (rules == as21xxx_led_supported_pattern[i].pattern) {
914
+        if (rules == as21xxx_led_supported_pattern[i].pattern) {
915
+            val = as21xxx_led_supported_pattern[i].val;
915
+            val = as21xxx_led_supported_pattern[i].val;
916
+            break;
916
+            break;
917
+        }
917
+        }
918
+
918
+
919
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
919
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
920
+             VEND1_LED_REG(index),
920
+             VEND1_LED_REG(index),
921
+             VEND1_LED_REG_A_EVENT,
921
+             VEND1_LED_REG_A_EVENT,
922
+             FIELD_PREP(VEND1_LED_REG_A_EVENT, val));
922
+             FIELD_PREP(VEND1_LED_REG_A_EVENT, val));
923
+}
923
+}
924
+
924
+
925
+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,
926
+                 unsigned long modes)
926
+                 unsigned long modes)
927
+{
927
+{
928
+    bool led_active_low = false;
928
+    bool led_active_low = false;
929
+    u16 mask, val = 0;
929
+    u16 mask, val = 0;
930
+    u32 mode;
930
+    u32 mode;
931
+
931
+
932
+    if (index > AEON_MAX_LDES)
932
+    if (index > AEON_MAX_LDES)
933
+        return -EINVAL;
933
+        return -EINVAL;
934
+
934
+
935
+    for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
935
+    for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
936
+        switch (mode) {
936
+        switch (mode) {
937
+        case PHY_LED_ACTIVE_LOW:
937
+        case PHY_LED_ACTIVE_LOW:
938
+            led_active_low = true;
938
+            led_active_low = true;
939
+            break;
939
+            break;
940
+        case PHY_LED_ACTIVE_HIGH: /* default mode */
940
+        case PHY_LED_ACTIVE_HIGH: /* default mode */
941
+            led_active_low = false;
941
+            led_active_low = false;
942
+            break;
942
+            break;
943
+        default:
943
+        default:
944
+            return -EINVAL;
944
+            return -EINVAL;
945
+        }
945
+        }
946
+    }
946
+    }
947
+
947
+
948
+    mask = VEND1_GLB_CPU_CTRL_LED_POLARITY(index);
948
+    mask = VEND1_GLB_CPU_CTRL_LED_POLARITY(index);
949
+    if (led_active_low)
949
+    if (led_active_low)
950
+        val = VEND1_GLB_CPU_CTRL_LED_POLARITY(index);
950
+        val = VEND1_GLB_CPU_CTRL_LED_POLARITY(index);
951
+
951
+
952
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
952
+    return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
953
+             VEND1_GLB_REG_CPU_CTRL,
953
+             VEND1_GLB_REG_CPU_CTRL,
954
+             mask, val);
954
+             mask, val);
955
+}
955
+}
956
+
956
+
957
+static int as21xxx_match_phy_device(struct phy_device *phydev,
957
+static int as21xxx_match_phy_device(struct phy_device *phydev,
958
+                 const struct phy_driver *phydrv)
958
+                 const struct phy_driver *phydrv)
959
+{
959
+{
960
+    struct as21xxx_priv *priv;
960
+    struct as21xxx_priv *priv;
961
+    u16 ret_sts;
961
+    u16 ret_sts;
962
+    u32 phy_id;
962
+    u32 phy_id;
963
+    int ret;
963
+    int ret;
964
+
964
+
965
+    /* Skip PHY that are not AS21xxx or already have firmware loaded */
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)
966
+    if (phydev->c45_ids.device_ids[MDIO_MMD_PCS] != PHY_ID_AS21XXX)
967
+        return genphy_match_phy_device(phydev, phydrv);
967
+        return genphy_match_phy_device(phydev, phydrv);
968
+
968
+
969
+    /* Read PHY ID to handle firmware just loaded */
969
+    /* Read PHY ID to handle firmware just loaded */
970
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1);
970
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1);
971
+    if (ret < 0)
971
+    if (ret < 0)
972
+        return ret;
972
+        return ret;
973
+    phy_id = ret << 16;
973
+    phy_id = ret << 16;
974
+
974
+
975
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID2);
975
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID2);
976
+    if (ret < 0)
976
+    if (ret < 0)
977
+        return ret;
977
+        return ret;
978
+    phy_id |= ret;
978
+    phy_id |= ret;
979
+
979
+
980
+    /* With PHY ID not the generic AS21xxx one assume
980
+    /* With PHY ID not the generic AS21xxx one assume
981
+     * the firmware just loaded
981
+     * the firmware just loaded
982
+     */
982
+     */
983
+    if (phy_id != PHY_ID_AS21XXX)
983
+    if (phy_id != PHY_ID_AS21XXX)
984
+        return phy_id == phydrv->phy_id;
984
+        return phy_id == phydrv->phy_id;
985
+
985
+
986
+    /* Allocate temp priv and load the firmware */
986
+    /* Allocate temp priv and load the firmware */
987
+    priv = kzalloc(sizeof(*priv), GFP_KERNEL);
987
+    priv = kzalloc(sizeof(*priv), GFP_KERNEL);
988
+    if (!priv)
988
+    if (!priv)
989
+        return -ENOMEM;
989
+        return -ENOMEM;
990
+
990
+
991
+    mutex_init(&priv->ipc_lock);
991
+    mutex_init(&priv->ipc_lock);
992
+
992
+
993
+    ret = aeon_firmware_load(phydev);
993
+    ret = aeon_firmware_load(phydev);
994
+    if (ret)
994
+    if (ret)
995
+        goto out;
995
+        goto out;
996
+
996
+
997
+    /* Sync parity... */
997
+    /* Sync parity... */
998
+    ret = aeon_ipc_sync_parity(phydev, priv);
998
+    ret = aeon_ipc_sync_parity(phydev, priv);
999
+    if (ret)
999
+    if (ret)
1000
+        goto out;
1000
+        goto out;
1001
+
1001
+
1002
+    /* ...and send a third NOOP cmd to wait for firmware finish loading */
1002
+    /* ...and send a third NOOP cmd to wait for firmware finish loading */
1003
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
1003
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
1004
+    if (ret)
1004
+    if (ret)
1005
+        goto out;
1005
+        goto out;
1006
+
1006
+
1007
+out:
1007
+out:
1008
+    mutex_destroy(&priv->ipc_lock);
1008
+    mutex_destroy(&priv->ipc_lock);
1009
+    kfree(priv);
1009
+    kfree(priv);
1010
+
1010
+
1011
+    /* Return not maching anyway as PHY ID will change after
1011
+    /* Return not maching anyway as PHY ID will change after
1012
+     * firmware is loaded. This relies on the driver probe
1012
+     * firmware is loaded. This relies on the driver probe
1013
+     * order where the first PHY driver probed is the
1013
+     * order where the first PHY driver probed is the
1014
+     * generic one.
1014
+     * generic one.
1015
+     */
1015
+     */
1016
+    return ret;
1016
+    return ret;
1017
+}
1017
+}
1018
+
1018
+
1019
+static struct phy_driver as21xxx_drivers[] = {
1019
+static struct phy_driver as21xxx_drivers[] = {
1020
+    {
1020
+    {
1021
+        /* PHY expose in C45 as 0x7500 0x9410
1021
+        /* PHY expose in C45 as 0x7500 0x9410
1022
+         * before firmware is loaded.
1022
+         * before firmware is loaded.
1023
+         * This driver entry must be attempted first to load
1023
+         * This driver entry must be attempted first to load
1024
+         * the firmware and thus update the ID registers.
1024
+         * the firmware and thus update the ID registers.
1025
+         */
1025
+         */
1026
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX),
1026
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX),
1027
+        .name        = "Aeonsemi AS21xxx",
1027
+        .name        = "Aeonsemi AS21xxx",
1028
+        .match_phy_device = as21xxx_match_phy_device,
1028
+        .match_phy_device = as21xxx_match_phy_device,
1029
+    },
1029
+    },
1030
+    {
1030
+    {
1031
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011JB1),
1031
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011JB1),
1032
+        .name        = "Aeonsemi AS21011JB1",
1032
+        .name        = "Aeonsemi AS21011JB1",
1033
+        .probe        = as21xxx_probe,
1033
+        .probe        = as21xxx_probe,
1034
+        .match_phy_device = as21xxx_match_phy_device,
1034
+        .match_phy_device = as21xxx_match_phy_device,
1035
+        .read_status    = as21xxx_read_status,
1035
+        .read_status    = as21xxx_read_status,
1036
+        .led_brightness_set = as21xxx_led_brightness_set,
1036
+        .led_brightness_set = as21xxx_led_brightness_set,
1037
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1037
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1038
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1038
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1039
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1039
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1040
+        .led_polarity_set = as21xxx_led_polarity_set,
1040
+        .led_polarity_set = as21xxx_led_polarity_set,
1041
+    },
1041
+    },
1042
+    {
1042
+    {
1043
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
1043
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
1044
+        .name        = "Aeonsemi AS21011PB1",
1044
+        .name        = "Aeonsemi AS21011PB1",
1045
+        .probe        = as21xxx_probe,
1045
+        .probe        = as21xxx_probe,
1046
+        .match_phy_device = as21xxx_match_phy_device,
1046
+        .match_phy_device = as21xxx_match_phy_device,
1047
+        .read_status    = as21xxx_read_status,
1047
+        .read_status    = as21xxx_read_status,
1048
+        .led_brightness_set = as21xxx_led_brightness_set,
1048
+        .led_brightness_set = as21xxx_led_brightness_set,
1049
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1049
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1050
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1050
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1051
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1051
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1052
+        .led_polarity_set = as21xxx_led_polarity_set,
1052
+        .led_polarity_set = as21xxx_led_polarity_set,
1053
+    },
1053
+    },
1054
+    {
1054
+    {
1055
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
1055
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
1056
+        .name        = "Aeonsemi AS21010PB1",
1056
+        .name        = "Aeonsemi AS21010PB1",
1057
+        .probe        = as21xxx_probe,
1057
+        .probe        = as21xxx_probe,
1058
+        .match_phy_device = as21xxx_match_phy_device,
1058
+        .match_phy_device = as21xxx_match_phy_device,
1059
+        .read_status    = as21xxx_read_status,
1059
+        .read_status    = as21xxx_read_status,
1060
+        .led_brightness_set = as21xxx_led_brightness_set,
1060
+        .led_brightness_set = as21xxx_led_brightness_set,
1061
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1061
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1062
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1062
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1063
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1063
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1064
+        .led_polarity_set = as21xxx_led_polarity_set,
1064
+        .led_polarity_set = as21xxx_led_polarity_set,
1065
+    },
1065
+    },
1066
+    {
1066
+    {
1067
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
1067
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
1068
+        .name        = "Aeonsemi AS21010JB1",
1068
+        .name        = "Aeonsemi AS21010JB1",
1069
+        .probe        = as21xxx_probe,
1069
+        .probe        = as21xxx_probe,
1070
+        .match_phy_device = as21xxx_match_phy_device,
1070
+        .match_phy_device = as21xxx_match_phy_device,
1071
+        .read_status    = as21xxx_read_status,
1071
+        .read_status    = as21xxx_read_status,
1072
+        .led_brightness_set = as21xxx_led_brightness_set,
1072
+        .led_brightness_set = as21xxx_led_brightness_set,
1073
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1073
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1074
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1074
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1075
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1075
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1076
+        .led_polarity_set = as21xxx_led_polarity_set,
1076
+        .led_polarity_set = as21xxx_led_polarity_set,
1077
+    },
1077
+    },
1078
+    {
1078
+    {
1079
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
1079
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
1080
+        .name        = "Aeonsemi AS21210PB1",
1080
+        .name        = "Aeonsemi AS21210PB1",
1081
+        .probe        = as21xxx_probe,
1081
+        .probe        = as21xxx_probe,
1082
+        .match_phy_device = as21xxx_match_phy_device,
1082
+        .match_phy_device = as21xxx_match_phy_device,
1083
+        .read_status    = as21xxx_read_status,
1083
+        .read_status    = as21xxx_read_status,
1084
+        .led_brightness_set = as21xxx_led_brightness_set,
1084
+        .led_brightness_set = as21xxx_led_brightness_set,
1085
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1085
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1086
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1086
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1087
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1087
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1088
+        .led_polarity_set = as21xxx_led_polarity_set,
1088
+        .led_polarity_set = as21xxx_led_polarity_set,
1089
+    },
1089
+    },
1090
+    {
1090
+    {
1091
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
1091
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
1092
+        .name        = "Aeonsemi AS21510JB1",
1092
+        .name        = "Aeonsemi AS21510JB1",
1093
+        .probe        = as21xxx_probe,
1093
+        .probe        = as21xxx_probe,
1094
+        .match_phy_device = as21xxx_match_phy_device,
1094
+        .match_phy_device = as21xxx_match_phy_device,
1095
+        .read_status    = as21xxx_read_status,
1095
+        .read_status    = as21xxx_read_status,
1096
+        .led_brightness_set = as21xxx_led_brightness_set,
1096
+        .led_brightness_set = as21xxx_led_brightness_set,
1097
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1097
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1098
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1098
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1099
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1099
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1100
+        .led_polarity_set = as21xxx_led_polarity_set,
1100
+        .led_polarity_set = as21xxx_led_polarity_set,
1101
+    },
1101
+    },
1102
+    {
1102
+    {
1103
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
1103
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
1104
+        .name        = "Aeonsemi AS21510PB1",
1104
+        .name        = "Aeonsemi AS21510PB1",
1105
+        .probe        = as21xxx_probe,
1105
+        .probe        = as21xxx_probe,
1106
+        .match_phy_device = as21xxx_match_phy_device,
1106
+        .match_phy_device = as21xxx_match_phy_device,
1107
+        .read_status    = as21xxx_read_status,
1107
+        .read_status    = as21xxx_read_status,
1108
+        .led_brightness_set = as21xxx_led_brightness_set,
1108
+        .led_brightness_set = as21xxx_led_brightness_set,
1109
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1109
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1110
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1110
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1111
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1111
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1112
+        .led_polarity_set = as21xxx_led_polarity_set,
1112
+        .led_polarity_set = as21xxx_led_polarity_set,
1113
+    },
1113
+    },
1114
+    {
1114
+    {
1115
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
1115
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
1116
+        .name        = "Aeonsemi AS21511JB1",
1116
+        .name        = "Aeonsemi AS21511JB1",
1117
+        .probe        = as21xxx_probe,
1117
+        .probe        = as21xxx_probe,
1118
+        .match_phy_device = as21xxx_match_phy_device,
1118
+        .match_phy_device = as21xxx_match_phy_device,
1119
+        .read_status    = as21xxx_read_status,
1119
+        .read_status    = as21xxx_read_status,
1120
+        .led_brightness_set = as21xxx_led_brightness_set,
1120
+        .led_brightness_set = as21xxx_led_brightness_set,
1121
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1121
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1122
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1122
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1123
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1123
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1124
+        .led_polarity_set = as21xxx_led_polarity_set,
1124
+        .led_polarity_set = as21xxx_led_polarity_set,
1125
+    },
1125
+    },
1126
+    {
1126
+    {
1127
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
1127
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
1128
+        .name        = "Aeonsemi AS21210JB1",
1128
+        .name        = "Aeonsemi AS21210JB1",
1129
+        .probe        = as21xxx_probe,
1129
+        .probe        = as21xxx_probe,
1130
+        .match_phy_device = as21xxx_match_phy_device,
1130
+        .match_phy_device = as21xxx_match_phy_device,
1131
+        .read_status    = as21xxx_read_status,
1131
+        .read_status    = as21xxx_read_status,
1132
+        .led_brightness_set = as21xxx_led_brightness_set,
1132
+        .led_brightness_set = as21xxx_led_brightness_set,
1133
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1133
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1134
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1134
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1135
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1135
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1136
+        .led_polarity_set = as21xxx_led_polarity_set,
1136
+        .led_polarity_set = as21xxx_led_polarity_set,
1137
+    },
1137
+    },
1138
+    {
1138
+    {
1139
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
1139
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
1140
+        .name        = "Aeonsemi AS21511PB1",
1140
+        .name        = "Aeonsemi AS21511PB1",
1141
+        .probe        = as21xxx_probe,
1141
+        .probe        = as21xxx_probe,
1142
+        .match_phy_device = as21xxx_match_phy_device,
1142
+        .match_phy_device = as21xxx_match_phy_device,
1143
+        .read_status    = as21xxx_read_status,
1143
+        .read_status    = as21xxx_read_status,
1144
+        .led_brightness_set = as21xxx_led_brightness_set,
1144
+        .led_brightness_set = as21xxx_led_brightness_set,
1145
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1145
+        .led_hw_is_supported = as21xxx_led_hw_is_supported,
1146
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1146
+        .led_hw_control_set = as21xxx_led_hw_control_set,
1147
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1147
+        .led_hw_control_get = as21xxx_led_hw_control_get,
1148
+        .led_polarity_set = as21xxx_led_polarity_set,
1148
+        .led_polarity_set = as21xxx_led_polarity_set,
1149
+    },
1149
+    },
1150
+};
1150
+};
1151
+module_phy_driver(as21xxx_drivers);
1151
+module_phy_driver(as21xxx_drivers);
1152
+
1152
+
1153
+static struct mdio_device_id __maybe_unused as21xxx_tbl[] = {
1153
+static struct mdio_device_id __maybe_unused as21xxx_tbl[] = {
1154
+    { PHY_ID_MATCH_VENDOR(PHY_VENDOR_AEONSEMI) },
1154
+    { PHY_ID_MATCH_VENDOR(PHY_VENDOR_AEONSEMI) },
1155
+    { }
1155
+    { }
1156
+};
1156
+};
1157
+MODULE_DEVICE_TABLE(mdio, as21xxx_tbl);
1157
+MODULE_DEVICE_TABLE(mdio, as21xxx_tbl);
1158
+
1158
+
1159
+MODULE_DESCRIPTION("Aeonsemi AS21xxx PHY driver");
1159
+MODULE_DESCRIPTION("Aeonsemi AS21xxx PHY driver");
1160
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
1160
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
1161
+MODULE_LICENSE("GPL");
1161
+MODULE_LICENSE("GPL");
1162
--
1162
--
1163
2.48.1
1163
2.48.1
1164
1164
diff view generated by jsdifflib
1
Add Aeonsemi PHYs and the requirement of a firmware to correctly work.
1
Add Aeonsemi PHYs and the requirement of a firmware to correctly work.
2
Also document the max number of LEDs supported and what PHY ID expose
2
Also document the max number of LEDs supported and what PHY ID expose
3
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
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
11
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
11
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
12
---
12
---
13
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++++++++++++++++++
13
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++++++++++++++++++
14
MAINTAINERS | 1 +
14
MAINTAINERS | 1 +
15
2 files changed, 123 insertions(+)
15
2 files changed, 123 insertions(+)
16
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
16
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
17
17
18
diff --git a/Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml b/Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
18
diff --git a/Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml b/Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
19
new file mode 100644
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
21
--- /dev/null
22
+++ b/Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
22
+++ b/Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
23
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
24
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
24
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
25
+%YAML 1.2
25
+%YAML 1.2
26
+---
26
+---
27
+$id: http://devicetree.org/schemas/net/aeonsemi,as21xxx.yaml#
27
+$id: http://devicetree.org/schemas/net/aeonsemi,as21xxx.yaml#
28
+$schema: http://devicetree.org/meta-schemas/core.yaml#
28
+$schema: http://devicetree.org/meta-schemas/core.yaml#
29
+
29
+
30
+title: Aeonsemi AS21XXX Ethernet PHY
30
+title: Aeonsemi AS21XXX Ethernet PHY
31
+
31
+
32
+maintainers:
32
+maintainers:
33
+ - Christian Marangi <ansuelsmth@gmail.com>
33
+ - Christian Marangi <ansuelsmth@gmail.com>
34
+
34
+
35
+description: |
35
+description: |
36
+ Aeonsemi AS21xxx Ethernet PHYs requires a firmware to be loaded to actually
36
+ Aeonsemi AS21xxx Ethernet PHYs requires a firmware to be loaded to actually
37
+ work. The same firmware is compatible with various PHYs of the same family.
37
+ work. The same firmware is compatible with various PHYs of the same family.
38
+
38
+
39
+ A PHY with not firmware loaded will be exposed on the MDIO bus with ID
39
+ A PHY with not firmware loaded will be exposed on the MDIO bus with ID
40
+ 0x7500 0x7500 or 0x7500 0x9410 on C45 registers.
40
+ 0x7500 0x7500 or 0x7500 0x9410 on C45 registers.
41
+
41
+
42
+ This can be done and is implemented by OEM in 2 different way:
42
+ This can be done and is implemented by OEM in 2 different way:
43
+ - Attached SPI flash directly to the PHY with the firmware. The PHY
43
+ - Attached SPI flash directly to the PHY with the firmware. The PHY
44
+ will self load the firmware in the presence of this configuration.
44
+ will self load the firmware in the presence of this configuration.
45
+ - Manually provided firmware loaded from a file in the filesystem.
45
+ - Manually provided firmware loaded from a file in the filesystem.
46
+
46
+
47
+ Each PHY can support up to 5 LEDs.
47
+ Each PHY can support up to 5 LEDs.
48
+
48
+
49
+ AS2xxx PHY Name logic:
49
+ AS2xxx PHY Name logic:
50
+
50
+
51
+ AS21x1xxB1
51
+ AS21x1xxB1
52
+ ^ ^^
52
+ ^ ^^
53
+ | |J: Supports SyncE/PTP
53
+ | |J: Supports SyncE/PTP
54
+ | |P: No SyncE/PTP support
54
+ | |P: No SyncE/PTP support
55
+ | 1: Supports 2nd Serdes
55
+ | 1: Supports 2nd Serdes
56
+ | 2: Not 2nd Serdes support
56
+ | 2: Not 2nd Serdes support
57
+ 0: 10G, 5G, 2.5G
57
+ 0: 10G, 5G, 2.5G
58
+ 5: 5G, 2.5G
58
+ 5: 5G, 2.5G
59
+ 2: 2.5G
59
+ 2: 2.5G
60
+
60
+
61
+allOf:
61
+allOf:
62
+ - $ref: ethernet-phy.yaml#
62
+ - $ref: ethernet-phy.yaml#
63
+
63
+
64
+select:
64
+select:
65
+ properties:
65
+ properties:
66
+ compatible:
66
+ compatible:
67
+ contains:
67
+ contains:
68
+ enum:
68
+ enum:
69
+ - ethernet-phy-id7500.9410
69
+ - ethernet-phy-id7500.9410
70
+ - ethernet-phy-id7500.9402
70
+ - ethernet-phy-id7500.9402
71
+ - ethernet-phy-id7500.9412
71
+ - ethernet-phy-id7500.9412
72
+ - ethernet-phy-id7500.9422
72
+ - ethernet-phy-id7500.9422
73
+ - ethernet-phy-id7500.9432
73
+ - ethernet-phy-id7500.9432
74
+ - ethernet-phy-id7500.9442
74
+ - ethernet-phy-id7500.9442
75
+ - ethernet-phy-id7500.9452
75
+ - ethernet-phy-id7500.9452
76
+ - ethernet-phy-id7500.9462
76
+ - ethernet-phy-id7500.9462
77
+ - ethernet-phy-id7500.9472
77
+ - ethernet-phy-id7500.9472
78
+ - ethernet-phy-id7500.9482
78
+ - ethernet-phy-id7500.9482
79
+ - ethernet-phy-id7500.9492
79
+ - ethernet-phy-id7500.9492
80
+ required:
80
+ required:
81
+ - compatible
81
+ - compatible
82
+
82
+
83
+properties:
83
+properties:
84
+ reg:
84
+ reg:
85
+ maxItems: 1
85
+ maxItems: 1
86
+
86
+
87
+ firmware-name:
87
+ firmware-name:
88
+ description: specify the name of PHY firmware to load
88
+ description: specify the name of PHY firmware to load
89
+ maxItems: 1
89
+ maxItems: 1
90
+
90
+
91
+required:
91
+required:
92
+ - compatible
92
+ - compatible
93
+ - reg
93
+ - reg
94
+
94
+
95
+if:
95
+if:
96
+ properties:
96
+ properties:
97
+ compatible:
97
+ compatible:
98
+ contains:
98
+ contains:
99
+ const: ethernet-phy-id7500.9410
99
+ const: ethernet-phy-id7500.9410
100
+then:
100
+then:
101
+ required:
101
+ required:
102
+ - firmware-name
102
+ - firmware-name
103
+else:
103
+else:
104
+ properties:
104
+ properties:
105
+ firmware-name: false
105
+ firmware-name: false
106
+
106
+
107
+unevaluatedProperties: false
107
+unevaluatedProperties: false
108
+
108
+
109
+examples:
109
+examples:
110
+ - |
110
+ - |
111
+ #include <dt-bindings/leds/common.h>
111
+ #include <dt-bindings/leds/common.h>
112
+
112
+
113
+ mdio {
113
+ mdio {
114
+ #address-cells = <1>;
114
+ #address-cells = <1>;
115
+ #size-cells = <0>;
115
+ #size-cells = <0>;
116
+
116
+
117
+ ethernet-phy@1f {
117
+ ethernet-phy@1f {
118
+ compatible = "ethernet-phy-id7500.9410",
118
+ compatible = "ethernet-phy-id7500.9410",
119
+ "ethernet-phy-ieee802.3-c45";
119
+ "ethernet-phy-ieee802.3-c45";
120
+
120
+
121
+ reg = <31>;
121
+ reg = <31>;
122
+ firmware-name = "as21x1x_fw.bin";
122
+ firmware-name = "as21x1x_fw.bin";
123
+
123
+
124
+ leds {
124
+ leds {
125
+ #address-cells = <1>;
125
+ #address-cells = <1>;
126
+ #size-cells = <0>;
126
+ #size-cells = <0>;
127
+
127
+
128
+ led@0 {
128
+ led@0 {
129
+ reg = <0>;
129
+ reg = <0>;
130
+ color = <LED_COLOR_ID_GREEN>;
130
+ color = <LED_COLOR_ID_GREEN>;
131
+ function = LED_FUNCTION_LAN;
131
+ function = LED_FUNCTION_LAN;
132
+ function-enumerator = <0>;
132
+ function-enumerator = <0>;
133
+ default-state = "keep";
133
+ default-state = "keep";
134
+ };
134
+ };
135
+
135
+
136
+ led@1 {
136
+ led@1 {
137
+ reg = <1>;
137
+ reg = <1>;
138
+ color = <LED_COLOR_ID_GREEN>;
138
+ color = <LED_COLOR_ID_GREEN>;
139
+ function = LED_FUNCTION_LAN;
139
+ function = LED_FUNCTION_LAN;
140
+ function-enumerator = <1>;
140
+ function-enumerator = <1>;
141
+ default-state = "keep";
141
+ default-state = "keep";
142
+ };
142
+ };
143
+ };
143
+ };
144
+ };
144
+ };
145
+ };
145
+ };
146
diff --git a/MAINTAINERS b/MAINTAINERS
146
diff --git a/MAINTAINERS b/MAINTAINERS
147
index XXXXXXX..XXXXXXX 100644
147
index XXXXXXX..XXXXXXX 100644
148
--- a/MAINTAINERS
148
--- a/MAINTAINERS
149
+++ b/MAINTAINERS
149
+++ b/MAINTAINERS
150
@@ -XXX,XX +XXX,XX @@ AEONSEMI PHY DRIVER
150
@@ -XXX,XX +XXX,XX @@ AEONSEMI PHY DRIVER
151
M:    Christian Marangi <ansuelsmth@gmail.com>
151
M:    Christian Marangi <ansuelsmth@gmail.com>
152
L:    netdev@vger.kernel.org
152
L:    netdev@vger.kernel.org
153
S:    Maintained
153
S:    Maintained
154
+F:    Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
154
+F:    Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
155
F:    drivers/net/phy/as21xxx.c
155
F:    drivers/net/phy/as21xxx.c
156
156
157
AF8133J THREE-AXIS MAGNETOMETER DRIVER
157
AF8133J THREE-AXIS MAGNETOMETER DRIVER
158
--
158
--
159
2.48.1
159
2.48.1
diff view generated by jsdifflib