@@ -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,52 @@ static struct at803x_hw_stat qca83xx_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,
+};
+
+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,
+};
+
+static const char *const qca8084_clock_name[] = {
+ "srds0_sys",
+ "srds1_sys",
+ "gephy0_sys",
+ "gephy1_sys",
+ "gephy2_sys",
+ "gephy3_sys",
+};
+
+static const char *const qca8084_reset_name[] = {
+ "srds0_sys",
+ "srds1_sys",
+ "gephy0_sys",
+ "gephy1_sys",
+ "gephy2_sys",
+ "gephy3_sys",
+ "gephy0_soft",
+ "gephy1_soft",
+ "gephy2_soft",
+ "gephy3_soft",
+ "gephy_dsp",
+};
+
struct at803x_priv {
int flags;
u16 clk_25m_reg;
@@ -348,6 +396,8 @@ struct at803x_priv {
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
u64 stats[ARRAY_SIZE(qca83xx_hw_stats)];
+ struct clk *clk[ARRAY_SIZE(qca8084_clock_name)];
+ struct reset_control *reset[ARRAY_SIZE(qca8084_reset_name)];
};
struct at803x_context {
@@ -816,8 +866,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 < ARRAY_SIZE(qca8084_clock_name); 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 < ARRAY_SIZE(qca8084_reset_name); 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);
}