Merge branch 'master' of github.com:armbian/build

This commit is contained in:
tonymac32 2021-06-28 01:16:02 -04:00
commit a53eadc325
10 changed files with 1085 additions and 344 deletions

View File

@ -2392,6 +2392,7 @@ CONFIG_MICREL_PHY=m
CONFIG_MICROCHIP_PHY=m
CONFIG_MICROCHIP_T1_PHY=m
# CONFIG_MICROSEMI_PHY is not set
CONFIG_MOTORCOMM_PHY=m
CONFIG_NATIONAL_PHY=m
# CONFIG_NXP_TJA11XX_PHY is not set
CONFIG_AT803X_PHY=m

View File

@ -2422,6 +2422,7 @@ CONFIG_MICREL_PHY=m
CONFIG_MICROCHIP_PHY=m
CONFIG_MICROCHIP_T1_PHY=m
# CONFIG_MICROSEMI_PHY is not set
CONFIG_MOTORCOMM_PHY=m
CONFIG_NATIONAL_PHY=m
# CONFIG_NXP_TJA11XX_PHY is not set
CONFIG_AT803X_PHY=m

View File

@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 5.4.85 Kernel Configuration
# Linux/arm64 5.4.88 Kernel Configuration
#
#
@ -2463,6 +2463,7 @@ CONFIG_MICREL_PHY=y
CONFIG_MICROCHIP_PHY=m
CONFIG_MICROCHIP_T1_PHY=m
# CONFIG_MICROSEMI_PHY is not set
CONFIG_MOTORCOMM_PHY=m
CONFIG_NATIONAL_PHY=m
# CONFIG_NXP_TJA11XX_PHY is not set
CONFIG_QSEMI_PHY=m

View File

