All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
To: u-boot@lists.denx.de
Cc: Peter.Hoyes@arm.com, aford173@gmail.com, alice.guo@nxp.com,
	andre.przywara@arm.com, andrey.zhizhikin@leica-geosystems.com,
	ariel.dalessandro@collabora.com, bmeng.cn@gmail.com,
	christian.gmeiner@gmail.com, christianshewitt@gmail.com,
	festevam@gmail.com, iliev@ronetix.at, jagan@amarulasolutions.com,
	jh80.chung@samsung.com, joe.hershberger@ni.com,
	kettenis@openbsd.org, kever.yang@rock-chips.com,
	kuldeep.singh@nxp.com, marcel.ziswiler@toradex.com,
	marex@denx.de, michael@amarulasolutions.com,
	michal.simek@xilinx.com, oliver.graute@kococonnector.com,
	pali@kernel.org, paul.liu@linaro.org, pbrobinson@gmail.com,
	peng.fan@nxp.com, philipp.tomsich@vrull.eu,
	priyanka.jain@nxp.com, radu-nicolae.pirea@oss.nxp.com,
	rath@ibv-augsburg.net, rfried.dev@gmail.com, samuel@sholland.org,
	sbabic@denx.de, simon.k.r.goldschmidt@gmail.com,
	sjg@chromium.org, stephan@gerhold.net, tharvey@gateworks.com,
	tien.fong.chee@intel.com, uboot-imx@nxp.com,
	vladimir.oltean@nxp.com, wd@denx.de, xypron.glpk@gmx.de,
	ye.li@nxp.com
Subject: [PATCH v5 6/7] net: phy: nxp-tja11xx: Add NXP TJA11xx PHY driver
Date: Tue, 12 Apr 2022 10:31:37 -0300	[thread overview]
Message-ID: <20220412133138.110815-7-ariel.dalessandro@collabora.com> (raw)
In-Reply-To: <20220412133138.110815-1-ariel.dalessandro@collabora.com>

From: Michael Trimarchi <michael@amarulasolutions.com>

Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
BroadRReach 100BaseT1 PHYs used in automotive.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
---
 drivers/net/phy/Kconfig       |   5 +
 drivers/net/phy/Makefile      |   1 +
 drivers/net/phy/nxp-tja11xx.c | 277 ++++++++++++++++++++++++++++++++++
 drivers/net/phy/phy.c         |   3 +
 include/phy.h                 |   1 +
 5 files changed, 287 insertions(+)
 create mode 100644 drivers/net/phy/nxp-tja11xx.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 014a4de223e..d40ce92cadc 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -215,6 +215,11 @@ config PHY_NXP_C45_TJA11XX
 	  Enable support for NXP C45 TJA11XX PHYs.
 	  Currently supports only the TJA1103 PHY.
 
+config PHY_NXP_TJA11XX
+	bool "NXP TJA11XX Ethernet PHYs support"
+	help
+	  Currently supports the NXP TJA1100 and TJA1101 PHY.
+
 config PHY_REALTEK
 	bool "Realtek Ethernet PHYs support"
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index b28440bc4e5..67ca4d3a69f 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
 obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
 obj-$(CONFIG_PHY_NATSEMI) += natsemi.o
 obj-$(CONFIG_PHY_NXP_C45_TJA11XX) += nxp-c45-tja11xx.o
