...
...
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 v5:
32
- Add Reviewed-by tag from Rob
33
- Fix subject in DT patch
34
- Fix wrong Suggested-by tag in patch 1
35
- Rework nxp patch to 80 column
36
Changes v4:
37
- Add Reviewed-by tag
38
- Better handle PHY ID scan in as21xxx
39
- Also simplify nxp driver and fix .match_phy_device
31
Changes v3:
40
Changes v3:
32
- Correct typo intergate->intergate
41
- Correct typo intergate->integrate
33
- Try to reduce to 80 column (where possible... define become
42
- Try to reduce to 80 column (where possible... define become
34
unreasable if split)
43
unreasable if split)
35
- Rework to new .match_phy_device implementation
44
- Rework to new .match_phy_device implementation
36
- Init active_low_led and fix other minor smatch war
45
- Init active_low_led and fix other minor smatch war
37
- Drop inline tag (kbot doesn't like it but not reported by checkpatch???)
46
- Drop inline tag (kbot doesn't like it but not reported by checkpatch???)
...
...
47
for generic PHY ID)
56
for generic PHY ID)
48
- Better document C22 in C45
57
- Better document C22 in C45
49
- Document PHY name logic
58
- Document PHY name logic
50
- Introduce patch to load PHY 2 times
59
- Introduce patch to load PHY 2 times
51
60
52
Christian Marangi (4):
61
Christian Marangi (6):
53
net: phy: pass PHY driver to .match_phy_device OP
62
net: phy: pass PHY driver to .match_phy_device OP
54
net: phy: bcm87xx: simplify .match_phy_device OP
63
net: phy: bcm87xx: simplify .match_phy_device OP
64
net: phy: nxp-c45-tja11xx: simplify .match_phy_device OP
65
net: phy: introduce genphy_match_phy_device()
55
net: phy: Add support for Aeonsemi AS21xxx PHYs
66
net: phy: Add support for Aeonsemi AS21xxx PHYs
56
dt-bindings: net: Document support for Aeonsemi PHYs
67
dt-bindings: net: Document support for Aeonsemi PHYs
57
68
58
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++
69
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++
59
MAINTAINERS | 7 +
70
MAINTAINERS | 7 +
60
drivers/net/phy/Kconfig | 12 +
71
drivers/net/phy/Kconfig | 12 +
61
drivers/net/phy/Makefile | 1 +
72
drivers/net/phy/Makefile | 1 +
62
drivers/net/phy/as21xxx.c | 1048 +++++++++++++++++
73
drivers/net/phy/as21xxx.c | 1067 +++++++++++++++++
63
drivers/net/phy/bcm87xx.c | 14 +-
74
drivers/net/phy/bcm87xx.c | 14 +-
64
drivers/net/phy/icplus.c | 6 +-
75
drivers/net/phy/icplus.c | 6 +-
65
drivers/net/phy/marvell10g.c | 12 +-
76
drivers/net/phy/marvell10g.c | 12 +-
66
drivers/net/phy/micrel.c | 6 +-
77
drivers/net/phy/micrel.c | 6 +-
78
drivers/net/phy/nxp-c45-tja11xx.c | 41 +-
67
drivers/net/phy/nxp-tja11xx.c | 6 +-
79
drivers/net/phy/nxp-tja11xx.c | 6 +-
68
drivers/net/phy/phy_device.c | 2 +-
80
drivers/net/phy/phy_device.c | 52 +-
69
drivers/net/phy/realtek/realtek_main.c | 27 +-
81
drivers/net/phy/realtek/realtek_main.c | 27 +-
70
drivers/net/phy/teranetics.c | 3 +-
82
drivers/net/phy/teranetics.c | 3 +-
71
include/linux/phy.h | 3 +-
83
include/linux/phy.h | 6 +-
72
14 files changed, 1238 insertions(+), 31 deletions(-)
84
15 files changed, 1316 insertions(+), 66 deletions(-)
73
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
85
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
74
create mode 100644 drivers/net/phy/as21xxx.c
86
create mode 100644 drivers/net/phy/as21xxx.c
75
87
76
--
88
--
77
2.48.1
89
2.48.1
diff view generated by jsdifflib
...
...
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) <linux@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
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
19
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
19
---
20
---
20
drivers/net/phy/bcm87xx.c | 6 ++++--
21
drivers/net/phy/bcm87xx.c | 6 ++++--
21
drivers/net/phy/icplus.c | 6 ++++--
22
drivers/net/phy/icplus.c | 6 ++++--
22
drivers/net/phy/marvell10g.c | 12 ++++++++----
23
drivers/net/phy/marvell10g.c | 12 ++++++++----
23
drivers/net/phy/micrel.c | 6 ++++--
24
drivers/net/phy/micrel.c | 6 ++++--
25
drivers/net/phy/nxp-c45-tja11xx.c | 12 ++++++++----
24
drivers/net/phy/nxp-tja11xx.c | 6 ++++--
26
drivers/net/phy/nxp-tja11xx.c | 6 ++++--
25
drivers/net/phy/phy_device.c | 2 +-
27
drivers/net/phy/phy_device.c | 2 +-
26
drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++---------
28
drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++---------
27
drivers/net/phy/teranetics.c | 3 ++-
29
drivers/net/phy/teranetics.c | 3 ++-
28
include/linux/phy.h | 3 ++-
30
include/linux/phy.h | 3 ++-
29
9 files changed, 47 insertions(+), 24 deletions(-)
31
10 files changed, 55 insertions(+), 28 deletions(-)
30
32
31
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
32
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
33
--- a/drivers/net/phy/bcm87xx.c
35
--- a/drivers/net/phy/bcm87xx.c
34
+++ b/drivers/net/phy/bcm87xx.c
36
+++ b/drivers/net/phy/bcm87xx.c
...
...
133
+static int ksz8795_match_phy_device(struct phy_device *phydev,
135
+static int ksz8795_match_phy_device(struct phy_device *phydev,
134
+                 const struct phy_driver *phydrv)
136
+                 const struct phy_driver *phydrv)
135
{
137
{
136
    return ksz8051_ksz8795_match_phy_device(phydev, false);
138
    return ksz8051_ksz8795_match_phy_device(phydev, false);
137
}
139
}
140
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/drivers/net/phy/nxp-c45-tja11xx.c
143
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
144
@@ -XXX,XX +XXX,XX @@ static int nxp_c45_macsec_ability(struct phy_device *phydev)
145
    return macsec_ability;