@ -0,0 +1,39 @@
From 0745b77825cdc10eb5381f75056d1a37fbb533ba Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Wed, 9 Jun 2021 12:45:25 +0800
Subject: [PATCH 4/4] arm64: dts: allwinner: a64-sopine-baseboard: change RGMII
mode to TXID
Although the schematics of Pine A64-LTS and SoPine Baseboard shows both
the RX and TX internal delay are enabled, they're using the same broken
RTL8211E chip batch with Pine A64+, so they should use TXID instead, not
ID.
In addition, by checking the real components soldered on both a SoPine
Baseboard and a Pine A64-LTS, RX delay is not enabled (GR69 soldered and
GR70 NC) despite the schematics says it's enabled.
So the RGMII delay mode should be TXID on these boards.
Fixes: c2b111e59a7b ("arm64: dts: allwinner: A64 Sopine: phy-mode rgmii-id")
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index d4069749d721..068cbd955bfc 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -79,7 +79,7 @@ &ehci1 {
&emac {
pinctrl-names = "default";
pinctrl-0 = <&rgmii_pins>;
- phy-mode = "rgmii-id";
+ phy-mode = "rgmii-txid";
phy-handle = <&ext_rgmii_phy>;
phy-supply = <&reg_dc1sw>;
status = "okay";
--
2.30.2

View File

@ -0,0 +1,319 @@
From 2c931ae9788444a8994928366c18d540c9a760eb Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Thu, 20 May 2021 12:32:30 -0400
Subject: [PATCH 1/4] net: phy: add driver for Motorcomm yt8511 phy
Add a driver for the Motorcomm yt8511 phy that will be used in the
production Pine64 rk3566-quartz64 development board.
It supports gigabit transfer speeds, rgmii, and 125mhz clk output.
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
MAINTAINERS | 6 ++
drivers/net/phy/Kconfig | 6 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/motorcomm.c | 136 ++++++++++++++++++++++++++++++++++++
4 files changed, 149 insertions(+)
create mode 100644 drivers/net/phy/motorcomm.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 4fef10dd2975..0d1d0845da3b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11812,6 +11812,12 @@ F: Documentation/userspace-api/media/drivers/meye*
F: drivers/media/pci/meye/
F: include/uapi/linux/meye.h
+MOTORCOMM PHY DRIVER
+M: Peter Geis <pgwipeout@gmail.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/phy/motorcomm.c
+
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@kernel.org>
S: Maintained
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 698bea312adc..940f2d701f86 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -223,6 +223,12 @@ config MICROSEMI_PHY
help
Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
+config MOTORCOMM_PHY
+ tristate "Motorcomm PHYs"
+ help
+ Enables support for Motorcomm network PHYs.
+ Currently supports the YT8511 gigabit PHY.
+
config NATIONAL_PHY
tristate "National Semiconductor PHYs"
help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index a13e402074cf..5b9b714b8dbd 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o
obj-$(CONFIG_MICROSEMI_PHY) += mscc/
+obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
new file mode 100644
index 000000000000..796b68f4b499
--- /dev/null
+++ b/drivers/net/phy/motorcomm.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Motorcomm PHYs
+ *
+ * Author: Peter Geis <pgwipeout@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define PHY_ID_YT8511 0x0000010a
+
+#define YT8511_PAGE_SELECT 0x1e
+#define YT8511_PAGE 0x1f
+#define YT8511_EXT_CLK_GATE 0x0c
+#define YT8511_EXT_DELAY_DRIVE 0x0d
+#define YT8511_EXT_SLEEP_CTRL 0x27
+
+/* 2b00 25m from pll
+ * 2b01 25m from xtl *default*
+ * 2b10 62.m from pll
+ * 2b11 125m from pll
+ */
+#define YT8511_CLK_125M (BIT(2) | BIT(1))
+#define YT8511_PLLON_SLP BIT(14)
+
+/* RX Delay enabled = 1.8ns 1000T, 8ns 10/100T */
+#define YT8511_DELAY_RX BIT(0)
+
+/* TX Gig-E Delay is bits 7:4, default 0x5
+ * TX Fast-E Delay is bits 15:12, default 0xf
+ * Delay = 150ps * N - 250ps
+ * On = 2000ps, off = 50ps
+ */
+#define YT8511_DELAY_GE_TX_EN (0xf << 4)
+#define YT8511_DELAY_GE_TX_DIS (0x2 << 4)
+#define YT8511_DELAY_FE_TX_EN (0xf << 12)
+#define YT8511_DELAY_FE_TX_DIS (0x2 << 12)
+
+static int yt8511_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, YT8511_PAGE_SELECT);
+};
+
+static int yt8511_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, YT8511_PAGE_SELECT, page);
+};
+
+static int yt8511_config_init(struct phy_device *phydev)
+{
+ unsigned int ge, fe;
+ int ret, oldpage;
+
+ /* set clock mode to 125mhz */
+ oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
+ if (oldpage < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* set rgmii delay mode */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ ge = YT8511_DELAY_GE_TX_DIS;
+ fe = YT8511_DELAY_FE_TX_DIS;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_DIS;
+ fe = YT8511_DELAY_FE_TX_DIS;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ge = YT8511_DELAY_GE_TX_EN;
+ fe = YT8511_DELAY_FE_TX_EN;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN;
+ fe = YT8511_DELAY_FE_TX_EN;
+ break;
+ default: /* leave everything alone in other modes */
+ break;
+ }
+
+ ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* fast ethernet delay is in a separate page */
+ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE);
+ if (ret < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, YT8511_DELAY_FE_TX_EN, fe);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* leave pll enabled in sleep */
+ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_SLEEP_CTRL);
+ if (ret < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_PLLON_SLP);
+ if (ret < 0)
+ goto err_restore_page;
+
+err_restore_page:
+ return phy_restore_page(phydev, oldpage, ret);
+}
+
+static struct phy_driver motorcomm_phy_drvs[] = {
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_YT8511),
+ .name = "YT8511 Gigabit Ethernet",
+ .config_init = yt8511_config_init,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = yt8511_read_page,
+ .write_page = yt8511_write_page,
+ },
+};
+
+module_phy_driver(motorcomm_phy_drvs);
+
+MODULE_DESCRIPTION("Motorcomm PHY driver");
+MODULE_AUTHOR("Peter Geis");
+MODULE_LICENSE("GPL");
+
+static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) },
+ { /* sentinal */ }
+};
+
+MODULE_DEVICE_TABLE(mdio, motorcomm_tbl);
--
2.30.2
From 5e464ac4cd49603515a053b7292597bfd0e9672c Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Sat, 29 May 2021 07:05:55 -0400
Subject: [PATCH 2/4] net: phy: fix yt8511 clang uninitialized variable warning
clang doesn't preinitialize variables. If phy_select_page failed and
returned an error, phy_restore_page would be called with `ret` being
uninitialized.
Even though phy_restore_page won't use `ret` in this scenario,
initialize `ret` to silence the warning.
Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy")
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/motorcomm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 796b68f4b499..68cd19540c67 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -50,8 +50,8 @@ static int yt8511_write_page(struct phy_device *phydev, int page)
static int yt8511_config_init(struct phy_device *phydev)
{
+ int oldpage, ret = 0;
unsigned int ge, fe;
- int ret, oldpage;
/* set clock mode to 125mhz */
oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
--
2.30.2
From a085ebd8f84bb556116ab41961c4fa671dc84fba Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Sat, 29 May 2021 07:05:56 -0400
Subject: [PATCH 3/4] net: phy: abort loading yt8511 driver in unsupported
modes
While investigating the clang `ge` uninitialized variable report, it was
discovered the default switch would have unintended consequences. Due to
the switch to __phy_modify, the driver would modify the ID values in the
default scenario.
Fix this by promoting the interface mode switch and aborting when the
mode is not a supported RGMII mode.
This prevents the `ge` and `fe` variables from ever being used
uninitialized.
Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy")
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/motorcomm.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 68cd19540c67..7e6ac2c5e27e 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -53,15 +53,10 @@ static int yt8511_config_init(struct phy_device *phydev)
int oldpage, ret = 0;
unsigned int ge, fe;
- /* set clock mode to 125mhz */
oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
if (oldpage < 0)
goto err_restore_page;
- ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
- if (ret < 0)
- goto err_restore_page;
-
/* set rgmii delay mode */
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
@@ -80,14 +75,20 @@ static int yt8511_config_init(struct phy_device *phydev)
ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN;
fe = YT8511_DELAY_FE_TX_EN;
break;
- default: /* leave everything alone in other modes */
- break;
+ default: /* do not support other modes */
+ ret = -EOPNOTSUPP;
+ goto err_restore_page;
}
ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge);
if (ret < 0)
goto err_restore_page;
+ /* set clock mode to 125mhz */
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
+ if (ret < 0)
+ goto err_restore_page;
+
/* fast ethernet delay is in a separate page */
ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE);
if (ret < 0)
--
2.30.2