+obj-$(CONFIG_PHY_NXP_TJA11XX) += nxp-tja11xx.o
 obj-$(CONFIG_PHY_REALTEK) += realtek.o
 obj-$(CONFIG_PHY_SMSC) += smsc.o
 obj-$(CONFIG_PHY_TERANETICS) += teranetics.o
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
new file mode 100644
index 00000000000..30dec5e605b
--- /dev/null
+++ b/drivers/net/phy/nxp-tja11xx.c
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: GPL-2.0
+/* NXP TJA1100 BroadRReach PHY driver
+ *
+ * Copyright (C) 2022 Michael Trimarchi <michael@amarulasolutions.com>
+ * Copyright (C) 2022 Ariel D'Alessandro <ariel.dalessandro@collabora.com>
+ * Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ */
+
+#include <common.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <phy.h>
+
+#define PHY_ID_MASK			0xfffffff0
+#define PHY_ID_TJA1100			0x0180dc40
+#define PHY_ID_TJA1101			0x0180dd00
+
+#define MII_ECTRL			17
+#define MII_ECTRL_LINK_CONTROL		BIT(15)
+#define MII_ECTRL_POWER_MODE_MASK	GENMASK(14, 11)
+#define MII_ECTRL_POWER_MODE_NO_CHANGE	(0x0 << 11)
+#define MII_ECTRL_POWER_MODE_NORMAL	(0x3 << 11)
+#define MII_ECTRL_POWER_MODE_STANDBY	(0xc << 11)
+#define MII_ECTRL_CABLE_TEST		BIT(5)
+#define MII_ECTRL_CONFIG_EN		BIT(2)
+#define MII_ECTRL_WAKE_REQUEST		BIT(0)
+
+#define MII_CFG1			18
+#define MII_CFG1_MASTER_SLAVE		BIT(15)
+#define MII_CFG1_AUTO_OP		BIT(14)
+#define MII_CFG1_SLEEP_CONFIRM		BIT(6)
+#define MII_CFG1_LED_MODE_MASK		GENMASK(5, 4)
+#define MII_CFG1_LED_MODE_LINKUP	0
+#define MII_CFG1_LED_ENABLE		BIT(3)
+
+#define MII_CFG2			19
+#define MII_CFG2_SLEEP_REQUEST_TO	GENMASK(1, 0)
+#define MII_CFG2_SLEEP_REQUEST_TO_16MS	0x3
+
+#define MII_INTSRC			21
+#define MII_INTSRC_LINK_FAIL		BIT(10)
+#define MII_INTSRC_LINK_UP		BIT(9)
+#define MII_INTSRC_MASK			(MII_INTSRC_LINK_FAIL | \
+					 MII_INTSRC_LINK_UP)
+#define MII_INTSRC_UV_ERR		BIT(3)
+#define MII_INTSRC_TEMP_ERR		BIT(1)
+
+#define MII_INTEN			22
+#define MII_INTEN_LINK_FAIL		BIT(10)
+#define MII_INTEN_LINK_UP		BIT(9)
+#define MII_INTEN_UV_ERR		BIT(3)
+#define MII_INTEN_TEMP_ERR		BIT(1)
+
+#define MII_COMMSTAT			23
+#define MII_COMMSTAT_LINK_UP		BIT(15)
+#define MII_COMMSTAT_SQI_STATE		GENMASK(7, 5)
+#define MII_COMMSTAT_SQI_MAX		7
+
+#define MII_GENSTAT			24
+#define MII_GENSTAT_PLL_LOCKED		BIT(14)
+
+#define MII_EXTSTAT			25
+#define MII_EXTSTAT_SHORT_DETECT	BIT(8)
+#define MII_EXTSTAT_OPEN_DETECT		BIT(7)
+#define MII_EXTSTAT_POLARITY_DETECT	BIT(6)
+
+#define MII_COMMCFG			27
+#define MII_COMMCFG_AUTO_OP		BIT(15)
+
+static inline int tja11xx_set_bits(struct phy_device *phydev, u32 regnum,
+				   u16 val)
+{
+	return phy_set_bits_mmd(phydev, MDIO_DEVAD_NONE, regnum, val);
+}
+
+static inline int tja11xx_clear_bits(struct phy_device *phydev, u32 regnum,
+				     u16 val)
+{
+	return phy_clear_bits_mmd(phydev, MDIO_DEVAD_NONE, regnum, val);
+}
+
+static inline int tja11xx_read(struct phy_device *phydev, int regnum)
+{
+	return phy_read(phydev, MDIO_DEVAD_NONE, regnum);
+}
+
+static inline int tja11xx_modify(struct phy_device *phydev, int regnum,
+				 u16 mask, u16 set)
+{
+	return phy_modify(phydev, MDIO_DEVAD_NONE, regnum, mask, set);
+}
+
+static int tja11xx_check(struct phy_device *phydev, u8 reg, u16 mask, u16 set)
+{
+	int val;
+
+	return read_poll_timeout(tja11xx_read, val, (val & mask) == set, 150,
+				 30000, phydev, reg);
+}
+
+static int tja11xx_modify_check(struct phy_device *phydev, u8 reg,
+			    u16 mask, u16 set)
+{
+	int ret;
+
+	ret = tja11xx_modify(phydev, reg, mask, set);
+	if (ret)
+		return ret;
+
+	return tja11xx_check(phydev, reg, mask, set);
+}
+
+static int tja11xx_enable_reg_write(struct phy_device *phydev)
+{
+	return tja11xx_set_bits(phydev, MII_ECTRL, MII_ECTRL_CONFIG_EN);
+}
+
+static int tja11xx_enable_link_control(struct phy_device *phydev)
+{
+	return tja11xx_set_bits(phydev, MII_ECTRL, MII_ECTRL_LINK_CONTROL);
+}
+
+static int tja11xx_wakeup(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = tja11xx_read(phydev, MII_ECTRL);
+	if (ret < 0)
+		return ret;
+
+	switch (ret & MII_ECTRL_POWER_MODE_MASK) {
+	case MII_ECTRL_POWER_MODE_NO_CHANGE:
+		break;
+	case MII_ECTRL_POWER_MODE_NORMAL:
+		ret = tja11xx_set_bits(phydev, MII_ECTRL,
+				       MII_ECTRL_WAKE_REQUEST);
+		if (ret)
+			return ret;
+
+		ret = tja11xx_clear_bits(phydev, MII_ECTRL,
+					 MII_ECTRL_WAKE_REQUEST);
+		if (ret)
+			return ret;
+		break;
+	case MII_ECTRL_POWER_MODE_STANDBY:
+		ret = tja11xx_modify_check(phydev, MII_ECTRL,
+					   MII_ECTRL_POWER_MODE_MASK,
+					   MII_ECTRL_POWER_MODE_STANDBY);
+		if (ret)
+			return ret;
+
+		ret = tja11xx_modify(phydev, MII_ECTRL,
+				     MII_ECTRL_POWER_MODE_MASK,
+				     MII_ECTRL_POWER_MODE_NORMAL);
+		if (ret)
+			return ret;
+
+		ret = tja11xx_modify_check(phydev, MII_GENSTAT,
+					   MII_GENSTAT_PLL_LOCKED,
+					   MII_GENSTAT_PLL_LOCKED);
+		if (ret)
+			return ret;
+
+		return tja11xx_enable_link_control(phydev);
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int tja11xx_config_init(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = tja11xx_enable_reg_write(phydev);
+	if (ret)
+		return ret;
+
+	phydev->autoneg = AUTONEG_DISABLE;
+	phydev->speed = SPEED_100;
+	phydev->duplex = DUPLEX_FULL;
+
+	switch (phydev->phy_id & PHY_ID_MASK) {
+	case PHY_ID_TJA1100:
+		ret = tja11xx_modify(phydev, MII_CFG1,
+				     MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_MASK |
+				     MII_CFG1_LED_ENABLE,
+				     MII_CFG1_AUTO_OP |
+				     MII_CFG1_LED_MODE_LINKUP |
+				     MII_CFG1_LED_ENABLE);
+		if (ret)
+			return ret;
+		break;
+	case PHY_ID_TJA1101:
+		ret = tja11xx_set_bits(phydev, MII_COMMCFG,
+				       MII_COMMCFG_AUTO_OP);
+		if (ret)
+			return ret;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = tja11xx_clear_bits(phydev, MII_CFG1, MII_CFG1_SLEEP_CONFIRM);
+	if (ret)
+		return ret;
+
+	ret = tja11xx_modify(phydev, MII_CFG2, MII_CFG2_SLEEP_REQUEST_TO,
+			     MII_CFG2_SLEEP_REQUEST_TO_16MS);
+	if (ret)
+		return ret;
+
+	ret = tja11xx_wakeup(phydev);
+	if (ret < 0)
+		return ret;
+
+	/* ACK interrupts by reading the status register */
+	ret = tja11xx_read(phydev, MII_INTSRC);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int tja11xx_startup(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	ret = tja11xx_read(phydev, MII_CFG1);
+	if (ret < 0)
+		return ret;
+
+	if (phydev->link) {
+		ret = tja11xx_read(phydev, MII_COMMSTAT);
+		if (ret < 0)
+			return ret;
+
+		if (!(ret & MII_COMMSTAT_LINK_UP))
+			phydev->link = 0;
+	}
+
+	return 0;
+}
+
+static struct phy_driver TJA1100_driver = {
+	.name = "NXP TJA1100",
+	.uid = PHY_ID_TJA1100,
+	.mask = PHY_ID_MASK,
+	.features = PHY_BASIC_FEATURES,
+	.config	= &tja11xx_config_init,
+	.startup = &tja11xx_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver TJA1101_driver = {
+	.name = "NXP TJA1101",
+	.uid = PHY_ID_TJA1101,
+	.mask = PHY_ID_MASK,
+	.features = PHY_BASIC_FEATURES,
+	.config	= &tja11xx_config_init,
+	.startup = &tja11xx_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_nxp_tja11xx_init(void)
+{
+	phy_register(&TJA1100_driver);
+	phy_register(&TJA1101_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 50448cf62c4..36722620f0c 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -532,6 +532,9 @@ int phy_init(void)
 #ifdef CONFIG_NXP_C45_TJA11XX_PHY
 	phy_nxp_c45_tja11xx_init();
 #endif
+#ifdef CONFIG_PHY_NXP_TJA11XX
+	phy_nxp_tja11xx_init();
+#endif
 #ifdef CONFIG_PHY_REALTEK
 	phy_realtek_init();
 #endif
diff --git a/include/phy.h b/include/phy.h
index 1a30aee5421..528839a33de 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -556,6 +556,7 @@ int phy_micrel_ksz90x1_init(void);
 int phy_meson_gxl_init(void);
 int phy_natsemi_init(void);
 int phy_nxp_c45_tja11xx_init(void);
+int phy_nxp_tja11xx_init(void);
 int phy_realtek_init(void);
 int phy_smsc_init(void);
 int phy_teranetics_init(void);
-- 
2.34.1


  parent reply	other threads:[~2022-04-12 13:37 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-12 13:31 [PATCH v5 0/7] imx8mn-smm-s2/pro: Add iMX8MN BSH SMM S2 boards Ariel D'Alessandro
2022-04-12 13:31 ` [PATCH v5 1/7] imx8m: add regs used by GPMI Ariel D'Alessandro
2022-04-12 18:47   ` sbabic
2022-04-12 13:31 ` [PATCH v5 2/7] imx8m: add init_nand_clk Ariel D'Alessandro
2022-04-12 18:46   ` sbabic
2022-04-12 13:31 ` [PATCH v5 3/7] phy: nxp-c45-tja11xx: Rename functions to be c45 tja11xx specific Ariel D'Alessandro
2022-04-12 18:46   ` sbabic
2022-04-12 13:31 ` [PATCH v5 4/7] iopoll: Extend read_poll_timeout macro to support variable parameters Ariel D'Alessandro
2022-04-12 18:45   ` sbabic
2022-04-12 13:31 ` [PATCH v5 5/7] net: phy: Add phy_modify() accessor Ariel D'Alessandro
2022-04-12 18:43   ` sbabic
2022-04-12 13:31 ` Ariel D'Alessandro [this message]
2022-04-12 18:45   ` [PATCH v5 6/7] net: phy: nxp-tja11xx: Add NXP TJA11xx PHY driver sbabic
2022-04-12 13:31 ` [PATCH v5 7/7] bsh: imx8mn-smm-s2/pro: Add iMX8MN BSH SMM S2 boards Ariel D'Alessandro
2022-04-12 18:46   ` sbabic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220412133138.110815-7-ariel.dalessandro@collabora.com \
    --to=ariel.dalessandro@collabora.com \
    --cc=Peter.Hoyes@arm.com \
    --cc=aford173@gmail.com \
    --cc=alice.guo@nxp.com \
    --cc=andre.przywara@arm.com \
    --cc=andrey.zhizhikin@leica-geosystems.com \
    --cc=bmeng.cn@gmail.com \
    --cc=christian.gmeiner@gmail.com \
    --cc=christianshewitt@gmail.com \
    --cc=festevam@gmail.com \
    --cc=iliev@ronetix.at \
    --cc=jagan@amarulasolutions.com \
    --cc=jh80.chung@samsung.com \
    --cc=joe.hershberger@ni.com \
    --cc=kettenis@openbsd.org \
    --cc=kever.yang@rock-chips.com \
    --cc=kuldeep.singh@nxp.com \
    --cc=marcel.ziswiler@toradex.com \
    --cc=marex@denx.de \
    --cc=michael@amarulasolutions.com \
    --cc=michal.simek@xilinx.com \
    --cc=oliver.graute@kococonnector.com \
    --cc=pali@kernel.org \
    --cc=paul.liu@linaro.org \
    --cc=pbrobinson@gmail.com \
    --cc=peng.fan@nxp.com \
    --cc=philipp.tomsich@vrull.eu \
    --cc=priyanka.jain@nxp.com \
    --cc=radu-nicolae.pirea@oss.nxp.com \
    --cc=rath@ibv-augsburg.net \
    --cc=rfried.dev@gmail.com \
    --cc=samuel@sholland.org \
    --cc=sbabic@denx.de \
    --cc=simon.k.r.goldschmidt@gmail.com \
    --cc=sjg@chromium.org \
    --cc=stephan@gerhold.net \
    --cc=tharvey@gateworks.com \
    --cc=tien.fong.chee@intel.com \
    --cc=u-boot@lists.denx.de \
    --cc=uboot-imx@nxp.com \
    --cc=vladimir.oltean@nxp.com \
    --cc=wd@denx.de \
    --cc=xypron.glpk@gmx.de \
    --cc=ye.li@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.