146
}
147
148
-static int tja1103_match_phy_device(struct phy_device *phydev)
149
+static int tja1103_match_phy_device(struct phy_device *phydev,
150
+                 const struct phy_driver *phydrv)
151
{
152
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
153
     !nxp_c45_macsec_ability(phydev);
154
}
155
156
-static int tja1104_match_phy_device(struct phy_device *phydev)
157
+static int tja1104_match_phy_device(struct phy_device *phydev,
158
+                 const struct phy_driver *phydrv)
159
{
160
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
161
     nxp_c45_macsec_ability(phydev);
162
}
163
164
-static int tja1120_match_phy_device(struct phy_device *phydev)
165
+static int tja1120_match_phy_device(struct phy_device *phydev,
166
+                 const struct phy_driver *phydrv)
167
{
168
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
169
     !nxp_c45_macsec_ability(phydev);
170
}
171
172
-static int tja1121_match_phy_device(struct phy_device *phydev)
173
+static int tja1121_match_phy_device(struct phy_device *phydev,
174
+                 const struct phy_driver *phydrv)
175
{
176
    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
177
     nxp_c45_macsec_ability(phydev);
138
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
139
index XXXXXXX..XXXXXXX 100644
179
index XXXXXXX..XXXXXXX 100644
140
--- a/drivers/net/phy/nxp-tja11xx.c
180
--- a/drivers/net/phy/nxp-tja11xx.c
141
+++ b/drivers/net/phy/nxp-tja11xx.c
181
+++ b/drivers/net/phy/nxp-tja11xx.c
142
@@ -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)
...
...
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
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
5
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
5
---
6
---
6
drivers/net/phy/bcm87xx.c | 14 ++++----------
7
drivers/net/phy/bcm87xx.c | 14 ++++----------
7
1 file changed, 4 insertions(+), 10 deletions(-)
8
1 file changed, 4 insertions(+), 10 deletions(-)
8
9
...
...
diff view generated by jsdifflib
New patch
1
Simplify .match_phy_device OP by using a generic function and using the
2
new phy_id PHY driver info instead of hardcoding the matching PHY ID
3
with new variant for macsec and no_macsec PHYs.
1
4
5
Also make use of PHY_ID_MATCH_MODEL macro and drop PHY_ID_MASK define to
6
introduce phy_id and phy_id_mask again in phy_driver struct.
7
8
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
9
---
10
drivers/net/phy/nxp-c45-tja11xx.c | 45 ++++++++++++++-----------------
11
1 file changed, 20 insertions(+), 25 deletions(-)
12
13
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/drivers/net/phy/nxp-c45-tja11xx.c
16
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
17
@@ -XXX,XX +XXX,XX @@
18
19
#include "nxp-c45-tja11xx.h"
20
21
-#define PHY_ID_MASK            GENMASK(31, 4)
22
/* Same id: TJA1103, TJA1104 */
23
#define PHY_ID_TJA_1103            0x001BB010
24
/* Same id: TJA1120, TJA1121 */
25
@@ -XXX,XX +XXX,XX @@ static int nxp_c45_macsec_ability(struct phy_device *phydev)
26
    return macsec_ability;