View File

@ -0,0 +1,39 @@
From 354d29be4a37055df567f1eb933e19a11e0ef88b Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Wed, 9 Jun 2021 12:45:25 +0800
Subject: [PATCH 4/4] arm64: dts: allwinner: a64-sopine-baseboard: change RGMII
mode to TXID
Although the schematics of Pine A64-LTS and SoPine Baseboard shows both
the RX and TX internal delay are enabled, they're using the same broken
RTL8211E chip batch with Pine A64+, so they should use TXID instead, not
ID.
In addition, by checking the real components soldered on both a SoPine
Baseboard and a Pine A64-LTS, RX delay is not enabled (GR69 soldered and
GR70 NC) despite the schematics says it's enabled.
So the RGMII delay mode should be TXID on these boards.
Fixes: c2b111e59a7b ("arm64: dts: allwinner: A64 Sopine: phy-mode rgmii-id")
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index e22b94c83647..5e66ce1a334f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -79,7 +79,7 @@ &ehci1 {
&emac {
pinctrl-names = "default";
pinctrl-0 = <&rgmii_pins>;
- phy-mode = "rgmii-id";
+ phy-mode = "rgmii-txid";
phy-handle = <&ext_rgmii_phy>;
phy-supply = <&reg_dc1sw>;
status = "okay";
--
2.30.2

View File

@ -0,0 +1,319 @@
From 4ed95d5b19ded99909ce63d1c2740da60f7abd04 Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Thu, 20 May 2021 12:32:30 -0400
Subject: [PATCH 1/4] net: phy: add driver for Motorcomm yt8511 phy
Add a driver for the Motorcomm yt8511 phy that will be used in the
production Pine64 rk3566-quartz64 development board.
It supports gigabit transfer speeds, rgmii, and 125mhz clk output.
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
MAINTAINERS | 6 ++
drivers/net/phy/Kconfig | 6 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/motorcomm.c | 136 ++++++++++++++++++++++++++++++++++++
4 files changed, 149 insertions(+)
create mode 100644 drivers/net/phy/motorcomm.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 9450e052f1b1..0f71a9983263 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12094,6 +12094,12 @@ F: Documentation/userspace-api/media/drivers/meye*
F: drivers/media/pci/meye/
F: include/uapi/linux/meye.h
+MOTORCOMM PHY DRIVER
+M: Peter Geis <pgwipeout@gmail.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/phy/motorcomm.c
+
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@kernel.org>
S: Maintained
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 698bea312adc..940f2d701f86 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -223,6 +223,12 @@ config MICROSEMI_PHY
help
Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
+config MOTORCOMM_PHY
+ tristate "Motorcomm PHYs"
+ help
+ Enables support for Motorcomm network PHYs.
+ Currently supports the YT8511 gigabit PHY.
+
config NATIONAL_PHY
tristate "National Semiconductor PHYs"
help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index a13e402074cf..5b9b714b8dbd 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o
obj-$(CONFIG_MICROSEMI_PHY) += mscc/
+obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
new file mode 100644
index 000000000000..796b68f4b499
--- /dev/null
+++ b/drivers/net/phy/motorcomm.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Motorcomm PHYs
+ *
+ * Author: Peter Geis <pgwipeout@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define PHY_ID_YT8511 0x0000010a
+
+#define YT8511_PAGE_SELECT 0x1e
+#define YT8511_PAGE 0x1f
+#define YT8511_EXT_CLK_GATE 0x0c
+#define YT8511_EXT_DELAY_DRIVE 0x0d
+#define YT8511_EXT_SLEEP_CTRL 0x27
+
+/* 2b00 25m from pll
+ * 2b01 25m from xtl *default*
+ * 2b10 62.m from pll
+ * 2b11 125m from pll
+ */
+#define YT8511_CLK_125M (BIT(2) | BIT(1))
+#define YT8511_PLLON_SLP BIT(14)
+
+/* RX Delay enabled = 1.8ns 1000T, 8ns 10/100T */
+#define YT8511_DELAY_RX BIT(0)
+
+/* TX Gig-E Delay is bits 7:4, default 0x5
+ * TX Fast-E Delay is bits 15:12, default 0xf
+ * Delay = 150ps * N - 250ps
+ * On = 2000ps, off = 50ps
+ */
+#define YT8511_DELAY_GE_TX_EN (0xf << 4)
+#define YT8511_DELAY_GE_TX_DIS (0x2 << 4)
+#define YT8511_DELAY_FE_TX_EN (0xf << 12)
+#define YT8511_DELAY_FE_TX_DIS (0x2 << 12)
+
+static int yt8511_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, YT8511_PAGE_SELECT);
+};
+
+static int yt8511_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, YT8511_PAGE_SELECT, page);
+};
+
+static int yt8511_config_init(struct phy_device *phydev)
+{
+ unsigned int ge, fe;
+ int ret, oldpage;
+
+ /* set clock mode to 125mhz */
+ oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
+ if (oldpage < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* set rgmii delay mode */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ ge = YT8511_DELAY_GE_TX_DIS;
+ fe = YT8511_DELAY_FE_TX_DIS;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_DIS;
+ fe = YT8511_DELAY_FE_TX_DIS;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ge = YT8511_DELAY_GE_TX_EN;
+ fe = YT8511_DELAY_FE_TX_EN;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN;
+ fe = YT8511_DELAY_FE_TX_EN;
+ break;
+ default: /* leave everything alone in other modes */
+ break;
+ }
+
+ ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* fast ethernet delay is in a separate page */
+ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE);
+ if (ret < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, YT8511_DELAY_FE_TX_EN, fe);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* leave pll enabled in sleep */
+ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_SLEEP_CTRL);
+ if (ret < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_PLLON_SLP);
+ if (ret < 0)
+ goto err_restore_page;
+
+err_restore_page:
+ return phy_restore_page(phydev, oldpage, ret);
+}
+
+static struct phy_driver motorcomm_phy_drvs[] = {
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_YT8511),
+ .name = "YT8511 Gigabit Ethernet",
+ .config_init = yt8511_config_init,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = yt8511_read_page,
+ .write_page = yt8511_write_page,
+ },
+};
+
+module_phy_driver(motorcomm_phy_drvs);
+
+MODULE_DESCRIPTION("Motorcomm PHY driver");
+MODULE_AUTHOR("Peter Geis");
+MODULE_LICENSE("GPL");
+
+static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) },
+ { /* sentinal */ }
+};
+
+MODULE_DEVICE_TABLE(mdio, motorcomm_tbl);
--
2.30.2
From 7828b6d9f8764ea28ea9c4326add1565299bb2e5 Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Sat, 29 May 2021 07:05:55 -0400
Subject: [PATCH 2/4] net: phy: fix yt8511 clang uninitialized variable warning
clang doesn't preinitialize variables. If phy_select_page failed and
returned an error, phy_restore_page would be called with `ret` being
uninitialized.
Even though phy_restore_page won't use `ret` in this scenario,
initialize `ret` to silence the warning.
Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy")
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/motorcomm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 796b68f4b499..68cd19540c67 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -50,8 +50,8 @@ static int yt8511_write_page(struct phy_device *phydev, int page)
static int yt8511_config_init(struct phy_device *phydev)
{
+ int oldpage, ret = 0;
unsigned int ge, fe;
- int ret, oldpage;
/* set clock mode to 125mhz */
oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
--
2.30.2
From a33cfaee53ac7e671632f2511192ec6bb2b60b4c Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Sat, 29 May 2021 07:05:56 -0400
Subject: [PATCH 3/4] net: phy: abort loading yt8511 driver in unsupported
modes
While investigating the clang `ge` uninitialized variable report, it was
discovered the default switch would have unintended consequences. Due to
the switch to __phy_modify, the driver would modify the ID values in the
default scenario.
Fix this by promoting the interface mode switch and aborting when the
mode is not a supported RGMII mode.
This prevents the `ge` and `fe` variables from ever being used
uninitialized.
Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy")
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/motorcomm.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 68cd19540c67..7e6ac2c5e27e 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -53,15 +53,10 @@ static int yt8511_config_init(struct phy_device *phydev)
int oldpage, ret = 0;
unsigned int ge, fe;
- /* set clock mode to 125mhz */
oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
if (oldpage < 0)
goto err_restore_page;
- ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
- if (ret < 0)
- goto err_restore_page;
-
/* set rgmii delay mode */
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
@@ -80,14 +75,20 @@ static int yt8511_config_init(struct phy_device *phydev)
ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN;
fe = YT8511_DELAY_FE_TX_EN;
break;
- default: /* leave everything alone in other modes */
- break;
+ default: /* do not support other modes */
+ ret = -EOPNOTSUPP;
+ goto err_restore_page;
}
ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge);
if (ret < 0)
goto err_restore_page;
+ /* set clock mode to 125mhz */
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
+ if (ret < 0)
+ goto err_restore_page;
+
/* fast ethernet delay is in a separate page */
ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE);
if (ret < 0)
--
2.30.2

