...
...
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
31
Changes v4:
36
Changes v4:
32
- Add Reviewed-by tag
37
- Add Reviewed-by tag
33
- Better handle PHY ID scan in as21xxx
38
- Better handle PHY ID scan in as21xxx
34
- Also simplify nxp driver and fix .match_phy_device
39
- Also simplify nxp driver and fix .match_phy_device
35
Changes v3:
40
Changes v3:
...
...
68
drivers/net/phy/as21xxx.c | 1067 +++++++++++++++++
73
drivers/net/phy/as21xxx.c | 1067 +++++++++++++++++
69
drivers/net/phy/bcm87xx.c | 14 +-
74
drivers/net/phy/bcm87xx.c | 14 +-
70
drivers/net/phy/icplus.c | 6 +-
75
drivers/net/phy/icplus.c | 6 +-
71
drivers/net/phy/marvell10g.c | 12 +-
76
drivers/net/phy/marvell10g.c | 12 +-
72
drivers/net/phy/micrel.c | 6 +-
77
drivers/net/phy/micrel.c | 6 +-
73
drivers/net/phy/nxp-c45-tja11xx.c | 35 +-
78
drivers/net/phy/nxp-c45-tja11xx.c | 41 +-
74
drivers/net/phy/nxp-tja11xx.c | 6 +-
79
drivers/net/phy/nxp-tja11xx.c | 6 +-
75
drivers/net/phy/phy_device.c | 52 +-
80
drivers/net/phy/phy_device.c | 52 +-
76
drivers/net/phy/realtek/realtek_main.c | 27 +-
81
drivers/net/phy/realtek/realtek_main.c | 27 +-
77
drivers/net/phy/teranetics.c | 3 +-
82
drivers/net/phy/teranetics.c | 3 +-
78
include/linux/phy.h | 6 +-
83
include/linux/phy.h | 6 +-
79
15 files changed, 1310 insertions(+), 66 deletions(-)
84
15 files changed, 1316 insertions(+), 66 deletions(-)
80
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
85
create mode 100644 Documentation/devicetree/bindings/net/aeonsemi,as21xxx.yaml
81
create mode 100644 drivers/net/phy/as21xxx.c
86
create mode 100644 drivers/net/phy/as21xxx.c
82
87
83
--
88
--
84
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: Reviewed-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 ++++--
...
...
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
...
...
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
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
8
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
9
---
9
---
10
drivers/net/phy/nxp-c45-tja11xx.c | 39 +++++++++++--------------------
10
drivers/net/phy/nxp-c45-tja11xx.c | 45 ++++++++++++++-----------------
11
1 file changed, 14 insertions(+), 25 deletions(-)
11
1 file changed, 20 insertions(+), 25 deletions(-)
12
12
13
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
13
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/drivers/net/phy/nxp-c45-tja11xx.c
15
--- a/drivers/net/phy/nxp-c45-tja11xx.c
16
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
16
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
...
...
30
-                 const struct phy_driver *phydrv)
30
-                 const struct phy_driver *phydrv)
31
+static int tja11xx_no_macsec_match_phy_device(struct phy_device *phydev,
31
+static int tja11xx_no_macsec_match_phy_device(struct phy_device *phydev,
32
+                     const struct phy_driver *phydrv)
32
+                     const struct phy_driver *phydrv)
33
{
33
{
34
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
34
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
35
+    return phy_id_compare(phydev->phy_id, phydrv->phy_id, phydrv->phy_id_mask) &&
35
-     !nxp_c45_macsec_ability(phydev);
36
     !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);
37
}
47
}
38
48
39
-static int tja1104_match_phy_device(struct phy_device *phydev,
49
-static int tja1120_match_phy_device(struct phy_device *phydev,
40
-                 const struct phy_driver *phydrv)
50
-                 const struct phy_driver *phydrv)
41
+static int tja11xx_macsec_match_phy_device(struct phy_device *phydev,
51
+static int tja11xx_macsec_match_phy_device(struct phy_device *phydev,
42
+                     const struct phy_driver *phydrv)
52
+                     const struct phy_driver *phydrv)
43
{
53
{
44
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) &&
45
-     nxp_c45_macsec_ability(phydev);
46
-}
47
-
48
-static int tja1120_match_phy_device(struct phy_device *phydev,
49
-                 const struct phy_driver *phydrv)
50
-{
51
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
54
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
52
-     !nxp_c45_macsec_ability(phydev);
55
-     !nxp_c45_macsec_ability(phydev);
53
-}
56
-}
54
-
57
+    if (!phy_id_compare(phydev->phy_id, phydrv->phy_id,
58
+             phydrv->phy_id_mask))
59
+        return 0;
60
55
-static int tja1121_match_phy_device(struct phy_device *phydev,
61
-static int tja1121_match_phy_device(struct phy_device *phydev,
56
-                 const struct phy_driver *phydrv)
62
-                 const struct phy_driver *phydrv)
57
-{
63
-{
58
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
64
-    return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) &&
59
+    return phy_id_compare(phydev->phy_id, phydrv->phy_id, phydrv->phy_id_mask) &&
65
-     nxp_c45_macsec_ability(phydev);
60
     nxp_c45_macsec_ability(phydev);
66
+    return nxp_c45_macsec_ability(phydev);
61
}
67
}
62
68
69
static const struct nxp_c45_regmap tja1120_regmap = {
63
@@ -XXX,XX +XXX,XX @@ static const struct nxp_c45_phy_data tja1120_phy_data = {
70
@@ -XXX,XX +XXX,XX @@ static const struct nxp_c45_phy_data tja1120_phy_data = {
64
71
65
static struct phy_driver nxp_c45_driver[] = {
72
static struct phy_driver nxp_c45_driver[] = {
66
    {
73
    {
67
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
74
+        PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
...
...
diff view generated by jsdifflib
1
Introduce new API, genphy_match_phy_device(), to provide a way to check
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
2
to match a PHY driver for a PHY device based on the info stored in the
3
PHY device struct.
3
PHY device struct.
4
4
5
The function generalize the logic used in phy_bus_match() to check the
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.
6
PHY ID whether if C45 or C22 ID should be used for matching.
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
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
12
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
13
---
13
---
14
drivers/net/phy/phy_device.c | 52 +++++++++++++++++++++++++-----------
14
drivers/net/phy/phy_device.c | 52 +++++++++++++++++++++++++-----------
15
include/linux/phy.h | 3 +++
15
include/linux/phy.h | 3 +++
16
2 files changed, 40 insertions(+), 15 deletions(-)
16
2 files changed, 40 insertions(+), 15 deletions(-)
17
17
18
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
18
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/drivers/net/phy/phy_device.c
20
--- a/drivers/net/phy/phy_device.c
21
+++ b/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)
22
@@ -XXX,XX +XXX,XX @@ static int phy_scan_fixups(struct phy_device *phydev)
23
    return 0;
23
    return 0;
24
}
24
}
25
25
26
-static int phy_bus_match(struct device *dev, const struct device_driver *drv)
26
-static int phy_bus_match(struct device *dev, const struct device_driver *drv)
27
+/**
27
+/**
28
+ * genphy_match_phy_device - match a PHY device with a PHY driver
28
+ * genphy_match_phy_device - match a PHY device with a PHY driver
29
+ * @phydev: target phy_device struct
29
+ * @phydev: target phy_device struct
30
+ * @phydrv: target phy_driver struct
30
+ * @phydrv: target phy_driver struct
31
+ *
31
+ *
32
+ * Description: Checks whether the given PHY device matches the specified
32
+ * Description: Checks whether the given PHY device matches the specified
33
+ * PHY driver. For Clause 45 PHYs, iterates over the available device
33
+ * PHY driver. For Clause 45 PHYs, iterates over the available device
34
+ * identifiers and compares them against the driver's expected PHY ID,
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
35
+ * applying the provided mask. For Clause 22 PHYs, a direct ID comparison
36
+ * is performed.
36
+ * is performed.
37
+ *
37
+ *
38
+ * Return: 1 if the PHY device matches the driver, 0 otherwise.
38
+ * Return: 1 if the PHY device matches the driver, 0 otherwise.
39
+ */
39
+ */
40
+int genphy_match_phy_device(struct phy_device *phydev,
40
+int genphy_match_phy_device(struct phy_device *phydev,
41
+             const struct phy_driver *phydrv)
41
+             const struct phy_driver *phydrv)
42
{
42
{
43
-    struct phy_device *phydev = to_phy_device(dev);
43
-    struct phy_device *phydev = to_phy_device(dev);
44
-    const struct phy_driver *phydrv = to_phy_driver(drv);
44
-    const struct phy_driver *phydrv = to_phy_driver(drv);
45
-    const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
45
-    const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
46
-    int i;
46
-    int i;
47
-
47
-
48
-    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
48
-    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
49
-        return 0;
49
-        return 0;
50
-
50
-
51
-    if (phydrv->match_phy_device)
51
-    if (phydrv->match_phy_device)
52
-        return phydrv->match_phy_device(phydev, phydrv);
52
-        return phydrv->match_phy_device(phydev, phydrv);
53
-
53
-
54
    if (phydev->is_c45) {
54
    if (phydev->is_c45) {
55
+        const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
55
+        const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
56
+        int i;
56
+        int i;
57
+
57
+
58
        for (i = 1; i < num_ids; i++) {
58
        for (i = 1; i < num_ids; i++) {
59
            if (phydev->c45_ids.device_ids[i] == 0xffffffff)
59
            if (phydev->c45_ids.device_ids[i] == 0xffffffff)
60
                continue;
60
                continue;
61
@@ -XXX,XX +XXX,XX @@ static int phy_bus_match(struct device *dev, const struct device_driver *drv)
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))
62
                     phydrv->phy_id, phydrv->phy_id_mask))
63
                return 1;
63
                return 1;
64
        }
64
        }
65
+
65
+
66
        return 0;
66
        return 0;
67
-    } else {
67
-    } else {
68
-        return phy_id_compare(phydev->phy_id, phydrv->phy_id,
68
-        return phy_id_compare(phydev->phy_id, phydrv->phy_id,
69
-                 phydrv->phy_id_mask);
69
-                 phydrv->phy_id_mask);
70
    }
70
    }
71
+
71
+
72
+    return phy_id_compare(phydev->phy_id, phydrv->phy_id,
72
+    return phy_id_compare(phydev->phy_id, phydrv->phy_id,
73
+             phydrv->phy_id_mask);
73
+             phydrv->phy_id_mask);
74
+}
74
+}
75
+EXPORT_SYMBOL_GPL(genphy_match_phy_device);
75
+EXPORT_SYMBOL_GPL(genphy_match_phy_device);
76
+
76
+
77
+static int phy_bus_match(struct device *dev, const struct device_driver *drv)
77
+static int phy_bus_match(struct device *dev, const struct device_driver *drv)
78
+{
78
+{
79
+    struct phy_device *phydev = to_phy_device(dev);
79
+    struct phy_device *phydev = to_phy_device(dev);
80
+    const struct phy_driver *phydrv = to_phy_driver(drv);
80
+    const struct phy_driver *phydrv = to_phy_driver(drv);
81
+
81
+
82
+    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
82
+    if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY))
83
+        return 0;
83
+        return 0;
84
+
84
+
85
+    if (phydrv->match_phy_device)
85
+    if (phydrv->match_phy_device)
86
+        return phydrv->match_phy_device(phydev, phydrv);
86
+        return phydrv->match_phy_device(phydev, phydrv);
87
+
87
+
88
+    return genphy_match_phy_device(phydev, phydrv);
88
+    return genphy_match_phy_device(phydev, phydrv);
89
}
89
}
90
90
91
static ssize_t
91
static ssize_t
92
diff --git a/include/linux/phy.h b/include/linux/phy.h
92
diff --git a/include/linux/phy.h b/include/linux/phy.h
93
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
94
--- a/include/linux/phy.h
94
--- a/include/linux/phy.h
95
+++ b/include/linux/phy.h
95
+++ b/include/linux/phy.h
96
@@ -XXX,XX +XXX,XX @@ char *phy_attached_info_irq(struct phy_device *phydev)
96
@@ -XXX,XX +XXX,XX @@ char *phy_attached_info_irq(struct phy_device *phydev)
97
    __malloc;
97
    __malloc;
98
void phy_attached_info(struct phy_device *phydev);
98
void phy_attached_info(struct phy_device *phydev);
99
99
100
+int genphy_match_phy_device(struct phy_device *phydev,
100
+int genphy_match_phy_device(struct phy_device *phydev,
101
+             const struct phy_driver *phydrv);
101
+             const struct phy_driver *phydrv);
102
+
102
+
103
/* Clause 22 PHY */
103
/* Clause 22 PHY */
104
int genphy_read_abilities(struct phy_device *phydev);
104
int genphy_read_abilities(struct phy_device *phydev);
105
int genphy_setup_forced(struct phy_device *phydev);
105
int genphy_setup_forced(struct phy_device *phydev);
106
--
106
--
107
2.48.1
107
2.48.1
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
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