27
}
28
29
-static int tja1103_match_phy_device(struct phy_device *phydev,
30
-                 const struct phy_driver *phydrv)
31
+static int tja11xx_no_macsec_match_phy_device(struct phy_device *phydev,
32
+                     const struct phy_driver *phydrv)
33
{
34
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
35
-     !nxp_c45_macsec_ability(phydev);
36
-}
37
+    if (!phy_id_compare(phydev->phy_id, phydrv->phy_id,
38
+             phydrv->phy_id_mask))
39
+        return 0;
40
41
-static int tja1104_match_phy_device(struct phy_device *phydev,
42
-                 const struct phy_driver *phydrv)
43
-{
44
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
45
-     nxp_c45_macsec_ability(phydev);
46
+    return !nxp_c45_macsec_ability(phydev);
47
}
48
49
-static int tja1120_match_phy_device(struct phy_device *phydev,
50
-                 const struct phy_driver *phydrv)
51
+static int tja11xx_macsec_match_phy_device(struct phy_device *phydev,
52
+                     const struct phy_driver *phydrv)
53
{
54
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
55
-     !nxp_c45_macsec_ability(phydev);
56
-}
57
+    if (!phy_id_compare(phydev->phy_id, phydrv->phy_id,
58
+             phydrv->phy_id_mask))
59
+        return 0;
60
61
-static int tja1121_match_phy_device(struct phy_device *phydev,
62
-                 const struct phy_driver *phydrv)
63
-{
64
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
65
-     nxp_c45_macsec_ability(phydev);
66
+    return nxp_c45_macsec_ability(phydev);
67
}
68
69
static const struct nxp_c45_regmap tja1120_regmap = {
70
@@ -XXX,XX +XXX,XX @@ static const struct nxp_c45_phy_data tja1120_phy_data = {
71
72
static struct phy_driver nxp_c45_driver[] = {
73
    {
74
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
75
        .name            = "NXP C45 TJA1103",
76
        .get_features        = nxp_c45_get_features,
77
        .driver_data        = &tja1103_phy_data,
78
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
79
        .get_sqi        = nxp_c45_get_sqi,
80
        .get_sqi_max        = nxp_c45_get_sqi_max,
81
        .remove            = nxp_c45_remove,
82
-        .match_phy_device    = tja1103_match_phy_device,
83
+        .match_phy_device    = tja11xx_no_macsec_match_phy_device,
84
    },
85
    {
86
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
87
        .name            = "NXP C45 TJA1104",
88
        .get_features        = nxp_c45_get_features,
89
        .driver_data        = &tja1103_phy_data,
90
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
91
        .get_sqi        = nxp_c45_get_sqi,
92
        .get_sqi_max        = nxp_c45_get_sqi_max,
93
        .remove            = nxp_c45_remove,
94
-        .match_phy_device    = tja1104_match_phy_device,
95
+        .match_phy_device    = tja11xx_macsec_match_phy_device,
96
    },
97
    {
98
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120),
99
        .name            = "NXP C45 TJA1120",
100
        .get_features        = nxp_c45_get_features,
101
        .driver_data        = &tja1120_phy_data,
102
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
103
        .get_sqi        = nxp_c45_get_sqi,
104
        .get_sqi_max        = nxp_c45_get_sqi_max,
105
        .remove            = nxp_c45_remove,
106
-        .match_phy_device    = tja1120_match_phy_device,
107
+        .match_phy_device    = tja11xx_no_macsec_match_phy_device,
108
    },
109
    {
110
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120),
111
        .name            = "NXP C45 TJA1121",
112
        .get_features        = nxp_c45_get_features,
113
        .driver_data        = &tja1120_phy_data,
114
@@ -XXX,XX +XXX,XX @@ static struct phy_driver nxp_c45_driver[] = {
115
        .get_sqi        = nxp_c45_get_sqi,
116
        .get_sqi_max        = nxp_c45_get_sqi_max,
117
        .remove            = nxp_c45_remove,
118
-        .match_phy_device    = tja1121_match_phy_device,
119
+        .match_phy_device    = tja11xx_macsec_match_phy_device,
120
    },
121
};
122
123
--
124
2.48.1
diff view generated by jsdifflib
New patch
1
Introduce new API, genphy_match_phy_device(), to provide a way to check
2
to match a PHY driver for a PHY device based on the info stored in the
3
PHY device struct.
1
4
5
The function generalize the logic used in phy_bus_match() to check the
6
PHY ID whether if C45 or C22 ID should be used for matching.
7
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
10
and provide the correct PHY ID)
11
12
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
13
---
14
drivers/net/phy/phy_device.c | 52 +++++++++++++++++++++++++-----------
15
include/linux/phy.h | 3 +++
16
2 files changed, 40 insertions(+), 15 deletions(-)
17
18
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/drivers/net/phy/phy_device.c
21
+++ b/drivers/net/phy/phy_device.c
22
@@ -XXX,XX +XXX,XX @@ static int phy_scan_fixups(struct phy_device *phydev)
23
    return 0;