View File

@ -0,0 +1,44 @@
From 5aa33a6b5581ad1227b8093b18e2c5bf531e11ed Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Wed, 9 Jun 2021 16:38:43 +0800
Subject: [PATCH 4/4] arm64: dts: allwinner: a64-sopine-baseboard: change RGMII
mode to TXID
Although the schematics of Pine A64-LTS and SoPine Baseboard shows both
the RX and TX internal delay are enabled, they're using the same broken
RTL8211E chip batch with Pine A64+, so they should use TXID instead, not
ID.
In addition, by checking the real components soldered on both a SoPine
Baseboard and a Pine A64-LTS, RX delay is not enabled (GR69 soldered and
GR70 NC) despite the schematics says it's enabled. It's a common
situation for Pine64 boards that the NC information on schematics is not
the same with the board.
So the RGMII delay mode should be TXID on these boards.
Fixes: c2b111e59a7b ("arm64: dts: allwinner: A64 Sopine: phy-mode rgmii-id")
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20210609083843.463750-1-icenowy@aosc.io
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index 25099202c52c..170bb19d894e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -115,7 +115,7 @@
&emac {
pinctrl-names = "default";
pinctrl-0 = <&rgmii_pins>;
- phy-mode = "rgmii";
+ phy-mode = "rgmii-txid";
phy-handle = <&ext_rgmii_phy>;
phy-supply = <&reg_dc1sw>;
status = "okay";
--
2.30.2

View File

@ -0,0 +1,321 @@
From ec565edb5e9216aee89412be327d59f038582df4 Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Thu, 20 May 2021 12:32:30 -0400
Subject: [PATCH 1/4] net: phy: add driver for Motorcomm yt8511 phy
Add a driver for the Motorcomm yt8511 phy that will be used in the
production Pine64 rk3566-quartz64 development board.
It supports gigabit transfer speeds, rgmii, and 125mhz clk output.
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[Icenowy: backport to 5.4]
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
MAINTAINERS | 6 ++
drivers/net/phy/Kconfig | 6 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/motorcomm.c | 136 ++++++++++++++++++++++++++++++++++++
4 files changed, 149 insertions(+)
create mode 100644 drivers/net/phy/motorcomm.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 1407008df749..fd8518bc5ba8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10966,6 +10966,12 @@ F: Documentation/media/v4l-drivers/meye*
F: drivers/media/pci/meye/
F: include/uapi/linux/meye.h
+MOTORCOMM PHY DRIVER
+M: Peter Geis <pgwipeout@gmail.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/phy/motorcomm.c
+
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
M: Jiri Slaby <jirislaby@gmail.com>
S: Maintained
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index dcf2051ef2c0..a9c66f28c0ce 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -434,6 +434,12 @@ config MICROSEMI_PHY
---help---
Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
+config MOTORCOMM_PHY
+ tristate "Motorcomm PHYs"
+ help
+ Enables support for Motorcomm network PHYs.
+ Currently supports the YT8511 gigabit PHY.
+
config NATIONAL_PHY
tristate "National Semiconductor PHYs"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index a03437e091f3..a3933c83fbdc 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o
obj-$(CONFIG_MICROSEMI_PHY) += mscc.o
+obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
new file mode 100644
index 000000000000..796b68f4b499
--- /dev/null
+++ b/drivers/net/phy/motorcomm.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Motorcomm PHYs
+ *
+ * Author: Peter Geis <pgwipeout@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define PHY_ID_YT8511 0x0000010a
+
+#define YT8511_PAGE_SELECT 0x1e
+#define YT8511_PAGE 0x1f
+#define YT8511_EXT_CLK_GATE 0x0c
+#define YT8511_EXT_DELAY_DRIVE 0x0d
+#define YT8511_EXT_SLEEP_CTRL 0x27
+
+/* 2b00 25m from pll
+ * 2b01 25m from xtl *default*
+ * 2b10 62.m from pll
+ * 2b11 125m from pll
+ */
+#define YT8511_CLK_125M (BIT(2) | BIT(1))
+#define YT8511_PLLON_SLP BIT(14)
+
+/* RX Delay enabled = 1.8ns 1000T, 8ns 10/100T */
+#define YT8511_DELAY_RX BIT(0)
+
+/* TX Gig-E Delay is bits 7:4, default 0x5
+ * TX Fast-E Delay is bits 15:12, default 0xf
+ * Delay = 150ps * N - 250ps
+ * On = 2000ps, off = 50ps
+ */
+#define YT8511_DELAY_GE_TX_EN (0xf << 4)
+#define YT8511_DELAY_GE_TX_DIS (0x2 << 4)
+#define YT8511_DELAY_FE_TX_EN (0xf << 12)
+#define YT8511_DELAY_FE_TX_DIS (0x2 << 12)
+
+static int yt8511_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, YT8511_PAGE_SELECT);
+};
+
+static int yt8511_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, YT8511_PAGE_SELECT, page);
+};
+
+static int yt8511_config_init(struct phy_device *phydev)
+{
+ unsigned int ge, fe;
+ int ret, oldpage;
+
+ /* set clock mode to 125mhz */
+ oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
+ if (oldpage < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* set rgmii delay mode */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ ge = YT8511_DELAY_GE_TX_DIS;
+ fe = YT8511_DELAY_FE_TX_DIS;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_DIS;
+ fe = YT8511_DELAY_FE_TX_DIS;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ge = YT8511_DELAY_GE_TX_EN;
+ fe = YT8511_DELAY_FE_TX_EN;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN;
+ fe = YT8511_DELAY_FE_TX_EN;
+ break;
+ default: /* leave everything alone in other modes */
+ break;
+ }
+
+ ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* fast ethernet delay is in a separate page */
+ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE);
+ if (ret < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, YT8511_DELAY_FE_TX_EN, fe);
+ if (ret < 0)
+ goto err_restore_page;
+
+ /* leave pll enabled in sleep */
+ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_SLEEP_CTRL);
+ if (ret < 0)
+ goto err_restore_page;
+
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_PLLON_SLP);
+ if (ret < 0)
+ goto err_restore_page;
+
+err_restore_page:
+ return phy_restore_page(phydev, oldpage, ret);
+}
+
+static struct phy_driver motorcomm_phy_drvs[] = {
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_YT8511),
+ .name = "YT8511 Gigabit Ethernet",
+ .config_init = yt8511_config_init,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = yt8511_read_page,
+ .write_page = yt8511_write_page,
+ },
+};
+
+module_phy_driver(motorcomm_phy_drvs);
+
+MODULE_DESCRIPTION("Motorcomm PHY driver");
+MODULE_AUTHOR("Peter Geis");
+MODULE_LICENSE("GPL");
+
+static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) },
+ { /* sentinal */ }
+};
+
+MODULE_DEVICE_TABLE(mdio, motorcomm_tbl);
--
2.30.2
From 9e2a06d3a2165c2d2e01aca6ab3a74d7a9623377 Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Sat, 29 May 2021 07:05:55 -0400
Subject: [PATCH 2/4] net: phy: fix yt8511 clang uninitialized variable warning
clang doesn't preinitialize variables. If phy_select_page failed and
returned an error, phy_restore_page would be called with `ret` being
uninitialized.
Even though phy_restore_page won't use `ret` in this scenario,
initialize `ret` to silence the warning.
Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy")
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/motorcomm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 796b68f4b499..68cd19540c67 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -50,8 +50,8 @@ static int yt8511_write_page(struct phy_device *phydev, int page)
static int yt8511_config_init(struct phy_device *phydev)
{
+ int oldpage, ret = 0;
unsigned int ge, fe;
- int ret, oldpage;
/* set clock mode to 125mhz */
oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
--
2.30.2
From 6e20d54c9574d980af58e83f0626991ba650dbd9 Mon Sep 17 00:00:00 2001
From: Peter Geis <pgwipeout@gmail.com>
Date: Sat, 29 May 2021 07:05:56 -0400
Subject: [PATCH 3/4] net: phy: abort loading yt8511 driver in unsupported
modes
While investigating the clang `ge` uninitialized variable report, it was
discovered the default switch would have unintended consequences. Due to
the switch to __phy_modify, the driver would modify the ID values in the
default scenario.
Fix this by promoting the interface mode switch and aborting when the
mode is not a supported RGMII mode.
This prevents the `ge` and `fe` variables from ever being used
uninitialized.
Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy")
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/motorcomm.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 68cd19540c67..7e6ac2c5e27e 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -53,15 +53,10 @@ static int yt8511_config_init(struct phy_device *phydev)
int oldpage, ret = 0;
unsigned int ge, fe;
- /* set clock mode to 125mhz */
oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE);
if (oldpage < 0)
goto err_restore_page;
- ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
- if (ret < 0)
- goto err_restore_page;
-
/* set rgmii delay mode */
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
@@ -80,14 +75,20 @@ static int yt8511_config_init(struct phy_device *phydev)
ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN;
fe = YT8511_DELAY_FE_TX_EN;
break;
- default: /* leave everything alone in other modes */
- break;
+ default: /* do not support other modes */
+ ret = -EOPNOTSUPP;
+ goto err_restore_page;
}
ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge);
if (ret < 0)
goto err_restore_page;
+ /* set clock mode to 125mhz */
+ ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M);
+ if (ret < 0)
+ goto err_restore_page;
+
/* fast ethernet delay is in a separate page */
ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE);
if (ret < 0)
--
2.30.2

