From 02c3e9e3b979385244df1b72bd815d881b17a790 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 18 Apr 2026 22:35:50 +0200 Subject: [PATCH 1/3] orangepizero2w: fix ethernet using sunxi-gmac driver It is patched into Armbian kernel sources, and was enabled in Linux 6.12, but has not been enabled anymore with Linux 6.18 and above. Additionally, a possible attempt to split the AC200 related patch ended up with half of sunxi-gmac dependencies missing, including such which are explicitly enabled in defconfs, including e.g. CONFIG_AC200_PHY_SUNXI. The mainline driver dwmac-sun8i, that might have been seen as possible replacement for sunxi-gmac, does not support the Ethernet chip of the Orange Pi Zero 2W expansion board yet. Signed-off-by: MichaIng --- config/kernel/linux-sunxi64-current.config | 1 + config/kernel/linux-sunxi64-edge.config | 1 + .../0201-drv-mfd-ac200-add-support.patch | 265 ------------------ .../0202-drv-net-phy-ac200-ephy-add.patch | 142 ---------- patch/kernel/archive/sunxi-6.18/series.conf | 4 +- .../0201-drv-mfd-ac200-add-support.patch | 265 ------------------ .../0202-drv-net-phy-ac200-ephy-add.patch | 142 ---------- patch/kernel/archive/sunxi-7.0/series.conf | 4 +- 8 files changed, 6 insertions(+), 818 deletions(-) delete mode 100644 patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch delete mode 100644 patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch delete mode 100644 patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch delete mode 100644 patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch diff --git a/config/kernel/linux-sunxi64-current.config b/config/kernel/linux-sunxi64-current.config index 1f2d0223e459..e36d1ffc9673 100644 --- a/config/kernel/linux-sunxi64-current.config +++ b/config/kernel/linux-sunxi64-current.config @@ -693,6 +693,7 @@ CONFIG_NETKIT=y # CONFIG_NET_VENDOR_AGERE is not set # CONFIG_NET_VENDOR_ALACRITECH is not set CONFIG_SUN4I_EMAC=m +CONFIG_SUNXI_GMAC=m # CONFIG_NET_VENDOR_ALTEON is not set # CONFIG_NET_VENDOR_AMAZON is not set # CONFIG_NET_VENDOR_AMD is not set diff --git a/config/kernel/linux-sunxi64-edge.config b/config/kernel/linux-sunxi64-edge.config index 378c80aa4946..b746a6ad9062 100644 --- a/config/kernel/linux-sunxi64-edge.config +++ b/config/kernel/linux-sunxi64-edge.config @@ -693,6 +693,7 @@ CONFIG_NETKIT=y # CONFIG_NET_VENDOR_AGERE is not set # CONFIG_NET_VENDOR_ALACRITECH is not set CONFIG_SUN4I_EMAC=m +CONFIG_SUNXI_GMAC=m # CONFIG_NET_VENDOR_ALTEON is not set # CONFIG_NET_VENDOR_AMAZON is not set # CONFIG_NET_VENDOR_AMD is not set diff --git a/patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch b/patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch deleted file mode 100644 index 1422c0b9ec5f..000000000000 --- a/patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch +++ /dev/null @@ -1,265 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Fri, 16 Aug 2019 16:38:21 +0200 -Subject: mfd: Add support for X-Powers AC200 - -The X-Powers AC200 is a mixed signal multi-purpose chip, which provides -audio DAC/ADCs, a CVBS video encoder, a 100Mbit/s Ethernet PHY and a -real-time clock. Its control registers can be accessed via I2C or -Allwinner's RSB bus. -Beside this chip being used on some older boards (for instance the Remix -Mini PC), it is quite wide spread due to its die being co-packaged on the -Allwinner H6 and H616 SoCs, which use its audio, video and PHY -functionality. - -Aside from the RTC, the other functions do not need constant -hand-holding via the I2C registers, but rather need to be configured and -enabled only once. - -We model the control side of this chip using the MFD subsystem. This -driver here just provides the parent device for the various subfunctions, -and takes care of enabling clocks and reset, but also provides the regmap, -which the respective child drivers will use. - -Signed-off-by: Jernej Skrabec -Signed-off-by: Andre Przywara ---- - drivers/mfd/Kconfig | 12 + - drivers/mfd/Makefile | 1 + - drivers/mfd/ac200.c | 190 ++++++++++ - 3 files changed, 203 insertions(+) - -diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 111111111111..222222222222 100644 ---- a/drivers/mfd/Kconfig -+++ b/drivers/mfd/Kconfig -@@ -204,6 +204,18 @@ config MFD_AC100 - This driver include only the core APIs. You have to select individual - components like codecs or RTC under the corresponding menus. - -+config MFD_AC200 -+ tristate "X-Powers AC200" -+ select MFD_CORE -+ select REGMAP_I2C -+ depends on COMMON_CLK -+ depends on I2C -+ depends on OF -+ help -+ If you say Y here you get support for the X-Powers AC200 IC. -+ This driver include only the core APIs. You have to select individual -+ components like Ethernet PHY or codec under the corresponding menus. -+ - config MFD_AXP20X - tristate - select MFD_CORE -diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/mfd/Makefile -+++ b/drivers/mfd/Makefile -@@ -149,6 +149,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o - obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o - - obj-$(CONFIG_MFD_AC100) += ac100.o -+obj-$(CONFIG_MFD_AC200) += ac200.o - obj-$(CONFIG_MFD_AXP20X) += axp20x.o - obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o - obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o -diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/mfd/ac200.c -@@ -0,0 +1,190 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * MFD core driver for X-Powers' AC200 IC -+ * -+ * The AC200 is a chip which is co-packaged with Allwinner H6 SoC and -+ * includes analog audio codec, analog TV encoder, ethernet PHY, eFuse -+ * and RTC. -+ * -+ * Copyright (c) 2019 Jernej Skrabec -+ * -+ * Based on AC100 driver with following copyrights: -+ * Copyright (2016) Chen-Yu Tsai -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct ac200_dev { -+ struct clk *clk; -+ struct regmap *regmap; -+}; -+ -+#define AC200_SYS_CONTROL 0x0002 -+#define AC200_SYS_BG_CTL 0x0050 -+ -+/* interface register (can be accessed from any page) */ -+#define AC200_TWI_REG_ADDR_H 0xFE -+ -+#define AC200_MAX_REG 0xA1F2 -+ -+static const struct regmap_range_cfg ac200_range_cfg[] = { -+ { -+ .range_max = AC200_MAX_REG, -+ .selector_reg = AC200_TWI_REG_ADDR_H, -+ .selector_mask = 0xff, -+ .selector_shift = 0, -+ .window_start = 0, -+ .window_len = 256, -+ } -+}; -+ -+static const struct regmap_config ac200_regmap_config = { -+ .name = "AC200", -+ .reg_bits = 8, -+ .reg_stride = 2, -+ .val_bits = 16, -+ .ranges = ac200_range_cfg, -+ .num_ranges = ARRAY_SIZE(ac200_range_cfg), -+ .max_register = AC200_MAX_REG, -+}; -+ -+static struct mfd_cell ac200_cells[] = { -+ { -+ .name = "ac200-codec", -+ .of_compatible = "x-powers,ac200-codec", -+ }, { -+ .name = "ac200-ephy-ctl", -+ .of_compatible = "x-powers,ac200-ephy-ctl", -+ }, -+}; -+ -+static int ac200_i2c_probe(struct i2c_client *i2c) -+{ -+ struct device *dev = &i2c->dev; -+ struct nvmem_cell *bgcell; -+ struct ac200_dev *ac200; -+ u16 *bgdata, bgval; -+ size_t bglen; -+ int ret; -+ -+ ac200 = devm_kzalloc(dev, sizeof(*ac200), GFP_KERNEL); -+ if (!ac200) -+ return -ENOMEM; -+ -+ i2c_set_clientdata(i2c, ac200); -+ -+ ac200->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(ac200->clk)) -+ return dev_err_probe(dev, PTR_ERR(ac200->clk), -+ "Can't obtain the clock\n"); -+ -+ ac200->regmap = devm_regmap_init_i2c(i2c, &ac200_regmap_config); -+ if (IS_ERR(ac200->regmap)) { -+ ret = PTR_ERR(ac200->regmap); -+ dev_err(dev, "Regmap init failed: %d\n", ret); -+ return ret; -+ } -+ -+ bgcell = devm_nvmem_cell_get(dev, "bandgap"); -+ if (IS_ERR(bgcell)) -+ return dev_err_probe(dev, PTR_ERR(bgcell), -+ "Unable to find bandgap data!\n"); -+ -+ bgdata = nvmem_cell_read(bgcell, &bglen); -+ if (IS_ERR(bgdata)) { -+ dev_err(dev, "Unable to read bandgap data!\n"); -+ return PTR_ERR(bgdata); -+ } -+ -+ if (bglen != 2) { -+ dev_err(dev, "Invalid nvmem bandgap length!\n"); -+ kfree(bgdata); -+ return -EINVAL; -+ } -+ -+ bgval = *bgdata; -+ kfree(bgdata); -+ -+ ret = clk_prepare_enable(ac200->clk); -+ if (ret) -+ return ret; -+ -+ /* -+ * There is no documentation on how long we have to wait before -+ * executing first operation. Vendor driver sleeps for 40 ms. -+ */ -+ msleep(40); -+ -+ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); -+ if (ret) -+ goto err; -+ -+ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 1); -+ if (ret) -+ goto err; -+ -+ if (bgval) { -+ /* bandgap register is not documented */ -+ ret = regmap_write(ac200->regmap, AC200_SYS_BG_CTL, -+ 0x8280 | bgval); -+ if (ret) -+ goto err; -+ } -+ -+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, ac200_cells, -+ ARRAY_SIZE(ac200_cells), NULL, 0, NULL); -+ if (ret) { -+ dev_err(dev, "Failed to add MFD devices: %d\n", ret); -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ clk_disable_unprepare(ac200->clk); -+ return ret; -+} -+ -+static void ac200_i2c_remove(struct i2c_client *i2c) -+{ -+ struct ac200_dev *ac200 = i2c_get_clientdata(i2c); -+ -+ regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); -+ -+ clk_disable_unprepare(ac200->clk); -+} -+ -+static const struct i2c_device_id ac200_ids[] = { -+ { "ac200", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, ac200_ids); -+ -+static const struct of_device_id ac200_of_match[] = { -+ { .compatible = "x-powers,ac200" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ac200_of_match); -+ -+static struct i2c_driver ac200_i2c_driver = { -+ .driver = { -+ .name = "ac200", -+ .of_match_table = of_match_ptr(ac200_of_match), -+ }, -+ .probe = ac200_i2c_probe, -+ .remove = ac200_i2c_remove, -+ .id_table = ac200_ids, -+}; -+module_i2c_driver(ac200_i2c_driver); -+ -+MODULE_DESCRIPTION("MFD core driver for AC200"); -+MODULE_AUTHOR("Jernej Skrabec "); -+MODULE_LICENSE("GPL v2"); --- -Armbian - diff --git a/patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch b/patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch deleted file mode 100644 index a36b63410d05..000000000000 --- a/patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Fri, 16 Aug 2019 16:38:57 +0200 -Subject: net: phy: Add support for AC200 EPHY - -The X-Powers AC200 mixed signal chip contains a 100Mbit/s Ethernet PHY. -While its sporting a usable default setup, and can be controlled by the -generic IEEE802.3-C22 PHY driver, the BSP sets up some extra registers, -which this driver here covers. - -Add a PHY driver matching the AC200 EPHY ID registers, and which -programs some PHY registers according to the BSP code. - -Signed-off-by: Jernej Skrabec -Signed-off-by: Andre Przywara ---- - drivers/net/phy/Kconfig | 7 + - drivers/net/phy/Makefile | 1 + - drivers/net/phy/ac200-phy.c | 82 ++++++++++ - 3 files changed, 90 insertions(+) - -diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig -index 111111111111..222222222222 100644 ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -101,6 +101,13 @@ config AIR_EN8811H_PHY - help - Currently supports the Airoha EN8811H PHY. - -+config AC200_PHY -+ tristate "AC200 EPHY" -+ depends on NVMEM -+ depends on OF -+ help -+ Fast ethernet PHY as found in X-Powers AC200 multi-function device. -+ - config AMD_PHY - tristate "AMD and Altima PHYs" - help -diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_SFP) += sfp.o - sfp-obj-$(CONFIG_SFP) += sfp-bus.o - obj-y += $(sfp-obj-y) $(sfp-obj-m) - -+obj-$(CONFIG_AC200_PHY) += ac200-phy.o - obj-$(CONFIG_ADIN_PHY) += adin.o - obj-$(CONFIG_ADIN1100_PHY) += adin1100.o - obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o -diff --git a/drivers/net/phy/ac200-phy.c b/drivers/net/phy/ac200-phy.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/net/phy/ac200-phy.c -@@ -0,0 +1,82 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/** -+ * Driver for AC200 Ethernet PHY -+ * -+ * Copyright (c) 2019 Jernej Skrabec -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define AC200_EPHY_ID 0x00441400 -+#define AC200_EPHY_ID_MASK 0x0ffffff0 -+ -+static int ac200_ephy_config_init(struct phy_device *phydev) -+{ -+ phy_write(phydev, 0x1f, 0x0100); /* Switch to Page 1 */ -+ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ -+ -+ phy_write(phydev, 0x1f, 0x0200); /* Switch to Page 2 */ -+ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ -+ -+ phy_write(phydev, 0x1f, 0x0600); /* Switch to Page 6 */ -+ phy_write(phydev, 0x14, 0x708f); /* PHYAFE TX optimization */ -+ phy_write(phydev, 0x13, 0xF000); /* PHYAFE RX optimization */ -+ phy_write(phydev, 0x15, 0x1530); -+ -+ phy_write(phydev, 0x1f, 0x0800); /* Switch to Page 8 */ -+ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ -+ -+ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ -+ phy_clear_bits(phydev, 0x17, BIT(3)); /* disable intelligent EEE */ -+ -+ /* disable 802.3az EEE */ -+ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ -+ phy_write(phydev, 0x18, 0x0000); -+ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ -+ phy_clear_bits_mmd(phydev, 0x7, 0x3c, BIT(1)); -+ -+ /* FIXME: This is probably H6 specific */ -+ phy_set_bits(phydev, 0x13, BIT(12)); -+ -+ return 0; -+} -+ -+static int ac200_ephy_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct clk *clk; -+ -+ clk = devm_clk_get_optional_enabled(dev, NULL); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to request clock\n"); -+ -+ return 0; -+} -+ -+static struct phy_driver ac200_ephy_driver[] = { -+ { -+ .phy_id = AC200_EPHY_ID, -+ .phy_id_mask = AC200_EPHY_ID_MASK, -+ .name = "Allwinner AC200 EPHY", -+ .soft_reset = genphy_soft_reset, -+ .config_init = ac200_ephy_config_init, -+ .probe = ac200_ephy_probe, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ } -+}; -+module_phy_driver(ac200_ephy_driver); -+ -+MODULE_AUTHOR("Jernej Skrabec "); -+MODULE_DESCRIPTION("AC200 Ethernet PHY driver"); -+MODULE_LICENSE("GPL"); -+ -+static const struct mdio_device_id __maybe_unused ac200_ephy_phy_tbl[] = { -+ { AC200_EPHY_ID, AC200_EPHY_ID_MASK }, -+ { } -+}; -+MODULE_DEVICE_TABLE(mdio, ac200_ephy_phy_tbl); --- -Armbian - diff --git a/patch/kernel/archive/sunxi-6.18/series.conf b/patch/kernel/archive/sunxi-6.18/series.conf index 760eac49b00d..eb58bf17c27b 100644 --- a/patch/kernel/archive/sunxi-6.18/series.conf +++ b/patch/kernel/archive/sunxi-6.18/series.conf @@ -403,8 +403,6 @@ # ################################################################################ - patches.armbian/0201-drv-mfd-ac200-add-support.patch - patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch patches.armbian/0301-arm64-dts-sun50i-h616-add-emac1-rmii-pins.patch patches.armbian/0302-arm64-dts-sun50i-h618-orangepi-zero2w-add-emac-sound.patch patches.armbian/0401-arm64-dts-sun50i-h6-add-ac200-ephy.patch @@ -535,10 +533,12 @@ patches.armbian/drv-leds-ws2812-add-h616-driver.patch patches.armbian/drv-media-dvb-frontends-si2168-fix-cmd-timeout.patch patches.armbian/drv-mfd-ac200-add-ephy-syscon.patch + patches.armbian/drv-mfd-ac200-add-support.patch patches.armbian/drv-mfd-axp20x-add-sysfs.patch patches.armbian/drv-misc-sunxi-add-addr-mgt-driver-uwe5622.patch patches.armbian/drv-mtd-nand-add-h27ubg8t2btr-nand.patch patches.armbian/drv-net-stmmac-dwmac-sun8i-add-second-emac-clock.patch + patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch patches.armbian/drv-net-usb-r8152-add-led-configuration-from-of.patch patches.armbian/drv-nvmem-sunxi-add-chipid-serial-helpers.patch patches.armbian/drv-nvmem-sunxi-add-h616-support.patch diff --git a/patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch b/patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch deleted file mode 100644 index be3cf1531d07..000000000000 --- a/patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch +++ /dev/null @@ -1,265 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Fri, 16 Aug 2019 16:38:21 +0200 -Subject: mfd: Add support for X-Powers AC200 - -The X-Powers AC200 is a mixed signal multi-purpose chip, which provides -audio DAC/ADCs, a CVBS video encoder, a 100Mbit/s Ethernet PHY and a -real-time clock. Its control registers can be accessed via I2C or -Allwinner's RSB bus. -Beside this chip being used on some older boards (for instance the Remix -Mini PC), it is quite wide spread due to its die being co-packaged on the -Allwinner H6 and H616 SoCs, which use its audio, video and PHY -functionality. - -Aside from the RTC, the other functions do not need constant -hand-holding via the I2C registers, but rather need to be configured and -enabled only once. - -We model the control side of this chip using the MFD subsystem. This -driver here just provides the parent device for the various subfunctions, -and takes care of enabling clocks and reset, but also provides the regmap, -which the respective child drivers will use. - -Signed-off-by: Jernej Skrabec -Signed-off-by: Andre Przywara ---- - drivers/mfd/Kconfig | 12 + - drivers/mfd/Makefile | 1 + - drivers/mfd/ac200.c | 190 ++++++++++ - 3 files changed, 203 insertions(+) - -diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 111111111111..222222222222 100644 ---- a/drivers/mfd/Kconfig -+++ b/drivers/mfd/Kconfig -@@ -205,6 +205,18 @@ config MFD_AC100 - This driver include only the core APIs. You have to select individual - components like codecs or RTC under the corresponding menus. - -+config MFD_AC200 -+ tristate "X-Powers AC200" -+ select MFD_CORE -+ select REGMAP_I2C -+ depends on COMMON_CLK -+ depends on I2C -+ depends on OF -+ help -+ If you say Y here you get support for the X-Powers AC200 IC. -+ This driver include only the core APIs. You have to select individual -+ components like Ethernet PHY or codec under the corresponding menus. -+ - config MFD_AXP20X - tristate - select MFD_CORE -diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/mfd/Makefile -+++ b/drivers/mfd/Makefile -@@ -151,6 +151,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o - obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o - - obj-$(CONFIG_MFD_AC100) += ac100.o -+obj-$(CONFIG_MFD_AC200) += ac200.o - obj-$(CONFIG_MFD_AXP20X) += axp20x.o - obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o - obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o -diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/mfd/ac200.c -@@ -0,0 +1,190 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * MFD core driver for X-Powers' AC200 IC -+ * -+ * The AC200 is a chip which is co-packaged with Allwinner H6 SoC and -+ * includes analog audio codec, analog TV encoder, ethernet PHY, eFuse -+ * and RTC. -+ * -+ * Copyright (c) 2019 Jernej Skrabec -+ * -+ * Based on AC100 driver with following copyrights: -+ * Copyright (2016) Chen-Yu Tsai -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct ac200_dev { -+ struct clk *clk; -+ struct regmap *regmap; -+}; -+ -+#define AC200_SYS_CONTROL 0x0002 -+#define AC200_SYS_BG_CTL 0x0050 -+ -+/* interface register (can be accessed from any page) */ -+#define AC200_TWI_REG_ADDR_H 0xFE -+ -+#define AC200_MAX_REG 0xA1F2 -+ -+static const struct regmap_range_cfg ac200_range_cfg[] = { -+ { -+ .range_max = AC200_MAX_REG, -+ .selector_reg = AC200_TWI_REG_ADDR_H, -+ .selector_mask = 0xff, -+ .selector_shift = 0, -+ .window_start = 0, -+ .window_len = 256, -+ } -+}; -+ -+static const struct regmap_config ac200_regmap_config = { -+ .name = "AC200", -+ .reg_bits = 8, -+ .reg_stride = 2, -+ .val_bits = 16, -+ .ranges = ac200_range_cfg, -+ .num_ranges = ARRAY_SIZE(ac200_range_cfg), -+ .max_register = AC200_MAX_REG, -+}; -+ -+static struct mfd_cell ac200_cells[] = { -+ { -+ .name = "ac200-codec", -+ .of_compatible = "x-powers,ac200-codec", -+ }, { -+ .name = "ac200-ephy-ctl", -+ .of_compatible = "x-powers,ac200-ephy-ctl", -+ }, -+}; -+ -+static int ac200_i2c_probe(struct i2c_client *i2c) -+{ -+ struct device *dev = &i2c->dev; -+ struct nvmem_cell *bgcell; -+ struct ac200_dev *ac200; -+ u16 *bgdata, bgval; -+ size_t bglen; -+ int ret; -+ -+ ac200 = devm_kzalloc(dev, sizeof(*ac200), GFP_KERNEL); -+ if (!ac200) -+ return -ENOMEM; -+ -+ i2c_set_clientdata(i2c, ac200); -+ -+ ac200->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(ac200->clk)) -+ return dev_err_probe(dev, PTR_ERR(ac200->clk), -+ "Can't obtain the clock\n"); -+ -+ ac200->regmap = devm_regmap_init_i2c(i2c, &ac200_regmap_config); -+ if (IS_ERR(ac200->regmap)) { -+ ret = PTR_ERR(ac200->regmap); -+ dev_err(dev, "Regmap init failed: %d\n", ret); -+ return ret; -+ } -+ -+ bgcell = devm_nvmem_cell_get(dev, "bandgap"); -+ if (IS_ERR(bgcell)) -+ return dev_err_probe(dev, PTR_ERR(bgcell), -+ "Unable to find bandgap data!\n"); -+ -+ bgdata = nvmem_cell_read(bgcell, &bglen); -+ if (IS_ERR(bgdata)) { -+ dev_err(dev, "Unable to read bandgap data!\n"); -+ return PTR_ERR(bgdata); -+ } -+ -+ if (bglen != 2) { -+ dev_err(dev, "Invalid nvmem bandgap length!\n"); -+ kfree(bgdata); -+ return -EINVAL; -+ } -+ -+ bgval = *bgdata; -+ kfree(bgdata); -+ -+ ret = clk_prepare_enable(ac200->clk); -+ if (ret) -+ return ret; -+ -+ /* -+ * There is no documentation on how long we have to wait before -+ * executing first operation. Vendor driver sleeps for 40 ms. -+ */ -+ msleep(40); -+ -+ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); -+ if (ret) -+ goto err; -+ -+ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 1); -+ if (ret) -+ goto err; -+ -+ if (bgval) { -+ /* bandgap register is not documented */ -+ ret = regmap_write(ac200->regmap, AC200_SYS_BG_CTL, -+ 0x8280 | bgval); -+ if (ret) -+ goto err; -+ } -+ -+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, ac200_cells, -+ ARRAY_SIZE(ac200_cells), NULL, 0, NULL); -+ if (ret) { -+ dev_err(dev, "Failed to add MFD devices: %d\n", ret); -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ clk_disable_unprepare(ac200->clk); -+ return ret; -+} -+ -+static void ac200_i2c_remove(struct i2c_client *i2c) -+{ -+ struct ac200_dev *ac200 = i2c_get_clientdata(i2c); -+ -+ regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); -+ -+ clk_disable_unprepare(ac200->clk); -+} -+ -+static const struct i2c_device_id ac200_ids[] = { -+ { "ac200", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, ac200_ids); -+ -+static const struct of_device_id ac200_of_match[] = { -+ { .compatible = "x-powers,ac200" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ac200_of_match); -+ -+static struct i2c_driver ac200_i2c_driver = { -+ .driver = { -+ .name = "ac200", -+ .of_match_table = of_match_ptr(ac200_of_match), -+ }, -+ .probe = ac200_i2c_probe, -+ .remove = ac200_i2c_remove, -+ .id_table = ac200_ids, -+}; -+module_i2c_driver(ac200_i2c_driver); -+ -+MODULE_DESCRIPTION("MFD core driver for AC200"); -+MODULE_AUTHOR("Jernej Skrabec "); -+MODULE_LICENSE("GPL v2"); --- -Armbian - diff --git a/patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch b/patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch deleted file mode 100644 index 1bad5dd213c2..000000000000 --- a/patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Fri, 16 Aug 2019 16:38:57 +0200 -Subject: net: phy: Add support for AC200 EPHY - -The X-Powers AC200 mixed signal chip contains a 100Mbit/s Ethernet PHY. -While its sporting a usable default setup, and can be controlled by the -generic IEEE802.3-C22 PHY driver, the BSP sets up some extra registers, -which this driver here covers. - -Add a PHY driver matching the AC200 EPHY ID registers, and which -programs some PHY registers according to the BSP code. - -Signed-off-by: Jernej Skrabec -Signed-off-by: Andre Przywara ---- - drivers/net/phy/Kconfig | 7 + - drivers/net/phy/Makefile | 1 + - drivers/net/phy/ac200-phy.c | 82 ++++++++++ - 3 files changed, 90 insertions(+) - -diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig -index 111111111111..222222222222 100644 ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -102,6 +102,13 @@ config AIR_EN8811H_PHY - help - Currently supports the Airoha EN8811H PHY. - -+config AC200_PHY -+ tristate "AC200 EPHY" -+ depends on NVMEM -+ depends on OF -+ help -+ Fast ethernet PHY as found in X-Powers AC200 multi-function device. -+ - config AMD_PHY - tristate "AMD and Altima PHYs" - help -diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_SFP) += sfp.o - sfp-obj-$(CONFIG_SFP) += sfp-bus.o - obj-y += $(sfp-obj-y) $(sfp-obj-m) - -+obj-$(CONFIG_AC200_PHY) += ac200-phy.o - obj-$(CONFIG_ADIN_PHY) += adin.o - obj-$(CONFIG_ADIN1100_PHY) += adin1100.o - obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o -diff --git a/drivers/net/phy/ac200-phy.c b/drivers/net/phy/ac200-phy.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/net/phy/ac200-phy.c -@@ -0,0 +1,82 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/** -+ * Driver for AC200 Ethernet PHY -+ * -+ * Copyright (c) 2019 Jernej Skrabec -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define AC200_EPHY_ID 0x00441400 -+#define AC200_EPHY_ID_MASK 0x0ffffff0 -+ -+static int ac200_ephy_config_init(struct phy_device *phydev) -+{ -+ phy_write(phydev, 0x1f, 0x0100); /* Switch to Page 1 */ -+ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ -+ -+ phy_write(phydev, 0x1f, 0x0200); /* Switch to Page 2 */ -+ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ -+ -+ phy_write(phydev, 0x1f, 0x0600); /* Switch to Page 6 */ -+ phy_write(phydev, 0x14, 0x708f); /* PHYAFE TX optimization */ -+ phy_write(phydev, 0x13, 0xF000); /* PHYAFE RX optimization */ -+ phy_write(phydev, 0x15, 0x1530); -+ -+ phy_write(phydev, 0x1f, 0x0800); /* Switch to Page 8 */ -+ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ -+ -+ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ -+ phy_clear_bits(phydev, 0x17, BIT(3)); /* disable intelligent EEE */ -+ -+ /* disable 802.3az EEE */ -+ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ -+ phy_write(phydev, 0x18, 0x0000); -+ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ -+ phy_clear_bits_mmd(phydev, 0x7, 0x3c, BIT(1)); -+ -+ /* FIXME: This is probably H6 specific */ -+ phy_set_bits(phydev, 0x13, BIT(12)); -+ -+ return 0; -+} -+ -+static int ac200_ephy_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct clk *clk; -+ -+ clk = devm_clk_get_optional_enabled(dev, NULL); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to request clock\n"); -+ -+ return 0; -+} -+ -+static struct phy_driver ac200_ephy_driver[] = { -+ { -+ .phy_id = AC200_EPHY_ID, -+ .phy_id_mask = AC200_EPHY_ID_MASK, -+ .name = "Allwinner AC200 EPHY", -+ .soft_reset = genphy_soft_reset, -+ .config_init = ac200_ephy_config_init, -+ .probe = ac200_ephy_probe, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ } -+}; -+module_phy_driver(ac200_ephy_driver); -+ -+MODULE_AUTHOR("Jernej Skrabec "); -+MODULE_DESCRIPTION("AC200 Ethernet PHY driver"); -+MODULE_LICENSE("GPL"); -+ -+static const struct mdio_device_id __maybe_unused ac200_ephy_phy_tbl[] = { -+ { AC200_EPHY_ID, AC200_EPHY_ID_MASK }, -+ { } -+}; -+MODULE_DEVICE_TABLE(mdio, ac200_ephy_phy_tbl); --- -Armbian - diff --git a/patch/kernel/archive/sunxi-7.0/series.conf b/patch/kernel/archive/sunxi-7.0/series.conf index c4caa78e82f6..dceadb8d30d5 100644 --- a/patch/kernel/archive/sunxi-7.0/series.conf +++ b/patch/kernel/archive/sunxi-7.0/series.conf @@ -362,8 +362,6 @@ # ################################################################################ - patches.armbian/0201-drv-mfd-ac200-add-support.patch - patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch patches.armbian/0301-arm64-dts-sun50i-h616-add-emac1-rmii-pins.patch patches.armbian/0302-arm64-dts-sun50i-h618-orangepi-zero2w-add-emac-sound.patch patches.armbian/0401-arm64-dts-sun50i-h6-add-ac200-ephy.patch @@ -494,10 +492,12 @@ patches.armbian/drv-leds-ws2812-add-h616-driver.patch patches.armbian/drv-media-dvb-frontends-si2168-fix-cmd-timeout.patch patches.armbian/drv-mfd-ac200-add-ephy-syscon.patch + patches.armbian/drv-mfd-ac200-add-support.patch patches.armbian/drv-mfd-axp20x-add-sysfs.patch patches.armbian/drv-misc-sunxi-add-addr-mgt-driver-uwe5622.patch patches.armbian/drv-mtd-nand-add-h27ubg8t2btr-nand.patch patches.armbian/drv-net-stmmac-dwmac-sun8i-add-second-emac-clock.patch + patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch patches.armbian/drv-net-usb-r8152-add-led-configuration-from-of.patch patches.armbian/drv-nvmem-sunxi-add-chipid-serial-helpers.patch patches.armbian/drv-nvmem-sunxi-add-h616-support.patch From d434ae43a3b77045c85cf60af759d1aaf188289a Mon Sep 17 00:00:00 2001 From: EvilOlaf Date: Thu, 14 May 2026 04:28:49 +0000 Subject: [PATCH 2/3] sunxi: add missing kernel options --- config/kernel/linux-sunxi64-current.config | 2 ++ config/kernel/linux-sunxi64-edge.config | 2 ++ 2 files changed, 4 insertions(+) diff --git a/config/kernel/linux-sunxi64-current.config b/config/kernel/linux-sunxi64-current.config index e36d1ffc9673..ef2f4ec34a1a 100644 --- a/config/kernel/linux-sunxi64-current.config +++ b/config/kernel/linux-sunxi64-current.config @@ -761,6 +761,7 @@ CONFIG_STMMAC_PCI=m # CONFIG_NET_VENDOR_XILINX is not set CONFIG_LED_TRIGGER_PHY=y CONFIG_AC200_PHY=m +CONFIG_AC200_PHY_SUNXI=m CONFIG_MOTORCOMM_PHY=y CONFIG_REALTEK_PHY=y CONFIG_SMSC_PHY=y @@ -1468,6 +1469,7 @@ CONFIG_MFD_SUN4I_GPADC=m CONFIG_MFD_AS3711=y CONFIG_MFD_AS3722=m CONFIG_MFD_AC200=m +CONFIG_MFD_AC200_SUNXI=m CONFIG_MFD_AXP20X_I2C=y CONFIG_MFD_AXP20X_RSB=y CONFIG_MFD_SUN6I_PRCM=y diff --git a/config/kernel/linux-sunxi64-edge.config b/config/kernel/linux-sunxi64-edge.config index b746a6ad9062..d7a69c7751b5 100644 --- a/config/kernel/linux-sunxi64-edge.config +++ b/config/kernel/linux-sunxi64-edge.config @@ -760,6 +760,7 @@ CONFIG_STMMAC_PCI=m # CONFIG_NET_VENDOR_XILINX is not set CONFIG_LED_TRIGGER_PHY=y CONFIG_AC200_PHY=m +CONFIG_AC200_PHY_SUNXI=m CONFIG_MOTORCOMM_PHY=y CONFIG_REALTEK_PHY=y CONFIG_SMSC_PHY=y @@ -1465,6 +1466,7 @@ CONFIG_MFD_SUN4I_GPADC=m CONFIG_MFD_AS3711=y CONFIG_MFD_AS3722=m CONFIG_MFD_AC200=m +CONFIG_MFD_AC200_SUNXI=m CONFIG_MFD_AXP20X_I2C=y CONFIG_MFD_AXP20X_RSB=y CONFIG_MFD_SUN6I_PRCM=y From 913894b939a97263dbf2421660f2acb30bc08281 Mon Sep 17 00:00:00 2001 From: EvilOlaf Date: Thu, 14 May 2026 09:04:11 +0000 Subject: [PATCH 3/3] revert some of the previous changes and relax dependency of SUNXI_GMAC --- .../0201-drv-mfd-ac200-add-support.patch | 265 ++++++++++++++++++ .../0202-drv-net-phy-ac200-ephy-add.patch | 142 ++++++++++ .../drv-net-stmmac-sun8i-add-h618-emac.patch | 2 +- patch/kernel/archive/sunxi-6.18/series.conf | 2 + .../0201-drv-mfd-ac200-add-support.patch | 265 ++++++++++++++++++ .../0202-drv-net-phy-ac200-ephy-add.patch | 142 ++++++++++ .../drv-net-stmmac-sun8i-add-h618-emac.patch | 2 +- patch/kernel/archive/sunxi-7.0/series.conf | 2 + 8 files changed, 820 insertions(+), 2 deletions(-) create mode 100644 patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch create mode 100644 patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch create mode 100644 patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch create mode 100644 patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch diff --git a/patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch b/patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch new file mode 100644 index 000000000000..1422c0b9ec5f --- /dev/null +++ b/patch/kernel/archive/sunxi-6.18/patches.armbian/0201-drv-mfd-ac200-add-support.patch @@ -0,0 +1,265 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:21 +0200 +Subject: mfd: Add support for X-Powers AC200 + +The X-Powers AC200 is a mixed signal multi-purpose chip, which provides +audio DAC/ADCs, a CVBS video encoder, a 100Mbit/s Ethernet PHY and a +real-time clock. Its control registers can be accessed via I2C or +Allwinner's RSB bus. +Beside this chip being used on some older boards (for instance the Remix +Mini PC), it is quite wide spread due to its die being co-packaged on the +Allwinner H6 and H616 SoCs, which use its audio, video and PHY +functionality. + +Aside from the RTC, the other functions do not need constant +hand-holding via the I2C registers, but rather need to be configured and +enabled only once. + +We model the control side of this chip using the MFD subsystem. This +driver here just provides the parent device for the various subfunctions, +and takes care of enabling clocks and reset, but also provides the regmap, +which the respective child drivers will use. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Andre Przywara +--- + drivers/mfd/Kconfig | 12 + + drivers/mfd/Makefile | 1 + + drivers/mfd/ac200.c | 190 ++++++++++ + 3 files changed, 203 insertions(+) + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -204,6 +204,18 @@ config MFD_AC100 + This driver include only the core APIs. You have to select individual + components like codecs or RTC under the corresponding menus. + ++config MFD_AC200 ++ tristate "X-Powers AC200" ++ select MFD_CORE ++ select REGMAP_I2C ++ depends on COMMON_CLK ++ depends on I2C ++ depends on OF ++ help ++ If you say Y here you get support for the X-Powers AC200 IC. ++ This driver include only the core APIs. You have to select individual ++ components like Ethernet PHY or codec under the corresponding menus. ++ + config MFD_AXP20X + tristate + select MFD_CORE +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -149,6 +149,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o + obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o + + obj-$(CONFIG_MFD_AC100) += ac100.o ++obj-$(CONFIG_MFD_AC200) += ac200.o + obj-$(CONFIG_MFD_AXP20X) += axp20x.o + obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o + obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o +diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/mfd/ac200.c +@@ -0,0 +1,190 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * MFD core driver for X-Powers' AC200 IC ++ * ++ * The AC200 is a chip which is co-packaged with Allwinner H6 SoC and ++ * includes analog audio codec, analog TV encoder, ethernet PHY, eFuse ++ * and RTC. ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ * ++ * Based on AC100 driver with following copyrights: ++ * Copyright (2016) Chen-Yu Tsai ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ac200_dev { ++ struct clk *clk; ++ struct regmap *regmap; ++}; ++ ++#define AC200_SYS_CONTROL 0x0002 ++#define AC200_SYS_BG_CTL 0x0050 ++ ++/* interface register (can be accessed from any page) */ ++#define AC200_TWI_REG_ADDR_H 0xFE ++ ++#define AC200_MAX_REG 0xA1F2 ++ ++static const struct regmap_range_cfg ac200_range_cfg[] = { ++ { ++ .range_max = AC200_MAX_REG, ++ .selector_reg = AC200_TWI_REG_ADDR_H, ++ .selector_mask = 0xff, ++ .selector_shift = 0, ++ .window_start = 0, ++ .window_len = 256, ++ } ++}; ++ ++static const struct regmap_config ac200_regmap_config = { ++ .name = "AC200", ++ .reg_bits = 8, ++ .reg_stride = 2, ++ .val_bits = 16, ++ .ranges = ac200_range_cfg, ++ .num_ranges = ARRAY_SIZE(ac200_range_cfg), ++ .max_register = AC200_MAX_REG, ++}; ++ ++static struct mfd_cell ac200_cells[] = { ++ { ++ .name = "ac200-codec", ++ .of_compatible = "x-powers,ac200-codec", ++ }, { ++ .name = "ac200-ephy-ctl", ++ .of_compatible = "x-powers,ac200-ephy-ctl", ++ }, ++}; ++ ++static int ac200_i2c_probe(struct i2c_client *i2c) ++{ ++ struct device *dev = &i2c->dev; ++ struct nvmem_cell *bgcell; ++ struct ac200_dev *ac200; ++ u16 *bgdata, bgval; ++ size_t bglen; ++ int ret; ++ ++ ac200 = devm_kzalloc(dev, sizeof(*ac200), GFP_KERNEL); ++ if (!ac200) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(i2c, ac200); ++ ++ ac200->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(ac200->clk)) ++ return dev_err_probe(dev, PTR_ERR(ac200->clk), ++ "Can't obtain the clock\n"); ++ ++ ac200->regmap = devm_regmap_init_i2c(i2c, &ac200_regmap_config); ++ if (IS_ERR(ac200->regmap)) { ++ ret = PTR_ERR(ac200->regmap); ++ dev_err(dev, "Regmap init failed: %d\n", ret); ++ return ret; ++ } ++ ++ bgcell = devm_nvmem_cell_get(dev, "bandgap"); ++ if (IS_ERR(bgcell)) ++ return dev_err_probe(dev, PTR_ERR(bgcell), ++ "Unable to find bandgap data!\n"); ++ ++ bgdata = nvmem_cell_read(bgcell, &bglen); ++ if (IS_ERR(bgdata)) { ++ dev_err(dev, "Unable to read bandgap data!\n"); ++ return PTR_ERR(bgdata); ++ } ++ ++ if (bglen != 2) { ++ dev_err(dev, "Invalid nvmem bandgap length!\n"); ++ kfree(bgdata); ++ return -EINVAL; ++ } ++ ++ bgval = *bgdata; ++ kfree(bgdata); ++ ++ ret = clk_prepare_enable(ac200->clk); ++ if (ret) ++ return ret; ++ ++ /* ++ * There is no documentation on how long we have to wait before ++ * executing first operation. Vendor driver sleeps for 40 ms. ++ */ ++ msleep(40); ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ if (ret) ++ goto err; ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 1); ++ if (ret) ++ goto err; ++ ++ if (bgval) { ++ /* bandgap register is not documented */ ++ ret = regmap_write(ac200->regmap, AC200_SYS_BG_CTL, ++ 0x8280 | bgval); ++ if (ret) ++ goto err; ++ } ++ ++ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, ac200_cells, ++ ARRAY_SIZE(ac200_cells), NULL, 0, NULL); ++ if (ret) { ++ dev_err(dev, "Failed to add MFD devices: %d\n", ret); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ clk_disable_unprepare(ac200->clk); ++ return ret; ++} ++ ++static void ac200_i2c_remove(struct i2c_client *i2c) ++{ ++ struct ac200_dev *ac200 = i2c_get_clientdata(i2c); ++ ++ regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ ++ clk_disable_unprepare(ac200->clk); ++} ++ ++static const struct i2c_device_id ac200_ids[] = { ++ { "ac200", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ac200_ids); ++ ++static const struct of_device_id ac200_of_match[] = { ++ { .compatible = "x-powers,ac200" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ac200_of_match); ++ ++static struct i2c_driver ac200_i2c_driver = { ++ .driver = { ++ .name = "ac200", ++ .of_match_table = of_match_ptr(ac200_of_match), ++ }, ++ .probe = ac200_i2c_probe, ++ .remove = ac200_i2c_remove, ++ .id_table = ac200_ids, ++}; ++module_i2c_driver(ac200_i2c_driver); ++ ++MODULE_DESCRIPTION("MFD core driver for AC200"); ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_LICENSE("GPL v2"); +-- +Armbian + diff --git a/patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch b/patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch new file mode 100644 index 000000000000..a36b63410d05 --- /dev/null +++ b/patch/kernel/archive/sunxi-6.18/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:57 +0200 +Subject: net: phy: Add support for AC200 EPHY + +The X-Powers AC200 mixed signal chip contains a 100Mbit/s Ethernet PHY. +While its sporting a usable default setup, and can be controlled by the +generic IEEE802.3-C22 PHY driver, the BSP sets up some extra registers, +which this driver here covers. + +Add a PHY driver matching the AC200 EPHY ID registers, and which +programs some PHY registers according to the BSP code. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Andre Przywara +--- + drivers/net/phy/Kconfig | 7 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/ac200-phy.c | 82 ++++++++++ + 3 files changed, 90 insertions(+) + +diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -101,6 +101,13 @@ config AIR_EN8811H_PHY + help + Currently supports the Airoha EN8811H PHY. + ++config AC200_PHY ++ tristate "AC200 EPHY" ++ depends on NVMEM ++ depends on OF ++ help ++ Fast ethernet PHY as found in X-Powers AC200 multi-function device. ++ + config AMD_PHY + tristate "AMD and Altima PHYs" + help +diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -27,6 +27,7 @@ obj-$(CONFIG_SFP) += sfp.o + sfp-obj-$(CONFIG_SFP) += sfp-bus.o + obj-y += $(sfp-obj-y) $(sfp-obj-m) + ++obj-$(CONFIG_AC200_PHY) += ac200-phy.o + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o + obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o +diff --git a/drivers/net/phy/ac200-phy.c b/drivers/net/phy/ac200-phy.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/phy/ac200-phy.c +@@ -0,0 +1,82 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/** ++ * Driver for AC200 Ethernet PHY ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#define AC200_EPHY_ID 0x00441400 ++#define AC200_EPHY_ID_MASK 0x0ffffff0 ++ ++static int ac200_ephy_config_init(struct phy_device *phydev) ++{ ++ phy_write(phydev, 0x1f, 0x0100); /* Switch to Page 1 */ ++ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ ++ ++ phy_write(phydev, 0x1f, 0x0200); /* Switch to Page 2 */ ++ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0600); /* Switch to Page 6 */ ++ phy_write(phydev, 0x14, 0x708f); /* PHYAFE TX optimization */ ++ phy_write(phydev, 0x13, 0xF000); /* PHYAFE RX optimization */ ++ phy_write(phydev, 0x15, 0x1530); ++ ++ phy_write(phydev, 0x1f, 0x0800); /* Switch to Page 8 */ ++ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ ++ phy_clear_bits(phydev, 0x17, BIT(3)); /* disable intelligent EEE */ ++ ++ /* disable 802.3az EEE */ ++ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ ++ phy_write(phydev, 0x18, 0x0000); ++ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ ++ phy_clear_bits_mmd(phydev, 0x7, 0x3c, BIT(1)); ++ ++ /* FIXME: This is probably H6 specific */ ++ phy_set_bits(phydev, 0x13, BIT(12)); ++ ++ return 0; ++} ++ ++static int ac200_ephy_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct clk *clk; ++ ++ clk = devm_clk_get_optional_enabled(dev, NULL); ++ if (IS_ERR(clk)) ++ return dev_err_probe(dev, PTR_ERR(clk), ++ "Failed to request clock\n"); ++ ++ return 0; ++} ++ ++static struct phy_driver ac200_ephy_driver[] = { ++ { ++ .phy_id = AC200_EPHY_ID, ++ .phy_id_mask = AC200_EPHY_ID_MASK, ++ .name = "Allwinner AC200 EPHY", ++ .soft_reset = genphy_soft_reset, ++ .config_init = ac200_ephy_config_init, ++ .probe = ac200_ephy_probe, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ } ++}; ++module_phy_driver(ac200_ephy_driver); ++ ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_DESCRIPTION("AC200 Ethernet PHY driver"); ++MODULE_LICENSE("GPL"); ++ ++static const struct mdio_device_id __maybe_unused ac200_ephy_phy_tbl[] = { ++ { AC200_EPHY_ID, AC200_EPHY_ID_MASK }, ++ { } ++}; ++MODULE_DEVICE_TABLE(mdio, ac200_ephy_phy_tbl); +-- +Armbian + diff --git a/patch/kernel/archive/sunxi-6.18/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch b/patch/kernel/archive/sunxi-6.18/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch index ec75c854177b..b4884a183e01 100644 --- a/patch/kernel/archive/sunxi-6.18/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch +++ b/patch/kernel/archive/sunxi-6.18/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch @@ -82,7 +82,7 @@ index 111111111111..222222222222 100644 + tristate "Allwinner GMAC support" + depends on ARCH_SUNXI + depends on OF -+ depends on AC200_PHY_SUNXI ++ select PHYLIB + select CRC32 + select MII + diff --git a/patch/kernel/archive/sunxi-6.18/series.conf b/patch/kernel/archive/sunxi-6.18/series.conf index eb58bf17c27b..c8497a33e577 100644 --- a/patch/kernel/archive/sunxi-6.18/series.conf +++ b/patch/kernel/archive/sunxi-6.18/series.conf @@ -403,6 +403,8 @@ # ################################################################################ + patches.armbian/0201-drv-mfd-ac200-add-support.patch + patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch patches.armbian/0301-arm64-dts-sun50i-h616-add-emac1-rmii-pins.patch patches.armbian/0302-arm64-dts-sun50i-h618-orangepi-zero2w-add-emac-sound.patch patches.armbian/0401-arm64-dts-sun50i-h6-add-ac200-ephy.patch diff --git a/patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch b/patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch new file mode 100644 index 000000000000..be3cf1531d07 --- /dev/null +++ b/patch/kernel/archive/sunxi-7.0/patches.armbian/0201-drv-mfd-ac200-add-support.patch @@ -0,0 +1,265 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:21 +0200 +Subject: mfd: Add support for X-Powers AC200 + +The X-Powers AC200 is a mixed signal multi-purpose chip, which provides +audio DAC/ADCs, a CVBS video encoder, a 100Mbit/s Ethernet PHY and a +real-time clock. Its control registers can be accessed via I2C or +Allwinner's RSB bus. +Beside this chip being used on some older boards (for instance the Remix +Mini PC), it is quite wide spread due to its die being co-packaged on the +Allwinner H6 and H616 SoCs, which use its audio, video and PHY +functionality. + +Aside from the RTC, the other functions do not need constant +hand-holding via the I2C registers, but rather need to be configured and +enabled only once. + +We model the control side of this chip using the MFD subsystem. This +driver here just provides the parent device for the various subfunctions, +and takes care of enabling clocks and reset, but also provides the regmap, +which the respective child drivers will use. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Andre Przywara +--- + drivers/mfd/Kconfig | 12 + + drivers/mfd/Makefile | 1 + + drivers/mfd/ac200.c | 190 ++++++++++ + 3 files changed, 203 insertions(+) + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -205,6 +205,18 @@ config MFD_AC100 + This driver include only the core APIs. You have to select individual + components like codecs or RTC under the corresponding menus. + ++config MFD_AC200 ++ tristate "X-Powers AC200" ++ select MFD_CORE ++ select REGMAP_I2C ++ depends on COMMON_CLK ++ depends on I2C ++ depends on OF ++ help ++ If you say Y here you get support for the X-Powers AC200 IC. ++ This driver include only the core APIs. You have to select individual ++ components like Ethernet PHY or codec under the corresponding menus. ++ + config MFD_AXP20X + tristate + select MFD_CORE +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -151,6 +151,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o + obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o + + obj-$(CONFIG_MFD_AC100) += ac100.o ++obj-$(CONFIG_MFD_AC200) += ac200.o + obj-$(CONFIG_MFD_AXP20X) += axp20x.o + obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o + obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o +diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/mfd/ac200.c +@@ -0,0 +1,190 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * MFD core driver for X-Powers' AC200 IC ++ * ++ * The AC200 is a chip which is co-packaged with Allwinner H6 SoC and ++ * includes analog audio codec, analog TV encoder, ethernet PHY, eFuse ++ * and RTC. ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ * ++ * Based on AC100 driver with following copyrights: ++ * Copyright (2016) Chen-Yu Tsai ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ac200_dev { ++ struct clk *clk; ++ struct regmap *regmap; ++}; ++ ++#define AC200_SYS_CONTROL 0x0002 ++#define AC200_SYS_BG_CTL 0x0050 ++ ++/* interface register (can be accessed from any page) */ ++#define AC200_TWI_REG_ADDR_H 0xFE ++ ++#define AC200_MAX_REG 0xA1F2 ++ ++static const struct regmap_range_cfg ac200_range_cfg[] = { ++ { ++ .range_max = AC200_MAX_REG, ++ .selector_reg = AC200_TWI_REG_ADDR_H, ++ .selector_mask = 0xff, ++ .selector_shift = 0, ++ .window_start = 0, ++ .window_len = 256, ++ } ++}; ++ ++static const struct regmap_config ac200_regmap_config = { ++ .name = "AC200", ++ .reg_bits = 8, ++ .reg_stride = 2, ++ .val_bits = 16, ++ .ranges = ac200_range_cfg, ++ .num_ranges = ARRAY_SIZE(ac200_range_cfg), ++ .max_register = AC200_MAX_REG, ++}; ++ ++static struct mfd_cell ac200_cells[] = { ++ { ++ .name = "ac200-codec", ++ .of_compatible = "x-powers,ac200-codec", ++ }, { ++ .name = "ac200-ephy-ctl", ++ .of_compatible = "x-powers,ac200-ephy-ctl", ++ }, ++}; ++ ++static int ac200_i2c_probe(struct i2c_client *i2c) ++{ ++ struct device *dev = &i2c->dev; ++ struct nvmem_cell *bgcell; ++ struct ac200_dev *ac200; ++ u16 *bgdata, bgval; ++ size_t bglen; ++ int ret; ++ ++ ac200 = devm_kzalloc(dev, sizeof(*ac200), GFP_KERNEL); ++ if (!ac200) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(i2c, ac200); ++ ++ ac200->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(ac200->clk)) ++ return dev_err_probe(dev, PTR_ERR(ac200->clk), ++ "Can't obtain the clock\n"); ++ ++ ac200->regmap = devm_regmap_init_i2c(i2c, &ac200_regmap_config); ++ if (IS_ERR(ac200->regmap)) { ++ ret = PTR_ERR(ac200->regmap); ++ dev_err(dev, "Regmap init failed: %d\n", ret); ++ return ret; ++ } ++ ++ bgcell = devm_nvmem_cell_get(dev, "bandgap"); ++ if (IS_ERR(bgcell)) ++ return dev_err_probe(dev, PTR_ERR(bgcell), ++ "Unable to find bandgap data!\n"); ++ ++ bgdata = nvmem_cell_read(bgcell, &bglen); ++ if (IS_ERR(bgdata)) { ++ dev_err(dev, "Unable to read bandgap data!\n"); ++ return PTR_ERR(bgdata); ++ } ++ ++ if (bglen != 2) { ++ dev_err(dev, "Invalid nvmem bandgap length!\n"); ++ kfree(bgdata); ++ return -EINVAL; ++ } ++ ++ bgval = *bgdata; ++ kfree(bgdata); ++ ++ ret = clk_prepare_enable(ac200->clk); ++ if (ret) ++ return ret; ++ ++ /* ++ * There is no documentation on how long we have to wait before ++ * executing first operation. Vendor driver sleeps for 40 ms. ++ */ ++ msleep(40); ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ if (ret) ++ goto err; ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 1); ++ if (ret) ++ goto err; ++ ++ if (bgval) { ++ /* bandgap register is not documented */ ++ ret = regmap_write(ac200->regmap, AC200_SYS_BG_CTL, ++ 0x8280 | bgval); ++ if (ret) ++ goto err; ++ } ++ ++ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, ac200_cells, ++ ARRAY_SIZE(ac200_cells), NULL, 0, NULL); ++ if (ret) { ++ dev_err(dev, "Failed to add MFD devices: %d\n", ret); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ clk_disable_unprepare(ac200->clk); ++ return ret; ++} ++ ++static void ac200_i2c_remove(struct i2c_client *i2c) ++{ ++ struct ac200_dev *ac200 = i2c_get_clientdata(i2c); ++ ++ regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ ++ clk_disable_unprepare(ac200->clk); ++} ++ ++static const struct i2c_device_id ac200_ids[] = { ++ { "ac200", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ac200_ids); ++ ++static const struct of_device_id ac200_of_match[] = { ++ { .compatible = "x-powers,ac200" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ac200_of_match); ++ ++static struct i2c_driver ac200_i2c_driver = { ++ .driver = { ++ .name = "ac200", ++ .of_match_table = of_match_ptr(ac200_of_match), ++ }, ++ .probe = ac200_i2c_probe, ++ .remove = ac200_i2c_remove, ++ .id_table = ac200_ids, ++}; ++module_i2c_driver(ac200_i2c_driver); ++ ++MODULE_DESCRIPTION("MFD core driver for AC200"); ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_LICENSE("GPL v2"); +-- +Armbian + diff --git a/patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch b/patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch new file mode 100644 index 000000000000..1bad5dd213c2 --- /dev/null +++ b/patch/kernel/archive/sunxi-7.0/patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:57 +0200 +Subject: net: phy: Add support for AC200 EPHY + +The X-Powers AC200 mixed signal chip contains a 100Mbit/s Ethernet PHY. +While its sporting a usable default setup, and can be controlled by the +generic IEEE802.3-C22 PHY driver, the BSP sets up some extra registers, +which this driver here covers. + +Add a PHY driver matching the AC200 EPHY ID registers, and which +programs some PHY registers according to the BSP code. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Andre Przywara +--- + drivers/net/phy/Kconfig | 7 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/ac200-phy.c | 82 ++++++++++ + 3 files changed, 90 insertions(+) + +diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -102,6 +102,13 @@ config AIR_EN8811H_PHY + help + Currently supports the Airoha EN8811H PHY. + ++config AC200_PHY ++ tristate "AC200 EPHY" ++ depends on NVMEM ++ depends on OF ++ help ++ Fast ethernet PHY as found in X-Powers AC200 multi-function device. ++ + config AMD_PHY + tristate "AMD and Altima PHYs" + help +diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -27,6 +27,7 @@ obj-$(CONFIG_SFP) += sfp.o + sfp-obj-$(CONFIG_SFP) += sfp-bus.o + obj-y += $(sfp-obj-y) $(sfp-obj-m) + ++obj-$(CONFIG_AC200_PHY) += ac200-phy.o + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o + obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o +diff --git a/drivers/net/phy/ac200-phy.c b/drivers/net/phy/ac200-phy.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/phy/ac200-phy.c +@@ -0,0 +1,82 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/** ++ * Driver for AC200 Ethernet PHY ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#define AC200_EPHY_ID 0x00441400 ++#define AC200_EPHY_ID_MASK 0x0ffffff0 ++ ++static int ac200_ephy_config_init(struct phy_device *phydev) ++{ ++ phy_write(phydev, 0x1f, 0x0100); /* Switch to Page 1 */ ++ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ ++ ++ phy_write(phydev, 0x1f, 0x0200); /* Switch to Page 2 */ ++ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0600); /* Switch to Page 6 */ ++ phy_write(phydev, 0x14, 0x708f); /* PHYAFE TX optimization */ ++ phy_write(phydev, 0x13, 0xF000); /* PHYAFE RX optimization */ ++ phy_write(phydev, 0x15, 0x1530); ++ ++ phy_write(phydev, 0x1f, 0x0800); /* Switch to Page 8 */ ++ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ ++ phy_clear_bits(phydev, 0x17, BIT(3)); /* disable intelligent EEE */ ++ ++ /* disable 802.3az EEE */ ++ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ ++ phy_write(phydev, 0x18, 0x0000); ++ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ ++ phy_clear_bits_mmd(phydev, 0x7, 0x3c, BIT(1)); ++ ++ /* FIXME: This is probably H6 specific */ ++ phy_set_bits(phydev, 0x13, BIT(12)); ++ ++ return 0; ++} ++ ++static int ac200_ephy_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct clk *clk; ++ ++ clk = devm_clk_get_optional_enabled(dev, NULL); ++ if (IS_ERR(clk)) ++ return dev_err_probe(dev, PTR_ERR(clk), ++ "Failed to request clock\n"); ++ ++ return 0; ++} ++ ++static struct phy_driver ac200_ephy_driver[] = { ++ { ++ .phy_id = AC200_EPHY_ID, ++ .phy_id_mask = AC200_EPHY_ID_MASK, ++ .name = "Allwinner AC200 EPHY", ++ .soft_reset = genphy_soft_reset, ++ .config_init = ac200_ephy_config_init, ++ .probe = ac200_ephy_probe, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ } ++}; ++module_phy_driver(ac200_ephy_driver); ++ ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_DESCRIPTION("AC200 Ethernet PHY driver"); ++MODULE_LICENSE("GPL"); ++ ++static const struct mdio_device_id __maybe_unused ac200_ephy_phy_tbl[] = { ++ { AC200_EPHY_ID, AC200_EPHY_ID_MASK }, ++ { } ++}; ++MODULE_DEVICE_TABLE(mdio, ac200_ephy_phy_tbl); +-- +Armbian + diff --git a/patch/kernel/archive/sunxi-7.0/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch b/patch/kernel/archive/sunxi-7.0/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch index ec75c854177b..b4884a183e01 100644 --- a/patch/kernel/archive/sunxi-7.0/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch +++ b/patch/kernel/archive/sunxi-7.0/patches.armbian/drv-net-stmmac-sun8i-add-h618-emac.patch @@ -82,7 +82,7 @@ index 111111111111..222222222222 100644 + tristate "Allwinner GMAC support" + depends on ARCH_SUNXI + depends on OF -+ depends on AC200_PHY_SUNXI ++ select PHYLIB + select CRC32 + select MII + diff --git a/patch/kernel/archive/sunxi-7.0/series.conf b/patch/kernel/archive/sunxi-7.0/series.conf index dceadb8d30d5..70d1a109a203 100644 --- a/patch/kernel/archive/sunxi-7.0/series.conf +++ b/patch/kernel/archive/sunxi-7.0/series.conf @@ -362,6 +362,8 @@ # ################################################################################ + patches.armbian/0201-drv-mfd-ac200-add-support.patch + patches.armbian/0202-drv-net-phy-ac200-ephy-add.patch patches.armbian/0301-arm64-dts-sun50i-h616-add-emac1-rmii-pins.patch patches.armbian/0302-arm64-dts-sun50i-h618-orangepi-zero2w-add-emac-sound.patch patches.armbian/0401-arm64-dts-sun50i-h6-add-ac200-ephy.patch