24
}
25
26
-static int phy_bus_match(struct device *dev, const struct device_driver *drv)
27
+/**
28
+ * genphy_match_phy_device - match a PHY device with a PHY driver
29
+ * @phydev: target phy_device struct
30
+ * @phydrv: target phy_driver struct
31
+ *
32
+ * Description: Checks whether the given PHY device matches the specified
33
+ * PHY driver. For Clause 45 PHYs, iterates over the available device
34
+ * identifiers and compares them against the driver's expected PHY ID,
35
+ * applying the provided mask. For Clause 22 PHYs, a direct ID comparison
36
+ * is performed.
37
+ *
38
+ * Return: 1 if the PHY device matches the driver, 0 otherwise.
39
+ */
40
+int genphy_match_phy_device(struct phy_device *phydev,
41
+             const struct phy_driver *phydrv)
42
{
43
-    struct phy_device *phydev = to_phy_device(dev);
44
-    const struct phy_driver *phydrv = to_phy_driver(drv);
45
-    const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
46
-    int i;
47
-
48
-    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
49
-        return 0;
50
-
51
-    if (phydrv->match_phy_device)
52
-        return phydrv->match_phy_device(phydev, phydrv);
53
-
54
    if (phydev->is_c45) {
55
+        const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
56
+        int i;
57
+
58
        for (i = 1; i < num_ids; i++) {
59
            if (phydev->c45_ids.device_ids[i] == 0xffffffff)
60
                continue;
61
@@ -XXX,XX +XXX,XX @@ static int phy_bus_match(struct device *dev, const struct device_driver *drv)
62
                     phydrv->phy_id, phydrv->phy_id_mask))
63
                return 1;
64
        }