View File

@ -1,343 +0,0 @@
diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c
index c1706dcec1..2e06ee4ed2 100644
--- a/arch/arm/cpu/armv8/generic_timer.c
+++ b/arch/arm/cpu/armv8/generic_timer.c
@@ -66,7 +66,7 @@ unsigned long timer_read_counter(void)
isb();
do {
asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
- } while (((cntpct + 1) & GENMASK(10, 0)) <= 1);
+ } while (((cntpct + 1) & GENMASK(9, 0)) <= 1);
return cntpct;
}
diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard.dts b/arch/arm/dts/sun50i-a64-sopine-baseboard.dts
index 53fcc9098d..8dac3f135b 100644
--- a/arch/arm/dts/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm/dts/sun50i-a64-sopine-baseboard.dts
@@ -55,6 +55,7 @@
aliases {
ethernet0 = &emac;
serial0 = &uart0;
+ spi0 = &spi0;
};
chosen {
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index ee387127f3..4aaa0932d7 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -321,6 +321,7 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_MMC(n) (AHB_GATE_OFFSET_MMC0 + (n))
#define AHB_GATE_OFFSET_DMA 6
#define AHB_GATE_OFFSET_SS 5
+#define AHB_GATE_OFFSET_SPI0 20
/* ahb_gate1 offsets */
#define AHB_GATE_OFFSET_DRC0 25
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
index 530e0dd73b..9bbd4d319e 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
@@ -194,6 +194,7 @@ struct sunxi_ccm_reg {
/* ahb gate1 field */
#define AHB_GATE_OFFSET_DMA 24
+#define AHB_GATE_OFFSET_SPI0 20
/* apb1_gate fields */
#define APB1_GATE_UART_SHIFT 16
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index 9ede081c08..af690c11c5 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -18,3 +18,20 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
CONFIG_SUN8I_EMAC=y
CONFIG_USB_EHCI_HCD=y
CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI=y
+CONFIG_SUN4I_SPI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHY_REALTEK=y
+CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y
\ No newline at end of file
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a7bb5b35c2..88e772cb1a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -219,9 +219,9 @@ config STM32_QSPI
this ST IP core.
config SUN4I_SPI
- bool "Allwinner A10 SoCs SPI controller"
+ bool "Allwinner SoCs SPI driver"
help
- SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
+ SPI driver for Allwinner SoCs
config TEGRA114_SPI
bool "nVidia Tegra114 SPI driver"
diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index 38cc743c61..7af8be15cf 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -37,6 +37,30 @@
#define SUN4I_TXDATA_REG 0x04
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+#define SUN4I_CTL_REG 0x04
+#define SUN4I_CTL_ENABLE BIT(0)
+#define SUN4I_CTL_MASTER BIT(1)
+#define SUN4I_CTL_TP BIT(7)
+#define SUN4I_CTL_SRST BIT(31)
+
+#define SUN4I_CTL_CPHA BIT(0)
+#define SUN4I_CTL_CPOL BIT(1)
+#define SUN4I_CTL_CS_ACTIVE_LOW BIT(2)
+#define SUN4I_CTL_CS_MASK 0x30
+#define SUN4I_CTL_CS(cs) (((cs) << 4) & SUN4I_CTL_CS_MASK)
+#define SUN4I_CTL_CS_MANUAL BIT(6)
+#define SUN4I_CTL_CS_LEVEL BIT(7)
+#define SUN4I_CTL_DHB BIT(8)
+#define SUN4I_CTL_XCH_MASK 0x80000000
+#define SUN4I_CTL_XCH BIT(31)
+
+#define SUN4I_CTL_RF_RST BIT(15)
+#define SUN4I_CTL_TF_RST BIT(31)
+
+#else
+#define SUN4I_CTL_SRST 0
+
#define SUN4I_CTL_REG 0x08
#define SUN4I_CTL_ENABLE BIT(0)
#define SUN4I_CTL_MASTER BIT(1)
@@ -54,6 +78,7 @@
#define SUN4I_CTL_CS_MANUAL BIT(16)
#define SUN4I_CTL_CS_LEVEL BIT(17)
#define SUN4I_CTL_TP BIT(18)
+#endif
#define SUN4I_INT_CTL_REG 0x0c
#define SUN4I_INT_CTL_RF_F34 BIT(4)
@@ -92,11 +117,39 @@
#define SUN4I_SPI_DEFAULT_RATE 1000000
#define SUN4I_SPI_TIMEOUT_US 1000000
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+/* sun6i spi register set */
+struct sun4i_spi_regs {
+ u32 res0;
+ u32 ctl; /* 0x04 */
+ u32 tctl; /* 0x08 */
+ u32 res1;
+ u32 intctl; /* 0x10 */
+ u32 st; /* 0x14 */
+ u32 fifo_ctl; /* 0x18 */
+ u32 fifo_sta; /* 0x1c */
+ u32 wait; /* 0x20 */
+ u32 cctl; /* 0x24 */
+ u32 res2[2];
+ u32 bc; /* 0x30 */
+ u32 tc; /* 0x34 */
+ u32 bctl; /* 0x38 */
+ u32 res3[113];
+ u32 txdata; /* 0x200 */
+ u32 res4[63];
+ u32 rxdata; /* 0x300 */
+};
+#else
/* sun4i spi register set */
struct sun4i_spi_regs {
u32 rxdata;
u32 txdata;
- u32 ctl;
+ union {
+ u32 ctl;
+ u32 tctl;
+ u32 fifo_ctl;
+ u32 bctl;
+ };
u32 intctl;
u32 st;
u32 dmactl;
@@ -106,6 +159,7 @@ struct sun4i_spi_regs {
u32 tc;
u32 fifo_sta;
};
+#endif
struct sun4i_spi_platdata {
u32 base_addr;
@@ -149,7 +203,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
struct sun4i_spi_priv *priv = dev_get_priv(bus);
u32 reg;
- reg = readl(&priv->regs->ctl);
+ reg = readl(&priv->regs->tctl);
reg &= ~SUN4I_CTL_CS_MASK;
reg |= SUN4I_CTL_CS(cs);
@@ -159,7 +213,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
else
reg |= SUN4I_CTL_CS_LEVEL;
- writel(reg, &priv->regs->ctl);
+ writel(reg, &priv->regs->tctl);
}
static int sun4i_spi_parse_pins(struct udevice *dev)
@@ -231,7 +285,10 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
if (pin < 0)
break;
- sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
+ if (IS_ENABLED(CONFIG_MACH_SUN50I))
+ sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
+ else
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
sunxi_gpio_set_drv(pin, drive);
sunxi_gpio_set_pull(pin, pull);
}
@@ -244,10 +301,27 @@ static inline void sun4i_spi_enable_clock(void)
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_SPI0));
+#endif
+
setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
writel((1 << 31), &ccm->spi0_clk_cfg);
}
+static inline void sun4i_spi_disable_clock(void)
+{
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
+
+ writel(0, &ccm->spi0_clk_cfg);
+ clrbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
+
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ clrbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_SPI0));
+#endif
+}
+
static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
{
struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
@@ -269,7 +343,6 @@ static int sun4i_spi_probe(struct udevice *bus)
struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
struct sun4i_spi_priv *priv = dev_get_priv(bus);
- sun4i_spi_enable_clock();
sun4i_spi_parse_pins(bus);
priv->regs = (struct sun4i_spi_regs *)(uintptr_t)plat->base_addr;
@@ -282,9 +355,17 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
{
struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
+ sun4i_spi_enable_clock();
writel(SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP |
- SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW,
+ SUN4I_CTL_SRST,
&priv->regs->ctl);
+
+ if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+ while (readl(&priv->regs->ctl) & SUN4I_CTL_SRST)
+ ;
+
+ setbits_le32(&priv->regs->tctl, SUN4I_CTL_CS_MANUAL |
+ SUN4I_CTL_CS_ACTIVE_LOW);
return 0;
}
@@ -296,6 +377,7 @@ static int sun4i_spi_release_bus(struct udevice *dev)
reg = readl(&priv->regs->ctl);
reg &= ~SUN4I_CTL_ENABLE;
writel(reg, &priv->regs->ctl);
+ sun4i_spi_disable_clock();
return 0;
}
@@ -323,10 +405,10 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
if (flags & SPI_XFER_BEGIN)
sun4i_spi_set_cs(bus, slave_plat->cs, true);
- reg = readl(&priv->regs->ctl);
+ reg = readl(&priv->regs->fifo_ctl);
/* Reset FIFOs */
- writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);
+ writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->fifo_ctl);
while (len) {
/* Setup the transfer now... */
@@ -335,16 +417,18 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
/* Setup the counters */
writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);
+ if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+ writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bctl);
/* Fill the TX FIFO */
sun4i_spi_fill_fifo(priv, nbytes);
/* Start the transfer */
- reg = readl(&priv->regs->ctl);
- writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);
+ reg = readl(&priv->regs->tctl);
+ writel(reg | SUN4I_CTL_XCH, &priv->regs->tctl);
/* Wait transfer to complete */
- ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
+ ret = wait_for_bit_le32(&priv->regs->tctl, SUN4I_CTL_XCH_MASK,
false, SUN4I_SPI_TIMEOUT_US, false);
if (ret) {
printf("ERROR: sun4i_spi: Timeout transferring data\n");
@@ -417,7 +501,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
struct sun4i_spi_priv *priv = dev_get_priv(dev);
u32 reg;
- reg = readl(&priv->regs->ctl);
+ reg = readl(&priv->regs->tctl);
reg &= ~(SUN4I_CTL_CPOL | SUN4I_CTL_CPHA);
if (mode & SPI_CPOL)
@@ -427,7 +511,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
reg |= SUN4I_CTL_CPHA;
priv->mode = mode;
- writel(reg, &priv->regs->ctl);
+ writel(reg, &priv->regs->tctl);
return 0;
}
@@ -441,7 +525,13 @@ static const struct dm_spi_ops sun4i_spi_ops = {
};
static const struct udevice_id sun4i_spi_ids[] = {
+#ifndef CONFIG_SUNXI_GEN_SUN6I
{ .compatible = "allwinner,sun4i-a10-spi" },
+#else
+ { .compatible = "allwinner,sun6i-a31-spi" },
+ { .compatible = "allwinner,sun8i-h3-spi" },
+ { .compatible = "allwinner,sun50i-a64-spi" },
+#endif
{ }
};