QCA8084 is four-port PHY with maximum link capability 2.5G,
which supports the interface mode qusgmii and sgmii mode,
there are two PCSs available to connected with ethernet port.
QCA8084 can work in switch mode or PHY mode.
For switch mode, both PCS0 and PCS1 work on sgmii mode.
For PHY mode, PCS1 works on qusgmii mode.
The fourth PHY connected with PCS0 works on sgmii mode.
Besides this PHY driver patches, the PCS driver is also needed
to bring up the qca8084 device, which mainly configurs PCS
and clocks.
The qca8084 PHY driver depends on the following clock controller
patchset, the initial clocks and resets are provided by the clock
controller driver below.
https://lore.kernel.org/lkml/[email protected]/T/
Changes in v3:
* pick the two patches to introduce the interface mode
10g-qxgmii from Vladimir Oltean([email protected]).
* add the function phydev_id_is_qca808x to identify the
PHY qca8081 and qca8084.
* update the interface mode name PHY_INTERFACE_MODE_QUSGMII
to PHY_INTERFACE_MODE_10G_QXGMII.
Changes in v4:
* remove the following patch:
<net: phylink: move phylink_pcs_neg_mode() to phylink.c>.
* split out 10g_qxgmii change of ethernet-controller.yaml.
Changes in v5:
* update the author of the patch below.
<introduce core support for phy-mode = "10g-qxgmii">.
Changes in v6:
* drop the "inline" keyword.
* apply the patches with "--max-line-length=80".
Changes in v7:
* add possible interfaces of phydev
* customize phy address
* add initialized clock & reset config
* add the work mode config
* update qca,ar803x.yaml for the new added properties
Luo Jie (12):
net: phy: at803x: add QCA8084 ethernet phy support
net: phy: at803x: add the function phydev_id_is_qca808x
net: phy: at803x: Add qca8084_config_init function
net: phy: at803x: add qca8084_link_change_notify
net: phy: at803x: add the possible_interfaces
net: phy: at803x: add qca8084 switch registe access
net: phy: at803x: set MDIO address of qca8084 PHY
net: phy: at803x: parse qca8084 clocks and resets
net: phy: at803x: add qca808x initial config sequence
net: phy: at803x: configure qca8084 common clocks
net: phy: at803x: configure qca8084 work mode
dt-bindings: net: ar803x: add qca8084 PHY propetry
Vladimir Oltean (2):
net: phy: introduce core support for phy-mode = "10g-qxgmii"
dt-bindings: net: ethernet-controller: add 10g-qxgmii mode
.../bindings/net/ethernet-controller.yaml | 1 +
.../devicetree/bindings/net/qca,ar803x.yaml | 158 ++++-
Documentation/networking/phy.rst | 6 +
drivers/net/phy/at803x.c | 586 +++++++++++++++++-
drivers/net/phy/phy-core.c | 1 +
drivers/net/phy/phylink.c | 11 +-
include/linux/phy.h | 4 +
include/linux/phylink.h | 2 +
8 files changed, 758 insertions(+), 11 deletions(-)
base-commit: 48e8992e33abf054bcc0bb2e77b2d43bb899212e
--
2.42.0
Add qca8084 PHY support, which is four-port PHY with maximum
link capability 2.5G, the features of each port is almost same
as QCA8081 and slave seed config is not needed.
Three kind of interface modes supported by qca8084.
PHY_INTERFACE_MODE_10G_QXGMII, PHY_INTERFACE_MODE_2500BASEX and
PHY_INTERFACE_MODE_SGMII.
The PCS(serdes) and clock are also needed to be configured to
bringup qca8084 PHY, which will be added in the pcs driver.
The additional CDT configurations used for qca8084.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 49 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 37fb033e1c29..8dfdf2ff56a5 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -176,6 +176,7 @@
#define AT8030_PHY_ID_MASK 0xffffffef
#define QCA8081_PHY_ID 0x004dd101
+#define QCA8084_PHY_ID 0x004dd180
#define QCA8327_A_PHY_ID 0x004dd033
#define QCA8327_B_PHY_ID 0x004dd034
@@ -1760,6 +1761,9 @@ static bool qca808x_is_prefer_master(struct phy_device *phydev)
static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev)
{
+ if (phydev_id_compare(phydev, QCA8084_PHY_ID))
+ return false;
+
return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported);
}
@@ -1824,6 +1828,23 @@ static int qca808x_read_status(struct phy_device *phydev)
return ret;
if (phydev->link) {
+ /* There are two PCSs available for QCA8084, which support the
+ * following interface modes.
+ *
+ * 1. PHY_INTERFACE_MODE_10G_QXGMII utilizes PCS1 for all
+ * available 4 ports, which is for all link speeds.
+ *
+ * 2. PHY_INTERFACE_MODE_2500BASEX utilizes PCS0 for the
+ * fourth port, which is only for the link speed 2500M same
+ * as QCA8081.
+ *
+ * 3. PHY_INTERFACE_MODE_SGMII utilizes PCS0 for the fourth
+ * port, which is for the link speed 10M, 100M and 1000M same
+ * as QCA8081.
+ */
+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII)
+ return 0;
+
if (phydev->speed == SPEED_2500)
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
else
@@ -1958,6 +1979,14 @@ static int qca808x_cable_test_start(struct phy_device *phydev)
phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060);
phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060);
+ if (phydev_id_compare(phydev, QCA8084_PHY_ID)) {
+ /* Adjust the positive and negative pulse thereshold of CDT */
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8075, 0xa060);
+
+ /* Disable the near echo bypass */
+ phy_modify_mmd(phydev, MDIO_MMD_PCS, 0x807f, BIT(15), 0);
+ }
+
return 0;
}
@@ -2227,6 +2256,25 @@ static struct phy_driver at803x_driver[] = {
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
.link_change_notify = qca808x_link_change_notify,
+}, {
+ /* Qualcomm QCA8084 */
+ PHY_ID_MATCH_MODEL(QCA8084_PHY_ID),
+ .name = "Qualcomm QCA8084",
+ .flags = PHY_POLL_CABLE_TEST,
+ .config_intr = at803x_config_intr,
+ .handle_interrupt = at803x_handle_interrupt,
+ .get_tunable = at803x_get_tunable,
+ .set_tunable = at803x_set_tunable,
+ .set_wol = at803x_set_wol,
+ .get_wol = at803x_get_wol,
+ .get_features = qca808x_get_features,
+ .config_aneg = at803x_config_aneg,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_status = qca808x_read_status,
+ .soft_reset = qca808x_soft_reset,
+ .cable_test_start = qca808x_cable_test_start,
+ .cable_test_get_status = qca808x_cable_test_get_status,
}, };
module_phy_driver(at803x_driver);
@@ -2242,6 +2290,7 @@ static struct mdio_device_id __maybe_unused atheros_tbl[] = {
{ PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
{ PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) },
{ PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) },
+ { PHY_ID_MATCH_MODEL(QCA8084_PHY_ID) },
{ }
};
--
2.42.0
Configure MSE detect threshold and ADC clock edge invert.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 143f0d2e36a6..ba5d069ad351 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -280,6 +280,15 @@
#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072
#define QCA8081_PHY_FIFO_RSTN BIT(11)
+/* QCA8084 ADC clock edge */
+#define QCA8084_ADC_CLK_SEL 0x8b80
+#define QCA8084_ADC_CLK_SEL_ACLK GENMASK(7, 4)
+#define QCA8084_ADC_CLK_SEL_ACLK_FALL 0xf
+#define QCA8084_ADC_CLK_SEL_ACLK_RISE 0x0
+
+#define QCA8084_MSE_THRESHOLD 0x800a
+#define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -2085,6 +2094,26 @@ static void qca808x_link_change_notify(struct phy_device *phydev)
QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0);
}
+static int qca8084_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Invert ADC clock edge */
+ ret = at803x_debug_reg_mask(phydev, QCA8084_ADC_CLK_SEL,
+ QCA8084_ADC_CLK_SEL_ACLK,
+ FIELD_PREP(QCA8084_ADC_CLK_SEL_ACLK,
+ QCA8084_ADC_CLK_SEL_ACLK_FALL));
+ if (ret < 0)
+ return ret;
+
+ /* Adjust MSE threshold value to avoid link issue with
+ * some link partner.
+ */
+ return phy_write_mmd(phydev, MDIO_MMD_PMAPMD,
+ QCA8084_MSE_THRESHOLD,
+ QCA8084_MSE_THRESHOLD_2P5G_VAL);
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -2281,6 +2310,7 @@ static struct phy_driver at803x_driver[] = {
.soft_reset = qca808x_soft_reset,
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
+ .config_init = qca8084_config_init,
}, };
module_phy_driver(at803x_driver);
--
2.42.0
When the link is changed, qca8084 needs to do the fifo reset and
adjust the IPG level for the qusgmii link speed 1000M.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 41 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index ba5d069ad351..b6b41b1a4352 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -289,6 +289,13 @@
#define QCA8084_MSE_THRESHOLD 0x800a
#define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6
+#define QCA8084_FIFO_CONTROL 0x19
+#define QCA8084_FIFO_MAC_2_PHY BIT(1)
+#define QCA8084_FIFO_PHY_2_MAC BIT(0)
+
+#define QCA8084_MMD7_IPG_OP 0x901d
+#define QCA8084_IPG_10_TO_11_EN BIT(0)
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -2114,6 +2121,39 @@ static int qca8084_config_init(struct phy_device *phydev)
QCA8084_MSE_THRESHOLD_2P5G_VAL);
}
+static void qca8084_link_change_notify(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL,
+ QCA8084_FIFO_MAC_2_PHY | QCA8084_FIFO_PHY_2_MAC,
+ 0);
+ if (ret)
+ return;
+
+ /* If the PHY works on PHY_INTERFACE_MODE_10G_QXGMII mode, the fifo
+ * needs to be kept as reset state in link down status.
+ */
+ if (phydev->interface != PHY_INTERFACE_MODE_10G_QXGMII ||
+ phydev->link) {
+ msleep(50);
+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL,
+ QCA8084_FIFO_MAC_2_PHY |
+ QCA8084_FIFO_PHY_2_MAC,
+ QCA8084_FIFO_MAC_2_PHY |
+ QCA8084_FIFO_PHY_2_MAC);
+ if (ret)
+ return;
+ }
+
+ /* Enable IPG 10 to 11 tuning on link speed 1000M of QUSGMII mode. */
+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII)
+ phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP,
+ QCA8084_IPG_10_TO_11_EN,
+ phydev->speed == SPEED_1000 ?
+ QCA8084_IPG_10_TO_11_EN : 0);
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -2311,6 +2351,7 @@ static struct phy_driver at803x_driver[] = {
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
.config_init = qca8084_config_init,
+ .link_change_notify = qca8084_link_change_notify,
}, };
module_phy_driver(at803x_driver);
--
2.42.0
From: Vladimir Oltean <[email protected]>
Add the new interface mode 10g-qxgmii, which is similar to
usxgmii but extend to 4 channels to support maximum of 4
ports with the link speed 10M/100M/1G/2.5G.
Signed-off-by: Vladimir Oltean <[email protected]>
Signed-off-by: Luo Jie <[email protected]>
Acked-by: Conor Dooley <[email protected]>
---
Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/net/ethernet-controller.yaml b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
index d14d123ad7a0..0ef6103c5fd8 100644
--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
@@ -104,6 +104,7 @@ properties:
- usxgmii
- 10gbase-r
- 25gbase-r
+ - 10g-qxgmii
phy-mode:
$ref: "#/properties/phy-connection-type"
--
2.42.0
For qca8084 chip, there are GCC, TLMM and security control
modules besides the PHY, these moudles are accessed with 32
bits value, which has the special MDIO sequences to read or
write this 32bit register.
There are initial configurations configured to make qca8084 PHY
probeable, and the MDIO address of qca8084 can be programmed for
the PHY device and PCS device.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 86 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index c186ef8e798f..016e40e32982 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -296,6 +296,13 @@
#define QCA8084_MMD7_IPG_OP 0x901d
#define QCA8084_IPG_10_TO_11_EN BIT(0)
+/* QCA8084 includes secure control module, which supports customizing the
+ * MDIO address of PHY device and PCS device, the register of secure control
+ * is accessed by MDIO bus with the special MDIO sequences.
+ */
+#define QCA8084_HIGH_ADDR_PREFIX 0x18
+#define QCA8084_LOW_ADDR_PREFIX 0x10
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -408,6 +415,85 @@ static int at803x_read_page(struct phy_device *phydev)
return AT803X_PAGE_FIBER;
}
+static void qca8084_split_addr(u32 regaddr, u16 *r1, u16 *r2,
+ u16 *page, u16 *sw_addr)
+{
+ *r1 = regaddr & 0x1c;
+
+ regaddr >>= 5;
+ *r2 = regaddr & 0x7;
+
+ regaddr >>= 3;
+ *page = regaddr & 0xffff;
+
+ regaddr >>= 16;
+ *sw_addr = regaddr & 0xff;
+}
+
+static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page)
+{
+ return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5),
+ sw_addr & 0x1f, page);
+}
+
+static int __qca8084_mii_read(struct mii_bus *bus, u16 addr, u16 reg, u32 *val)
+{
+ int ret, data;
+
+ ret = __mdiobus_read(bus, addr, reg);
+ if (ret >= 0) {
+ data = ret;
+
+ ret = __mdiobus_read(bus, addr, reg | BIT(1));
+ if (ret >= 0)
+ *val = data | ret << 16;
+ }
+
+ return ret < 0 ? ret : 0;
+}
+
+static int __qca8084_mii_write(struct mii_bus *bus, u16 addr, u16 reg, u32 val)
+{
+ int ret;
+
+ ret = __mdiobus_write(bus, addr, reg, lower_16_bits(val));
+ if (!ret)
+ ret = __mdiobus_write(bus, addr, reg | BIT(1), upper_16_bits(val));
+
+ return ret;
+}
+
+static int qca8084_mii_modify(struct phy_device *phydev, u32 regaddr,
+ u32 clear, u32 set)
+{
+ struct mii_bus *bus;
+ u16 reg, addr, page, sw_addr;
+ u32 val;
+ int ret;
+
+ bus = phydev->mdio.bus;
+ mutex_lock(&bus->mdio_lock);
+
+ qca8084_split_addr(regaddr, ®, &addr, &page, &sw_addr);
+ ret = __qca8084_set_page(bus, sw_addr, page);
+ if (ret < 0)
+ goto qca8084_mii_modify_exit;
+
+ ret = __qca8084_mii_read(bus, QCA8084_LOW_ADDR_PREFIX | addr,
+ reg, &val);
+ if (ret < 0)
+ goto qca8084_mii_modify_exit;
+
+ val &= ~clear;
+ val |= set;
+ ret = __qca8084_mii_write(bus, QCA8084_LOW_ADDR_PREFIX | addr,
+ reg, val);
+
+qca8084_mii_modify_exit:
+ mutex_unlock(&bus->mdio_lock);
+ return ret;
+};
+
static int at803x_enable_rx_delay(struct phy_device *phydev)
{
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0,
--
2.42.0
When qca808x works on the interface mode sgmii or
2500base-x, the interface mode can be switched according
to the PHY link speed.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index b6b41b1a4352..c186ef8e798f 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -2101,10 +2101,22 @@ static void qca808x_link_change_notify(struct phy_device *phydev)
QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0);
}
+static void qca808x_fill_possible_interfaces(struct phy_device *phydev)
+{
+ unsigned long *possible = phydev->possible_interfaces;
+
+ if (phydev->interface != PHY_INTERFACE_MODE_10G_QXGMII) {
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible);
+ __set_bit(PHY_INTERFACE_MODE_SGMII, possible);
+ }
+}
+
static int qca8084_config_init(struct phy_device *phydev)
{
int ret;
+ qca808x_fill_possible_interfaces(phydev);
+
/* Invert ADC clock edge */
ret = at803x_debug_reg_mask(phydev, QCA8084_ADC_CLK_SEL,
QCA8084_ADC_CLK_SEL_ACLK,
--
2.42.0
Program the MDIO address of qca8084 PHY and PCS device
in the PHY probe function.
The MDIO address of qca8084 device is configured according
to the property "qcom,phy-addr-fixup" of phy node, which
defines the MDIO address for 4 PHYs and 3 PCSes, each MDIO
address occupies 5 bits in the config register.
The MDIO address of qca8084 should be configured correctly
before doing the clock initialization in the PHY probe function,
so the property "reg" can't be used to configure the MDIO address
of phy device one by one, the clock initialization will be configured
with all 4 PHY devices in one PHY probe function.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 61 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 016e40e32982..a00c5950683c 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -303,6 +303,18 @@
#define QCA8084_HIGH_ADDR_PREFIX 0x18
#define QCA8084_LOW_ADDR_PREFIX 0x10
+#define QCA8084_PCS_CFG 0xc90f014
+#define QCA8084_PCS_ADDR0_MASK GENMASK(4, 0)
+#define QCA8084_PCS_ADDR1_MASK GENMASK(9, 5)
+#define QCA8084_PCS_ADDR2_MASK GENMASK(14, 10)
+
+#define QCA8084_EPHY_CFG 0xc90f018
+#define QCA8084_EPHY_ADDR0_MASK GENMASK(4, 0)
+#define QCA8084_EPHY_ADDR1_MASK GENMASK(9, 5)
+#define QCA8084_EPHY_ADDR2_MASK GENMASK(14, 10)
+#define QCA8084_EPHY_ADDR3_MASK GENMASK(19, 15)
+#define QCA8084_EPHY_LDO_EN GENMASK(21, 20)
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -955,6 +967,51 @@ static int at803x_parse_dt(struct phy_device *phydev)
return 0;
}
+static int qca8084_parse_and_set_phyaddr(struct phy_device *phydev)
+{
+ struct device_node *node;
+ u32 addr[7];
+ int ret;
+
+ node = phydev->mdio.dev.of_node;
+
+ /* The property "qcom,phy-addr-fixup" is only defined in one
+ * PHY device tree node.
+ */
+ ret = of_property_read_u32_array(node, "qcom,phy-addr-fixup",
+ addr, ARRAY_SIZE(addr));
+ if (ret)
+ return ret == -EINVAL ? 0 : ret;
+
+ /* There are 4 PHYs and 3 PCSes on qca8084 chip, each device address
+ * occupies 5 bits of the config register to customize the MDIO address.
+ */
+ ret = qca8084_mii_modify(phydev, QCA8084_EPHY_CFG,
+ QCA8084_EPHY_ADDR0_MASK |
+ QCA8084_EPHY_ADDR1_MASK |
+ QCA8084_EPHY_ADDR2_MASK |
+ QCA8084_EPHY_ADDR3_MASK,
+ FIELD_PREP(QCA8084_EPHY_ADDR0_MASK, addr[0]) |
+ FIELD_PREP(QCA8084_EPHY_ADDR1_MASK, addr[1]) |
+ FIELD_PREP(QCA8084_EPHY_ADDR2_MASK, addr[2]) |
+ FIELD_PREP(QCA8084_EPHY_ADDR3_MASK, addr[3]));
+ if (ret)
+ return ret;
+
+ return qca8084_mii_modify(phydev, QCA8084_PCS_CFG,
+ QCA8084_PCS_ADDR0_MASK |
+ QCA8084_PCS_ADDR1_MASK |
+ QCA8084_PCS_ADDR2_MASK,
+ FIELD_PREP(QCA8084_PCS_ADDR0_MASK, addr[4]) |
+ FIELD_PREP(QCA8084_PCS_ADDR1_MASK, addr[5]) |
+ FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]));
+}
+
+static int qca8084_probe(struct phy_device *phydev)
+{
+ return qca8084_parse_and_set_phyaddr(phydev);
+}
+
static int at803x_probe(struct phy_device *phydev)
{
struct device *dev = &phydev->mdio.dev;
@@ -967,6 +1024,9 @@ static int at803x_probe(struct phy_device *phydev)
phydev->priv = priv;
+ if (phydev_id_compare(phydev, QCA8084_PHY_ID))
+ return qca8084_probe(phydev);
+
ret = at803x_parse_dt(phydev);
if (ret)
return ret;
@@ -2434,6 +2494,7 @@ static struct phy_driver at803x_driver[] = {
PHY_ID_MATCH_MODEL(QCA8084_PHY_ID),
.name = "Qualcomm QCA8084",
.flags = PHY_POLL_CABLE_TEST,
+ .probe = at803x_probe,
.config_intr = at803x_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.get_tunable = at803x_get_tunable,
--
2.42.0
These clock and reset IDs are needed to bring up qca8084,
after the initializations with these clocks and resets,
the PHY function can be accessed correctly such as reading
the capabilities of PHY.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 89 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index a00c5950683c..6a7a7111ff68 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -21,6 +21,8 @@
#include <linux/phylink.h>
#include <linux/sfp.h>
#include <dt-bindings/net/qca-ar803x.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10
#define AT803X_SFC_ASSERT_CRS BIT(11)
@@ -337,6 +339,31 @@ static struct at803x_hw_stat at803x_hw_stats[] = {
{ "eee_wake_errors", 0x16, GENMASK(15, 0), MMD},
};
+enum {
+ SRDS0_SYS_CLK,
+ SRDS1_SYS_CLK,
+ GEPHY0_SYS_CLK,
+ GEPHY1_SYS_CLK,
+ GEPHY2_SYS_CLK,
+ GEPHY3_SYS_CLK,
+ QCA8084_CLK_CNT
+};
+
+enum {
+ SRDS0_SYS_RESET,
+ SRDS1_SYS_RESET,
+ GEPHY0_SYS_RESET,
+ GEPHY1_SYS_RESET,
+ GEPHY2_SYS_RESET,
+ GEPHY3_SYS_RESET,
+ GEPHY0_RESET,
+ GEPHY1_RESET,
+ GEPHY2_RESET,
+ GEPHY3_RESET,
+ GEPHY_DSP_RESET,
+ QCA8084_RESET_CNT,
+};
+
struct at803x_priv {
int flags;
u16 clk_25m_reg;
@@ -348,6 +375,8 @@ struct at803x_priv {
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
u64 stats[ARRAY_SIZE(at803x_hw_stats)];
+ struct clk *clk[QCA8084_CLK_CNT];
+ struct reset_control *reset[QCA8084_RESET_CNT];
};
struct at803x_context {
@@ -359,6 +388,29 @@ struct at803x_context {
u16 led_control;
};
+static const char *const qca8084_clock_name[QCA8084_CLK_CNT] = {
+ "srds0_sys",
+ "srds1_sys",
+ "gephy0_sys",
+ "gephy1_sys",
+ "gephy2_sys",
+ "gephy3_sys",
+};
+
+static const char *const qca8084_reset_name[QCA8084_RESET_CNT] = {
+ "srds0_sys",
+ "srds1_sys",
+ "gephy0_sys",
+ "gephy1_sys",
+ "gephy2_sys",
+ "gephy3_sys",
+ "gephy0_soft",
+ "gephy1_soft",
+ "gephy2_soft",
+ "gephy3_soft",
+ "gephy_dsp",
+};
+
static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data)
{
int ret;
@@ -1007,8 +1059,45 @@ static int qca8084_parse_and_set_phyaddr(struct phy_device *phydev)
FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]));
}
+static int qca8084_parse_dt(struct phy_device *phydev)
+{
+ struct at803x_priv *priv;
+ int i;
+
+ priv = phydev->priv;
+ for (i = 0; i < QCA8084_CLK_CNT; i++) {
+ priv->clk[i] = devm_clk_get_optional(&phydev->mdio.dev,
+ qca8084_clock_name[i]);
+ if (IS_ERR(priv->clk[i])) {
+ phydev_err(phydev, "failed to get the clock ID %s!\n",
+ qca8084_clock_name[i]);
+
+ return PTR_ERR(priv->clk[i]);
+ }
+ }
+
+ for (i = 0; i < QCA8084_RESET_CNT; i++) {
+ priv->reset[i] = devm_reset_control_get_optional_exclusive(&phydev->mdio.dev,
+ qca8084_reset_name[i]);
+ if (IS_ERR(priv->reset[i])) {
+ phydev_err(phydev, "failed to get the reset ID %s!\n",
+ qca8084_reset_name[i]);
+
+ return PTR_ERR(priv->reset[i]);
+ }
+ }
+
+ return 0;
+}
+
static int qca8084_probe(struct phy_device *phydev)
{
+ int ret;
+
+ ret = qca8084_parse_dt(phydev);
+ if (ret)
+ return ret;
+
return qca8084_parse_and_set_phyaddr(phydev);
}
--
2.42.0
There are four kind of work modes supported by qca8084.
1. Quad PHYs work on 10g-qxgmii.
2. PHY1, PHY2, PHY3 wors on 10g-qxgmii, PHY4 works on sgmii.
3. Quad PHYs connected with internal MACs by GMII, which works
on switch mode.
4. PHY1, PHY2, PHY3 connected with internal MACs by GMII, PHY4
works on sgmii.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 53 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 4499d78891d2..6bc80704949a 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -317,6 +317,13 @@
#define QCA8084_EPHY_ADDR3_MASK GENMASK(19, 15)
#define QCA8084_EPHY_LDO_EN GENMASK(21, 20)
+#define QCA8084_WORK_MODE_CFG 0xc90f030
+#define QCA8084_WORK_MODE_MASK GENMASK(5, 0)
+#define QCA8084_WORK_MODE_QXGMII (BIT(5) | GENMASK(3, 0))
+#define QCA8084_WORK_MODE_QXGMII_PORT4_SGMII (BIT(5) | GENMASK(2, 0))
+#define QCA8084_WORK_MODE_SWITCH BIT(4)
+#define QCA8084_WORK_MODE_SWITCH_PORT4_SGMII BIT(5)
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -1231,6 +1238,46 @@ static int qca8084_common_clock_init(struct phy_device *phydev)
return clk_prepare_enable(priv->clk[MDIO_MASTER_AHB_CLK]);
}
+static int qca8084_parse_and_set_work_mode(struct phy_device *phydev)
+{
+ struct device_node *node;
+ struct at803x_priv *priv;
+ u32 value, work_mode;
+ int ret;
+
+ node = phydev->mdio.dev.of_node;
+ priv = phydev->priv;
+
+ /* The property "qcom,phy-work-mode" is only defined in one
+ * PHY device tree node.
+ */
+ ret = of_property_read_u32(node, "qcom,phy-work-mode", &value);
+ if (ret)
+ return ret == -EINVAL ? 0 : ret;
+
+ switch (value) {
+ case 0:
+ work_mode = QCA8084_WORK_MODE_QXGMII;
+ break;
+ case 1:
+ work_mode = QCA8084_WORK_MODE_QXGMII_PORT4_SGMII;
+ break;
+ case 2:
+ work_mode = QCA8084_WORK_MODE_SWITCH;
+ break;
+ case 3:
+ work_mode = QCA8084_WORK_MODE_SWITCH_PORT4_SGMII;
+ break;
+ default:
+ phydev_err(phydev, "invalid qcom,phy-work-mode %d\n", value);
+ return -EINVAL;
+ }
+
+ return qca8084_mii_modify(phydev, QCA8084_WORK_MODE_CFG,
+ QCA8084_WORK_MODE_MASK,
+ FIELD_PREP(QCA8084_WORK_MODE_MASK, work_mode));
+}
+
static int qca8084_probe(struct phy_device *phydev)
{
int ret;
@@ -1247,7 +1294,11 @@ static int qca8084_probe(struct phy_device *phydev)
if (ret)
return ret;
- return qca8084_common_clock_init(phydev);
+ ret = qca8084_common_clock_init(phydev);
+ if (ret)
+ return ret;
+
+ return qca8084_parse_and_set_work_mode(phydev);
}
static int at803x_probe(struct phy_device *phydev)
--
2.42.0
After initial clock sequence, the clock source 312.5MHZ is
available, the common clocks based on clock source 312.5MHZ
needs to be configured, which includes APB bridge clock tree
with rate 312.5MHZ, AHB clock tree with 104.17MHZ.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 69 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 204f5ca6001c..4499d78891d2 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -340,6 +340,14 @@ static struct at803x_hw_stat at803x_hw_stats[] = {
};
enum {
+ APB_BRIDGE_CLK,
+ AHB_CLK,
+ SEC_CTRL_AHB_CLK,
+ TLMM_CLK,
+ TLMM_AHB_CLK,
+ CNOC_AHB_CLK,
+ MDIO_AHB_CLK,
+ MDIO_MASTER_AHB_CLK,
SRDS0_SYS_CLK,
SRDS1_SYS_CLK,
GEPHY0_SYS_CLK,
@@ -389,6 +397,14 @@ struct at803x_context {
};
static const char *const qca8084_clock_name[QCA8084_CLK_CNT] = {
+ "apb_bridge",
+ "ahb",
+ "sec_ctrl_ahb",
+ "tlmm",
+ "tlmm_ahb",
+ "cnoc_ahb",
+ "mdio_ahb",
+ "mdio_master_ahb",
"srds0_sys",
"srds1_sys",
"gephy0_sys",
@@ -1168,6 +1184,53 @@ static int qca8084_clock_config(struct phy_device *phydev)
return 0;
}
+static int qca8084_common_clock_init(struct phy_device *phydev)
+{
+ struct at803x_priv *priv;
+ int ret = 0;
+
+ priv = phydev->priv;
+ /* Enable APB bridge tree clock */
+ ret = clk_set_rate(priv->clk[APB_BRIDGE_CLK], 312500000);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[APB_BRIDGE_CLK]);
+ if (ret)
+ return ret;
+
+ /* Enable AHB tree clocks */
+ ret = clk_set_rate(priv->clk[AHB_CLK], 104170000);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[AHB_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[SEC_CTRL_AHB_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[TLMM_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[TLMM_AHB_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[CNOC_AHB_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[MDIO_AHB_CLK]);
+ if (ret)
+ return ret;
+
+ return clk_prepare_enable(priv->clk[MDIO_MASTER_AHB_CLK]);
+}
+
static int qca8084_probe(struct phy_device *phydev)
{
int ret;
@@ -1180,7 +1243,11 @@ static int qca8084_probe(struct phy_device *phydev)
if (ret)
return ret;
- return qca8084_clock_config(phydev);
+ ret = qca8084_clock_config(phydev);
+ if (ret)
+ return ret;
+
+ return qca8084_common_clock_init(phydev);
}
static int at803x_probe(struct phy_device *phydev)
--
2.42.0
The following properties are added for qca8084 PHY.
1. add the compatible string "ethernet-phy-id004d.d180" since
the PHY device is not accessible during MDIO bus register.
2. add property "qcom,phy-addr-fixup" for customizing MDIO address.
3. add property "qcom,phy-work-mode" for specifying qca8084 PHY
work mode.
4. add the initial clocks and resets.
Signed-off-by: Luo Jie <[email protected]>
---
.../devicetree/bindings/net/qca,ar803x.yaml | 158 +++++++++++++++++-
1 file changed, 155 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/qca,ar803x.yaml b/Documentation/devicetree/bindings/net/qca,ar803x.yaml
index 3acd09f0da86..febff039a44f 100644
--- a/Documentation/devicetree/bindings/net/qca,ar803x.yaml
+++ b/Documentation/devicetree/bindings/net/qca,ar803x.yaml
@@ -14,9 +14,6 @@ maintainers:
description: |
Bindings for Qualcomm Atheros AR803x PHYs
-allOf:
- - $ref: ethernet-phy.yaml#
-
properties:
qca,clk-out-frequency:
description: Clock output frequency in Hertz.
@@ -85,6 +82,161 @@ properties:
$ref: /schemas/regulator/regulator.yaml
unevaluatedProperties: false
+ qcom,phy-addr-fixup:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ MDIO address for 4 PHY devices and 3 PCS devices
+
+ qcom,phy-work-mode:
+ description: PHY device work mode.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+
+ clocks:
+ items:
+ - description: APB bridge clock
+ - description: AHB clock
+ - description: Security control clock
+ - description: TLMM clock
+ - description: TLMM AHB clock
+ - description: CNOC AHB clock
+ - description: MDIO AHB clock
+ - description: MDIO master AHB clock
+ - description: PCS0 system clock
+ - description: PCS1 system clock
+ - description: EPHY0 system clock
+ - description: EPHY1 system clock
+ - description: EPHY2 system clock
+ - description: EPHY3 system clock
+ description: PHY initial common clock configs
+
+ clock-names:
+ items:
+ - const: apb_bridge
+ - const: ahb
+ - const: sec_ctrl_ahb
+ - const: tlmm
+ - const: tlmm_ahb
+ - const: cnoc_ahb
+ - const: mdio_ahb
+ - const: mdio_master_ahb
+ - const: srds0_sys
+ - const: srds1_sys
+ - const: gephy0_sys
+ - const: gephy1_sys
+ - const: gephy2_sys
+ - const: gephy3_sys
+
+ resets:
+ items:
+ - description: PCS0 system reset
+ - description: PCS1 system reset
+ - description: EPHY0 system reset
+ - description: EPHY1 system reset
+ - description: EPHY2 system reset
+ - description: EPHY3 system reset
+ - description: EPHY0 software reset
+ - description: EPHY1 software reset
+ - description: EPHY2 software reset
+ - description: EPHY3 software reset
+ - description: Ethernet DSP reset
+ description: PHY initial common reset configs
+
+ reset-names:
+ items:
+ - const: srds0_sys
+ - const: srds1_sys
+ - const: gephy0_sys
+ - const: gephy1_sys
+ - const: gephy2_sys
+ - const: gephy3_sys
+ - const: gephy0_soft
+ - const: gephy1_soft
+ - const: gephy2_soft
+ - const: gephy3_soft
+ - const: gephy_dsp
+
+allOf:
+ - $ref: ethernet-phy.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - ethernet-phy-id004d.d180
+ then:
+ properties:
+ clocks:
+ items:
+ - description: APB bridge clock
+ - description: AHB clock
+ - description: Security control clock
+ - description: TLMM clock
+ - description: TLMM AHB clock
+ - description: CNOC AHB clock
+ - description: MDIO AHB clock
+ - description: MDIO master AHB clock
+ - description: PCS0 system clock
+ - description: PCS1 system clock
+ - description: EPHY0 system clock
+ - description: EPHY1 system clock
+ - description: EPHY2 system clock
+ - description: EPHY3 system clock
+ clock-names:
+ items:
+ - const: apb_bridge
+ - const: ahb
+ - const: sec_ctrl_ahb
+ - const: tlmm
+ - const: tlmm_ahb
+ - const: cnoc_ahb
+ - const: mdio_ahb
+ - const: mdio_master_ahb
+ - const: srds0_sys
+ - const: srds1_sys
+ - const: gephy0_sys
+ - const: gephy1_sys
+ - const: gephy2_sys
+ - const: gephy3_sys
+ resets:
+ items:
+ - description: PCS0 system reset
+ - description: PCS1 system reset
+ - description: EPHY0 system reset
+ - description: EPHY1 system reset
+ - description: EPHY2 system reset
+ - description: EPHY3 system reset
+ - description: EPHY0 software reset
+ - description: EPHY1 software reset
+ - description: EPHY2 software reset
+ - description: EPHY3 software reset
+ - description: Ethernet DSP reset
+ reset-names:
+ items:
+ - const: srds0_sys
+ - const: srds1_sys
+ - const: gephy0_sys
+ - const: gephy1_sys
+ - const: gephy2_sys
+ - const: gephy3_sys
+ - const: gephy0_soft
+ - const: gephy1_soft
+ - const: gephy2_soft
+ - const: gephy3_soft
+ - const: gephy_dsp
+ required:
+ - qcom,phy-addr-fixup
+ - qcom,phy-work-mode
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ else:
+ properties:
+ qcom,phy-addr-fixup: false
+ qcom,phy-work-mode: false
+
unevaluatedProperties: false
examples:
--
2.42.0
After GPIO reset, these Ethernet clock sequence needs to be
configured before reading the features of PHY, the Ethernet
system clock works on 25MHZ.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 84 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 83 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 6a7a7111ff68..204f5ca6001c 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1090,6 +1090,84 @@ static int qca8084_parse_dt(struct phy_device *phydev)
return 0;
}
+static int qca8084_clock_config(struct phy_device *phydev)
+{
+ struct at803x_priv *priv;
+ int ret = 0;
+
+ /* The ethernet clock IDs are only defined in one PHY device
+ * tree node, and these ethernet clocks only needs to be configured
+ * one time, which work on the clock rate 25MHZ.
+ */
+ priv = phydev->priv;
+ if (!priv->clk[SRDS0_SYS_CLK])
+ return 0;
+
+ ret = clk_set_rate(priv->clk[SRDS0_SYS_CLK], 25000000);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[SRDS0_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[SRDS1_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ /* Reset PCS system clocks */
+ reset_control_assert(priv->reset[SRDS0_SYS_RESET]);
+ reset_control_assert(priv->reset[SRDS1_SYS_RESET]);
+ fsleep(20000);
+
+ reset_control_deassert(priv->reset[SRDS0_SYS_RESET]);
+ reset_control_deassert(priv->reset[SRDS1_SYS_RESET]);
+
+ ret = clk_prepare_enable(priv->clk[GEPHY0_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[GEPHY1_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[GEPHY2_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk[GEPHY3_SYS_CLK]);
+ if (ret)
+ return ret;
+
+ /* Reset ethernet system clocks */
+ reset_control_assert(priv->reset[GEPHY0_SYS_RESET]);
+ reset_control_assert(priv->reset[GEPHY1_SYS_RESET]);
+ reset_control_assert(priv->reset[GEPHY2_SYS_RESET]);
+ reset_control_assert(priv->reset[GEPHY3_SYS_RESET]);
+ fsleep(20000);
+
+ reset_control_deassert(priv->reset[GEPHY0_SYS_RESET]);
+ reset_control_deassert(priv->reset[GEPHY1_SYS_RESET]);
+ reset_control_deassert(priv->reset[GEPHY2_SYS_RESET]);
+ reset_control_deassert(priv->reset[GEPHY3_SYS_RESET]);
+
+ /* Release ethernet DSP reset */
+ reset_control_deassert(priv->reset[GEPHY0_RESET]);
+ reset_control_deassert(priv->reset[GEPHY1_RESET]);
+ reset_control_deassert(priv->reset[GEPHY2_RESET]);
+ reset_control_deassert(priv->reset[GEPHY3_RESET]);
+ reset_control_deassert(priv->reset[GEPHY_DSP_RESET]);
+
+ /* Enable efuse loading into analog circuit */
+ ret = qca8084_mii_modify(phydev, QCA8084_EPHY_CFG,
+ QCA8084_EPHY_LDO_EN, 0);
+ if (ret)
+ return ret;
+
+ fsleep(10000);
+ return 0;
+}
+
static int qca8084_probe(struct phy_device *phydev)
{
int ret;
@@ -1098,7 +1176,11 @@ static int qca8084_probe(struct phy_device *phydev)
if (ret)
return ret;
- return qca8084_parse_and_set_phyaddr(phydev);
+ ret = qca8084_parse_and_set_phyaddr(phydev);
+ if (ret)
+ return ret;
+
+ return qca8084_clock_config(phydev);
}
static int at803x_probe(struct phy_device *phydev)
--
2.42.0
On Thu, Dec 14, 2023 at 05:48:01PM +0800, Luo Jie wrote:
> From: Vladimir Oltean <[email protected]>
>
> Add the new interface mode 10g-qxgmii, which is similar to
> usxgmii but extend to 4 channels to support maximum of 4
> ports with the link speed 10M/100M/1G/2.5G.
>
> Signed-off-by: Vladimir Oltean <[email protected]>
> Signed-off-by: Luo Jie <[email protected]>
> Acked-by: Conor Dooley <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
On Thu, Dec 14, 2023 at 05:48:02PM +0800, Luo Jie wrote:
> Add qca8084 PHY support, which is four-port PHY with maximum
> link capability 2.5G, the features of each port is almost same
> as QCA8081 and slave seed config is not needed.
>
> Three kind of interface modes supported by qca8084.
> PHY_INTERFACE_MODE_10G_QXGMII, PHY_INTERFACE_MODE_2500BASEX and
> PHY_INTERFACE_MODE_SGMII.
>
> The PCS(serdes) and clock are also needed to be configured to
> bringup qca8084 PHY, which will be added in the pcs driver.
>
> The additional CDT configurations used for qca8084.
>
> Signed-off-by: Luo Jie <[email protected]>
> ---
> drivers/net/phy/at803x.c | 49 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 49 insertions(+)
>
> diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
> index 37fb033e1c29..8dfdf2ff56a5 100644
> --- a/drivers/net/phy/at803x.c
> +++ b/drivers/net/phy/at803x.c
> @@ -176,6 +176,7 @@
> #define AT8030_PHY_ID_MASK 0xffffffef
>
> #define QCA8081_PHY_ID 0x004dd101
> +#define QCA8084_PHY_ID 0x004dd180
>
> #define QCA8327_A_PHY_ID 0x004dd033
> #define QCA8327_B_PHY_ID 0x004dd034
> @@ -1760,6 +1761,9 @@ static bool qca808x_is_prefer_master(struct phy_device *phydev)
>
> static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev)
> {
> + if (phydev_id_compare(phydev, QCA8084_PHY_ID))
> + return false;
> +
> return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported);
> }
It looks like these patches need rebasing on net-next/main. It appears
you are missing Christians patches.
Andrew
---
pw-bot: cr
On 12/14/2023 7:01 PM, Andrew Lunn wrote:
> On Thu, Dec 14, 2023 at 05:48:02PM +0800, Luo Jie wrote:
>> Add qca8084 PHY support, which is four-port PHY with maximum
>> link capability 2.5G, the features of each port is almost same
>> as QCA8081 and slave seed config is not needed.
>>
>> Three kind of interface modes supported by qca8084.
>> PHY_INTERFACE_MODE_10G_QXGMII, PHY_INTERFACE_MODE_2500BASEX and
>> PHY_INTERFACE_MODE_SGMII.
>>
>> The PCS(serdes) and clock are also needed to be configured to
>> bringup qca8084 PHY, which will be added in the pcs driver.
>>
>> The additional CDT configurations used for qca8084.
>>
>> Signed-off-by: Luo Jie <[email protected]>
>> ---
>> drivers/net/phy/at803x.c | 49 ++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 49 insertions(+)
>>
>> diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
>> index 37fb033e1c29..8dfdf2ff56a5 100644
>> --- a/drivers/net/phy/at803x.c
>> +++ b/drivers/net/phy/at803x.c
>> @@ -176,6 +176,7 @@
>> #define AT8030_PHY_ID_MASK 0xffffffef
>>
>> #define QCA8081_PHY_ID 0x004dd101
>> +#define QCA8084_PHY_ID 0x004dd180
>>
>> #define QCA8327_A_PHY_ID 0x004dd033
>> #define QCA8327_B_PHY_ID 0x004dd034
>> @@ -1760,6 +1761,9 @@ static bool qca808x_is_prefer_master(struct phy_device *phydev)
>>
>> static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev)
>> {
>> + if (phydev_id_compare(phydev, QCA8084_PHY_ID))
>> + return false;
>> +
>> return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported);
>> }
>
>
> It looks like these patches need rebasing on net-next/main. It appears
> you are missing Christians patches.
>
>
> Andrew
>
> ---
> pw-bot: cr
Oh, Yes, i will update the patch set based on the latest code, thanks.
On 14/12/2023 10:48, Luo Jie wrote:
> The following properties are added for qca8084 PHY.
>
> 1. add the compatible string "ethernet-phy-id004d.d180" since
> the PHY device is not accessible during MDIO bus register.
> 2. add property "qcom,phy-addr-fixup" for customizing MDIO address.
Why? Commit msg must explain why, not "what".
> 3. add property "qcom,phy-work-mode" for specifying qca8084 PHY
> work mode.
Why?
> 4. add the initial clocks and resets.
Why only initial, not final?
>
> Signed-off-by: Luo Jie <[email protected]>
> ---
> .../devicetree/bindings/net/qca,ar803x.yaml | 158 +++++++++++++++++-
> 1 file changed, 155 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/qca,ar803x.yaml b/Documentation/devicetree/bindings/net/qca,ar803x.yaml
> index 3acd09f0da86..febff039a44f 100644
> --- a/Documentation/devicetree/bindings/net/qca,ar803x.yaml
> +++ b/Documentation/devicetree/bindings/net/qca,ar803x.yaml
> @@ -14,9 +14,6 @@ maintainers:
> description: |
> Bindings for Qualcomm Atheros AR803x PHYs
>
> -allOf:
> - - $ref: ethernet-phy.yaml#
> -
> properties:
> qca,clk-out-frequency:
> description: Clock output frequency in Hertz.
> @@ -85,6 +82,161 @@ properties:
> $ref: /schemas/regulator/regulator.yaml
> unevaluatedProperties: false
>
> + qcom,phy-addr-fixup:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
Why no constraints?
> + description:
> + MDIO address for 4 PHY devices and 3 PCS devices
Why do you need to change MMIO address?
> +
> + qcom,phy-work-mode:
> + description: PHY device work mode.
Your description copies property name. Tell us something we don't
know... like the meaning of the vcalues.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + enum: [0, 1, 2, 3]
> +
> + clocks:
> + items:
> + - description: APB bridge clock
> + - description: AHB clock
> + - description: Security control clock
> + - description: TLMM clock
> + - description: TLMM AHB clock
> + - description: CNOC AHB clock
> + - description: MDIO AHB clock
> + - description: MDIO master AHB clock
> + - description: PCS0 system clock
> + - description: PCS1 system clock
> + - description: EPHY0 system clock
> + - description: EPHY1 system clock
> + - description: EPHY2 system clock
> + - description: EPHY3 system clock
> + description: PHY initial common clock configs
> +
> + clock-names:
> + items:
> + - const: apb_bridge
> + - const: ahb
> + - const: sec_ctrl_ahb
> + - const: tlmm
> + - const: tlmm_ahb
> + - const: cnoc_ahb
> + - const: mdio_ahb
> + - const: mdio_master_ahb
> + - const: srds0_sys
> + - const: srds1_sys
> + - const: gephy0_sys
> + - const: gephy1_sys
> + - const: gephy2_sys
> + - const: gephy3_sys
> +
> + resets:
> + items:
> + - description: PCS0 system reset
> + - description: PCS1 system reset
> + - description: EPHY0 system reset
> + - description: EPHY1 system reset
> + - description: EPHY2 system reset
> + - description: EPHY3 system reset
> + - description: EPHY0 software reset
> + - description: EPHY1 software reset
> + - description: EPHY2 software reset
> + - description: EPHY3 software reset
> + - description: Ethernet DSP reset
> + description: PHY initial common reset configs
> +
> + reset-names:
> + items:
> + - const: srds0_sys
> + - const: srds1_sys
> + - const: gephy0_sys
> + - const: gephy1_sys
> + - const: gephy2_sys
> + - const: gephy3_sys
> + - const: gephy0_soft
> + - const: gephy1_soft
> + - const: gephy2_soft
> + - const: gephy3_soft
> + - const: gephy_dsp
> +
> +allOf:
> + - $ref: ethernet-phy.yaml#
> +
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - ethernet-phy-id004d.d180
> + then:
> + properties:
> + clocks:
> + items:
> + - description: APB bridge clock
> + - description: AHB clock
> + - description: Security control clock
> + - description: TLMM clock
> + - description: TLMM AHB clock
> + - description: CNOC AHB clock
> + - description: MDIO AHB clock
> + - description: MDIO master AHB clock
> + - description: PCS0 system clock
> + - description: PCS1 system clock
> + - description: EPHY0 system clock
> + - description: EPHY1 system clock
> + - description: EPHY2 system clock
> + - description: EPHY3 system clock
> + clock-names:
> + items:
> + - const: apb_bridge
> + - const: ahb
> + - const: sec_ctrl_ahb
> + - const: tlmm
> + - const: tlmm_ahb
> + - const: cnoc_ahb
> + - const: mdio_ahb
> + - const: mdio_master_ahb
> + - const: srds0_sys
> + - const: srds1_sys
> + - const: gephy0_sys
> + - const: gephy1_sys
> + - const: gephy2_sys
> + - const: gephy3_sys
?!? Why do you duplicate properties?
> + resets:
> + items:
> + - description: PCS0 system reset
> + - description: PCS1 system reset
> + - description: EPHY0 system reset
> + - description: EPHY1 system reset
> + - description: EPHY2 system reset
> + - description: EPHY3 system reset
> + - description: EPHY0 software reset
> + - description: EPHY1 software reset
> + - description: EPHY2 software reset
> + - description: EPHY3 software reset
> + - description: Ethernet DSP reset
> + reset-names:
> + items:
> + - const: srds0_sys
> + - const: srds1_sys
> + - const: gephy0_sys
> + - const: gephy1_sys
> + - const: gephy2_sys
> + - const: gephy3_sys
> + - const: gephy0_soft
> + - const: gephy1_soft
> + - const: gephy2_soft
> + - const: gephy3_soft
> + - const: gephy_dsp
> + required:
> + - qcom,phy-addr-fixup
> + - qcom,phy-work-mode
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + else:
> + properties:
> + qcom,phy-addr-fixup: false
> + qcom,phy-work-mode: false
And what about clcoks and resets for other variants? Your patch now
defined them for all variants without any explanation in commit msg.
> +
> unevaluatedProperties: false
>
> examples:
Best regards,
Krzysztof