65
+
66
        return 0;
67
-    } else {
68
-        return phy_id_compare(phydev->phy_id, phydrv->phy_id,
69
-                 phydrv->phy_id_mask);
70
    }
71
+
72
+    return phy_id_compare(phydev->phy_id, phydrv->phy_id,
73
+             phydrv->phy_id_mask);
74
+}
75
+EXPORT_SYMBOL_GPL(genphy_match_phy_device);
76
+
77
+static int phy_bus_match(struct device *dev, const struct device_driver *drv)
78
+{
79
+    struct phy_device *phydev = to_phy_device(dev);
80
+    const struct phy_driver *phydrv = to_phy_driver(drv);
81
+
82
+    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
83
+        return 0;
84
+
85
+    if (phydrv->match_phy_device)
86
+        return phydrv->match_phy_device(phydev, phydrv);
87
+
88
+    return genphy_match_phy_device(phydev, phydrv);
89
}
90
91
static ssize_t
92
diff --git a/include/linux/phy.h b/include/linux/phy.h
93
index XXXXXXX..XXXXXXX 100644
94
--- a/include/linux/phy.h
95
+++ b/include/linux/phy.h
96
@@ -XXX,XX +XXX,XX @@ char *phy_attached_info_irq(struct phy_device *phydev)
97
    __malloc;
98
void phy_attached_info(struct phy_device *phydev);
99
100
+int genphy_match_phy_device(struct phy_device *phydev,
101
+             const struct phy_driver *phydrv);
102
+
103
/* Clause 22 PHY */
104
int genphy_read_abilities(struct phy_device *phydev);
105
int genphy_setup_forced(struct phy_device *phydev);
106
--
107
2.48.1
diff view generated by jsdifflib
...
...
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 | 1048 +++++++++++++++++++++++++++++++++++++
33
drivers/net/phy/as21xxx.c | 1067 +++++++++++++++++++++++++++++++++++++
34
4 files changed, 1067 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
...
...
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
+             u32 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.
...
...
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
+             struct as21xxx_priv *priv,
535
+             u16 opcode, u16 *data, unsigned int data_len,
534
+             u16 opcode, u16 *data, unsigned int data_len,
536
+             u16 *ret_sts)
535
+             u16 *ret_sts)
537
+{
536
+{
538
+    u32 cmd;
537
+    struct as21xxx_priv *priv = phydev->priv;
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.
...
...
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
+             struct as21xxx_priv *priv,
568
+             u16 ret_sts, u16 *data)
567
+             u16 ret_sts, u16 *data)
569
+{
568
+{
570
+    unsigned int size = FIELD_GET(AEON_IPC_STS_SIZE, ret_sts);
569
+    struct as21xxx_priv *priv = phydev->priv;
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
+    if (size > AEON_IPC_DATA_MAX)
579
+    if (size > AEON_IPC_DATA_MAX)
579
+        return -EINVAL;
580
+        return -EINVAL;
580
+
581
+
581
+    mutex_lock(&priv->ipc_lock);
582
+    mutex_lock(&priv->ipc_lock);
582
+
583
+
...
...
592
+
593
+
593
+out:
594
+out:
594
+    mutex_unlock(&priv->ipc_lock);
595
+    mutex_unlock(&priv->ipc_lock);
595
+
596
+
596
+    return size;
597
+    return size;
598
+}
599
+
600
+static int aeon_ipc_noop(struct phy_device *phydev,
601
+             struct as21xxx_priv *priv, u16 *ret_sts)
602
+{
603
+    u16 cmd;
604
+
605
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) |
606
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP);
607
+
608
+    return aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
597
+}
609
+}
598
+
610
+
599
+/* Logic to sync parity bit with IPC.
611
+/* Logic to sync parity bit with IPC.
600
+ * 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
601
+ * to handle the packet only for the second one. This way
613
+ * to handle the packet only for the second one. This way
602
+ * we make sure we are sync for every next cmd.
614
+ * we make sure we are sync for every next cmd.
603
+ */
615
+ */
604
+static int aeon_ipc_sync_parity(struct phy_device *phydev,
616
+static int aeon_ipc_sync_parity(struct phy_device *phydev,
605
+                struct as21xxx_priv *priv)
617
+                struct as21xxx_priv *priv)
606
+{
618
+{
607
+    u16 ret_sts;
619
+    u16 ret_sts;
608
+    u32 cmd;
609
+    int ret;
620
+    int ret;
610
+
621
+
611
+    mutex_lock(&priv->ipc_lock);
622
+    mutex_lock(&priv->ipc_lock);
612
+
623
+
613
+    /* Send NOP with no parity */
624
+    /* Send NOP with no parity */
614
+    cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) |
625
+    aeon_ipc_noop(phydev, priv, NULL);
615
+     FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP);
616
+    aeon_ipc_send_cmd(phydev, priv, cmd, NULL);
617
+
626
+
618
+    /* Reset packet parity */
627
+    /* Reset packet parity */
619
+    priv->parity_status = false;
628
+    priv->parity_status = false;
620
+
629
+
621
+    /* Send second NOP with no parity */
630
+    /* Send second NOP with no parity */
622
+    ret = aeon_ipc_send_cmd(phydev, priv, cmd, &ret_sts);
631
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
623
+
632
+
624
+    mutex_unlock(&priv->ipc_lock);
633
+    mutex_unlock(&priv->ipc_lock);
625
+
634
+
626
+    /* We expect to return -EINVAL */
635
+    /* We expect to return -EINVAL */
627
+    if (ret != -EINVAL)
636
+    if (ret != -EINVAL)
...
...
634
+    }
643
+    }
635
+
644
+
636
+    return 0;
645
+    return 0;
637
+}
646
+}
638
+
647
+
639
+static int aeon_ipc_get_fw_version(struct phy_device *phydev,
648
+static int aeon_ipc_get_fw_version(struct phy_device *phydev)
640
+                 struct as21xxx_priv *priv)
641
+{
649
+{
642
+    u16 ret_data[8], data[1];
650
+    u16 ret_data[8], data[1];
643
+    u16 ret_sts;
651
+    u16 ret_sts;
644
+    int ret;
652
+    int ret;
645
+
653
+
646
+    data[0] = IPC_INFO_VERSION;
654
+    data[0] = IPC_INFO_VERSION;
647
+    ret = aeon_ipc_send_msg(phydev, priv, IPC_CMD_INFO, data,
655
+    ret = aeon_ipc_send_msg(phydev, IPC_CMD_INFO, data,
648
+                sizeof(data), &ret_sts);
656
+                sizeof(data), &ret_sts);
649
+    if (ret)
657
+    if (ret)
650
+        return ret;
658
+        return ret;
651
+
659
+
652
+    ret = aeon_ipc_rcv_msg(phydev, priv, ret_sts, ret_data);
660
+    ret = aeon_ipc_rcv_msg(phydev, ret_sts, ret_data);
653
+    if (ret < 0)
661
+    if (ret < 0)
654
+        return ret;
662
+        return ret;
655
+
663
+
656
+    phydev_info(phydev, "Firmware Version: %s\n", (char *)ret_data);
664
+    phydev_info(phydev, "Firmware Version: %s\n", (char *)ret_data);
657
+
665
+
658
+    return 0;
666
+    return 0;
659
+}
667
+}
660
+
668
+
661
+static int aeon_dpc_ra_enable(struct phy_device *phydev,
669
+static int aeon_dpc_ra_enable(struct phy_device *phydev)
662
+             struct as21xxx_priv *priv)
663
+{
670
+{
664
+    u16 data[2];
671
+    u16 data[2];
665
+    u16 ret_sts;
672
+    u16 ret_sts;
666
+
673
+
667
+    data[0] = IPC_CFG_PARAM_DIRECT;
674
+    data[0] = IPC_CFG_PARAM_DIRECT;
668
+    data[1] = IPC_CFG_PARAM_DIRECT_DPC_RA;
675
+    data[1] = IPC_CFG_PARAM_DIRECT_DPC_RA;
669
+
676
+
670
+    return aeon_ipc_send_msg(phydev, priv, IPC_CMD_CFG_PARAM, data,
677
+    return aeon_ipc_send_msg(phydev, IPC_CMD_CFG_PARAM, data,
671
+                 sizeof(data), &ret_sts);
678
+                 sizeof(data), &ret_sts);
672
+}
679
+}
673
+
680
+
674
+static int as21xxx_probe(struct phy_device *phydev)
681
+static int as21xxx_probe(struct phy_device *phydev)
675
+{
682
+{
...
...
689
+
696
+
690
+    ret = aeon_ipc_sync_parity(phydev, priv);
697
+    ret = aeon_ipc_sync_parity(phydev, priv);
691
+    if (ret)
698
+    if (ret)
692
+        return ret;
699
+        return ret;
693
+
700
+
694
+    return aeon_ipc_get_fw_version(phydev, priv);
701
+    ret = aeon_ipc_get_fw_version(phydev);
702
+    if (ret)
703
+        return ret;
704
+
705
+    /* Enable PTP clk if not already Enabled */
706
+    ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK,
707
+             VEND1_PTP_CLK_EN);
708
+    if (ret)
709
+        return ret;
710
+
711
+    return aeon_dpc_ra_enable(phydev);
695
+}
712
+}
696
+
713
+
697
+static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
714
+static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
698
+{
715
+{
699
+    int status;
716
+    int status;
...
...
939
+
956
+
940
+static int as21xxx_match_phy_device(struct phy_device *phydev,
957
+static int as21xxx_match_phy_device(struct phy_device *phydev,
941
+                 const struct phy_driver *phydrv)
958
+                 const struct phy_driver *phydrv)
942
+{
959
+{
943
+    struct as21xxx_priv *priv;
960
+    struct as21xxx_priv *priv;
961
+    u16 ret_sts;
944
+    u32 phy_id;
962
+    u32 phy_id;
945
+    int ret;
963
+    int ret;
946
+
964
+
947
+    /* Skip PHY that are not AS21xxx or already have firmware loaded */
965
+    /* Skip PHY that are not AS21xxx or already have firmware loaded */
948
+    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)
949
+        return phydev->phy_id == phydrv->phy_id;
967
+        return genphy_match_phy_device(phydev, phydrv);
950
+
968
+
951
+    /* Read PHY ID to handle firmware just loaded */
969
+    /* Read PHY ID to handle firmware just loaded */
952
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1);
970
+    ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1);
953
+    if (ret < 0)
971
+    if (ret < 0)
954
+        return ret;
972
+        return ret;
...
...
972
+
990
+
973
+    mutex_init(&priv->ipc_lock);
991
+    mutex_init(&priv->ipc_lock);
974
+
992
+
975
+    ret = aeon_firmware_load(phydev);
993
+    ret = aeon_firmware_load(phydev);
976
+    if (ret)
994
+    if (ret)
977
+        return ret;
995
+        goto out;
978
+
996
+
997
+    /* Sync parity... */
979
+    ret = aeon_ipc_sync_parity(phydev, priv);
998
+    ret = aeon_ipc_sync_parity(phydev, priv);
980
+    if (ret)
999
+    if (ret)
981
+        return ret;
1000
+        goto out;
982
+
1001
+
983
+    /* Enable PTP clk if not already Enabled */
1002
+    /* ...and send a third NOOP cmd to wait for firmware finish loading */
984
+    ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK,
1003
+    ret = aeon_ipc_noop(phydev, priv, &ret_sts);
985
+             VEND1_PTP_CLK_EN);
1004
+    if (ret)
986
+    if (ret)
1005
+        goto out;
987
+        return ret;
1006
+
988
+
1007
+out:
989
+    ret = aeon_dpc_ra_enable(phydev, priv);
990
+    if (ret)
991
+        return ret;
992
+
993
+    mutex_destroy(&priv->ipc_lock);
1008
+    mutex_destroy(&priv->ipc_lock);
994
+    kfree(priv);
1009
+    kfree(priv);
995
+
1010
+
996
+    /* Return not maching anyway as PHY ID will change after
1011
+    /* Return not maching anyway as PHY ID will change after
997
+     * firmware is loaded.
1012
+     * firmware is loaded. This relies on the driver probe
1013
+     * order where the first PHY driver probed is the
1014
+     * generic one.
998
+     */
1015
+     */
999
+    return 0;
1016
+    return ret;
1000
+}
1017
+}
1001
+
1018
+
1002
+static struct phy_driver as21xxx_drivers[] = {
1019
+static struct phy_driver as21xxx_drivers[] = {
1003
+    {
1020
+    {
1004
+        /* PHY expose in C45 as 0x7500 0x9410
1021
+        /* PHY expose in C45 as 0x7500 0x9410
1005
+         * before firmware is loaded.
1022
+         * before firmware is loaded.
1023
+         * This driver entry must be attempted first to load
1024
+         * the firmware and thus update the ID registers.
1006
+         */
1025
+         */
1007
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX),
1026
+        PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX),
1008
+        .name        = "Aeonsemi AS21xxx",
1027
+        .name        = "Aeonsemi AS21xxx",
1009
+        .match_phy_device = as21xxx_match_phy_device,
1028
+        .match_phy_device = as21xxx_match_phy_device,
1010
+    },
1029
+    },
...
...
diff view generated by jsdifflib
1
Document support for Aeonsemi PHYs and the requirement of a firmware to
1
Add Aeonsemi PHYs and the requirement of a firmware to correctly work.
2
correctly work. Also document the max number of LEDs supported and what
2
Also document the max number of LEDs supported and what PHY ID expose
3
PHY ID expose when no firmware is loaded.
3
when no firmware is loaded.
4
4
5
Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
5
Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1,
6
AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
6
AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1,
7
AS21210PB1 that all register with the PHY ID 0x7500 0x9410 on C45
7
AS21210PB1 that all register with the PHY ID 0x7500 0x9410 on C45
8
registers before the firmware is loaded.
8
registers before the firmware is loaded.
9
9
10
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
10
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
11
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
11
---
12
---
12
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++++++++++++++++++
13
.../bindings/net/aeonsemi,as21xxx.yaml | 122 ++++++++++++++++++
13
MAINTAINERS | 1 +
14
MAINTAINERS | 1 +
14
2 files changed, 123 insertions(+)
15
2 files changed, 123 insertions(+)
...
...
diff view generated by jsdifflib