uefi: drop old patchsets (6.6, 6.9, 7.0) for x86/arm64/loong64

This commit is contained in:
Ricardo Pardini
2026-06-25 08:08:09 +02:00
committed by Igor
parent 3f55be6bfb
commit 0c022176fd
36 changed files with 0 additions and 17312 deletions
@@ -1,56 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Catalin Marinas <catalin.marinas@arm.com>
Date: Wed, 10 Apr 2024 08:25:37 -0400
Subject: arm64: swiotlb: Reduce the default size if no ZONE_DMA bouncing
needed
With CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC enabled, the arm64 kernel still
allocates the default SWIOTLB buffer (64MB) even if ZONE_DMA is disabled
or all the RAM fits into this zone. However, this potentially wastes a
non-negligible amount of memory on platforms with little RAM.
Reduce the SWIOTLB size to 1MB per 1GB of RAM if only needed for
kmalloc() buffer bouncing.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Suggested-by: Ross Burton <ross.burton@arm.com>
Cc: Ross Burton <ross.burton@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
---
arch/arm64/mm/init.c | 11 +++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 111111111111..222222222222 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -16,6 +16,7 @@
#include <linux/nodemask.h>
#include <linux/initrd.h>
#include <linux/gfp.h>
+#include <linux/math.h>
#include <linux/memblock.h>
#include <linux/sort.h>
#include <linux/of.h>
@@ -493,8 +494,16 @@ void __init mem_init(void)
{
bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit);
- if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC))
+ if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb) {
+ /*
+ * If no bouncing needed for ZONE_DMA, reduce the swiotlb
+ * buffer for kmalloc() bouncing to 1MB per 1GB of RAM.
+ */
+ unsigned long size =
+ DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+ swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
swiotlb = true;
+ }
swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
--
Armbian
@@ -1,77 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kevin Schmidt <kevin.patrick.schmidt@googlemail.com>
Date: Thu, 31 Aug 2023 11:41:14 +0200
Subject: [ARCHEOLOGY] Add board: HiKey960
> X-Git-Archeology: - Revision d8200e5c383c1c77569596bfd2b8886ef8258c3f: https://github.com/armbian/build/commit/d8200e5c383c1c77569596bfd2b8886ef8258c3f
> X-Git-Archeology: Date: Thu, 31 Aug 2023 11:41:14 +0200
> X-Git-Archeology: From: Kevin Schmidt <kevin.patrick.schmidt@googlemail.com>
> X-Git-Archeology: Subject: Add board: HiKey960
> X-Git-Archeology:
---
arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 35 +++++++++-
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -197,6 +197,37 @@ optee {
method = "smc";
};
};
+
+ usb_hub_vdd: usb_hub_vdd {
+ compatible = "regulator-fixed";
+ regulator-name = "hub-vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio5 6 0>;
+ enable-active-high;
+ };
+
+ usb-hub {
+ compatible = "hisilicon,usbhub";
+ typec-vbus-gpios = <&gpio25 2 GPIO_ACTIVE_HIGH>;
+ otg-switch-gpios = <&gpio25 6 GPIO_ACTIVE_HIGH>;
+ hub-vdd-supply = <&usb_hub_vdd>;
+ usb-role-switch;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hikey_usb_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&dwc3_role_switch>;
+ };
+ hikey_usb_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&rt1711h_ep>;
+ };
+ };
+ };
};
/*
@@ -564,7 +595,7 @@ port {
rt1711h_ep: endpoint@0 {
reg = <0>;
- remote-endpoint = <&dwc3_role_switch>;
+ remote-endpoint = <&hikey_usb_ep1>;
};
};
};
@@ -686,7 +717,7 @@ port {
#size-cells = <0>;
dwc3_role_switch: endpoint@0 {
reg = <0>;
- remote-endpoint = <&rt1711h_ep>;
+ remote-endpoint = <&hikey_usb_ep0>;
};
dwc3_ss: endpoint@1 {
--
Armbian
@@ -1,702 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Thu, 4 Aug 2022 21:49:10 +0200
Subject: Phytium onboard ethernet drivers for 6.x
My board has two eths; only eth1 has an actual PHY and works.
From https://gitee.com/atzlinux/atzlinux-kernel/tree/master/debian/patch
rpardini hammered:
- small api change in upstream around 5.19
- hand-merged for 6.5
- use `.remove_new` due to "net: stmmac: Make stmmac_pltfr_remove() return void"
- hand-merged for 6.6:
- OXNAS is no more, Makefile lost reference, fix manually
- Remove Kconfig deps from Feiteng stuff not in mainline
- Default Kconfig to module
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 +
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 19 +
drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c | 222 ++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 254 +++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | 2 +
drivers/net/phy/at803x.c | 23 +
8 files changed, 531 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -121,6 +121,16 @@ config DWMAC_MESON
the stmmac device driver. This driver is used for Meson6,
Meson8, Meson8b and GXBB SoCs.
+config DWMAC_PHYTIUM
+ tristate "Phytium DWMAC support"
+ default m
+ depends on ACPI
+ help
+ Support for Ethernet controllers on Phytium SoCs.
+
+ This selects the Phytium DWMAC glue layer support for the stmmac
+ device driver.
+
config DWMAC_QCOM_ETHQOS
tristate "Qualcomm ETHQOS support"
default ARCH_QCOM
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
+obj-$(CONFIG_DWMAC_PHYTIUM) += dwmac-phytium.o
obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -9,6 +9,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -32,6 +33,12 @@ static int dwmac_generic_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
+ } else if (has_acpi_companion(&pdev->dev)) {
+ plat_dat = stmmac_probe_config_acpi(pdev, stmmac_res.mac);
+ if (!plat_dat) {
+ dev_err(&pdev->dev, "acpi configuration failed\n");
+ return -EINVAL;
+ }
} else {
plat_dat = dev_get_platdata(&pdev->dev);
if (!plat_dat) {
@@ -75,6 +82,17 @@ static const struct of_device_id dwmac_generic_match[] = {
};
MODULE_DEVICE_TABLE(of, dwmac_generic_match);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id dwmac_acpi_ids[] = {
+ { .id = "PHYT0004" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(acpi, dwmac_acpi_ids);
+#else
+#define dwmac_acpi_ids NULL
+#endif
+
static struct platform_driver dwmac_generic_driver = {
.probe = dwmac_generic_probe,
.remove_new = stmmac_pltfr_remove,
@@ -82,6 +100,7 @@ static struct platform_driver dwmac_generic_driver = {
.name = STMMAC_RESOURCE_NAME,
.pm = &stmmac_pltfr_pm_ops,
.of_match_table = dwmac_generic_match,
+ .acpi_match_table = ACPI_PTR(dwmac_acpi_ids),
},
};
module_platform_driver(dwmac_generic_driver);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Phytium DWMAC platform glue driver
+ *
+ * Copyright (C) 2022 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "stmmac.h"
+#include "stmmac_platform.h"
+
+/**
+ * Acquire Phytium DWMAC resources from ACPI
+ */
+int dwmac_phytium_get_resources(struct platform_device *pdev,
+ struct stmmac_resources *stmmac_res)
+{
+ memset(stmmac_res, 0, sizeof(*stmmac_res));
+
+ stmmac_res->irq = platform_get_irq(pdev, 0);
+ if (stmmac_res->irq < 0)
+ return stmmac_res->irq;
+
+ stmmac_res->addr = devm_platform_ioremap_resource(pdev, 0);
+ stmmac_res->wol_irq = stmmac_res->irq;
+ stmmac_res->lpi_irq = -ENOENT;
+
+ return PTR_ERR_OR_ZERO(stmmac_res->addr);
+}
+
+/**
+ * Parse Phytium ACPI properties
+ */
+static struct plat_stmmacenet_data *
+dwmac_phytium_parse_config_acpi(struct platform_device *pdev, const char *mac)
+{
+ struct device *dev = &pdev->dev;
+ struct fwnode_handle *np;
+ struct plat_stmmacenet_data *plat;
+ struct stmmac_dma_cfg *dma_cfg;
+ struct stmmac_axi *axi;
+ struct clk_hw *clk_hw;
+ u64 clk_freq;
+ int ret;
+
+ plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
+ if (!plat)
+ return ERR_PTR(-ENOMEM);
+
+ np = dev_fwnode(dev);
+
+ plat->phy_interface = fwnode_get_phy_mode(np);
+ plat->interface = plat->phy_interface;
+
+ /* Get max speed of operation from properties */
+ if (fwnode_property_read_u32(np, "max-speed", &plat->max_speed))
+ plat->max_speed = 1000;
+
+ if (fwnode_property_read_u32(np, "bus_id", &plat->bus_id))
+ plat->bus_id = 2;
+
+ /* Default to PHY auto-detection */
+ plat->phy_addr = -1;
+
+ plat->mdio_bus_data = devm_kzalloc(dev,
+ sizeof(struct stmmac_mdio_bus_data),
+ GFP_KERNEL);
+
+ fwnode_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
+ fwnode_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
+ if (plat->tx_fifo_size == 0)
+ plat->tx_fifo_size = 0x10000;
+ if (plat->rx_fifo_size == 0)
+ plat->rx_fifo_size = 0x10000;
+
+ plat->force_sf_dma_mode =
+ fwnode_property_read_bool(np, "snps,force_sf_dma_mode");
+ plat->en_tx_lpi_clockgating =
+ fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating");
+
+ /* Set the maxmtu to a default of JUMBO_LEN in case the
+ * parameter is not present.
+ */
+ plat->maxmtu = JUMBO_LEN;
+
+ /* Set default value for multicast hash bins */
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+ /* Set default value for unicast filter entries */
+ plat->unicast_filter_entries = 1;
+
+ fwnode_property_read_u32(np, "max-frame-size", &plat->maxmtu);
+ plat->has_gmac = 1;
+ plat->pmt = 1;
+
+ dma_cfg = devm_kzalloc(dev, sizeof(*dma_cfg), GFP_KERNEL);
+ if (!dma_cfg)
+ return ERR_PTR(-ENOMEM);
+ plat->dma_cfg = dma_cfg;
+
+ fwnode_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ if (!dma_cfg->pbl)
+ dma_cfg->pbl = DEFAULT_DMA_PBL;
+
+ fwnode_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
+ fwnode_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
+ dma_cfg->pblx8 = !fwnode_property_read_bool(np, "snps,no-pbl-x8");
+
+ dma_cfg->aal = fwnode_property_read_bool(np, "snps,aal");
+ dma_cfg->fixed_burst = fwnode_property_read_bool(np, "snps,fixed-burst");
+ dma_cfg->mixed_burst = fwnode_property_read_bool(np, "snps,mixed-burst");
+
+ plat->force_thresh_dma_mode = fwnode_property_read_bool(np, "snps,force_thresh_dma_mode");
+ if (plat->force_thresh_dma_mode)
+ plat->force_sf_dma_mode = 0;
+
+ fwnode_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed);
+
+ axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL);
+ if (!axi)
+ return ERR_PTR(-ENOMEM);
+ plat->axi = axi;
+
+ axi->axi_wr_osr_lmt = 1;
+ axi->axi_rd_osr_lmt = 1;
+
+ plat->rx_queues_to_use = 1;
+ plat->tx_queues_to_use = 1;
+
+ /**
+ * First Queue must always be in DCB mode. As MTL_QUEUE_DCB=1 we need
+ * to always set this, otherwise Queue will be classified as AVB
+ * (because MTL_QUEUE_AVB = 0).
+ */
+ plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+ plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+
+ plat->rx_queues_cfg[0].use_prio = true;
+
+ plat->rx_queues_cfg[0].pkt_route = 0x0;
+
+ plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP;
+
+ ret = fwnode_property_read_u64(np, "clock-frequency", &clk_freq);
+ if (ret < 0)
+ clk_freq = 125000000; /* default to 125MHz */
+
+ clk_hw = clk_hw_register_fixed_rate(dev, dev_name(dev), NULL,
+ 0, clk_freq);
+ if (IS_ERR(clk_hw))
+ return ERR_PTR(PTR_ERR(clk_hw));
+ ret = devm_clk_hw_register_clkdev(dev, clk_hw, dev_name(dev),
+ dev_name(dev));
+ if (ret)
+ return ERR_PTR(ret);
+ plat->stmmac_clk = clk_hw->clk;
+ clk_prepare_enable(plat->stmmac_clk);
+
+ return plat;
+}
+
+static int dwmac_phytium_probe(struct platform_device *pdev)
+{
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ int ret;
+
+ ret = dwmac_phytium_get_resources(pdev, &stmmac_res);
+ if (ret)
+ return ret;
+
+ if (has_acpi_companion(&pdev->dev)) {
+ plat_dat = dwmac_phytium_parse_config_acpi(pdev, stmmac_res.mac);
+ if (IS_ERR(plat_dat)) {
+ dev_err(&pdev->dev, "ACPI configuration failed\n");
+ return PTR_ERR(plat_dat);
+ }
+ } else {
+ dev_err(&pdev->dev, "no ACPI properties\n");
+ return -EINVAL;
+ }
+
+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ if (ret)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ if (plat_dat->exit)
+ plat_dat->exit(pdev, plat_dat->bsp_priv);
+
+ return ret;
+}
+
+static const struct acpi_device_id dwmac_phytium_acpi_match[] = {
+ {
+ .id = "PHYT0004",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, dwmac_phytium_acpi_match);
+
+static struct platform_driver dwmac_phytium_driver = {
+ .probe = dwmac_phytium_probe,
+ .remove_new = stmmac_pltfr_remove,
+ .driver = {
+ .name = "dwmac-phytium",
+ .pm = &stmmac_pltfr_pm_ops,
+ .acpi_match_table = ACPI_PTR(dwmac_phytium_acpi_match),
+ },
+};
+module_platform_driver(dwmac_phytium_driver);
+
+MODULE_DESCRIPTION("Glue driver for Phytium DWMAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -14,6 +14,7 @@
https://bugzilla.stlinux.com/
*******************************************************************************/
+#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,9 @@
*******************************************************************************/
#include <linux/device.h>
+#include <linux/acpi.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -703,6 +706,248 @@ EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
EXPORT_SYMBOL_GPL(devm_stmmac_probe_config_dt);
EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
+#ifdef CONFIG_ACPI
+/*
+ * Parse ACPI _DSD to setup AXI register
+ */
+static struct stmmac_axi * stmmac_axi_setup_acpi(struct platform_device *pdev)
+{
+ struct fwnode_handle *np = dev_fwnode(&(pdev->dev));
+ struct stmmac_axi * axi;
+
+ axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL);
+ if (!axi)
+ return ERR_PTR(-ENOMEM);
+
+ axi->axi_lpi_en = fwnode_property_read_bool(np, "snps,lpi_en");
+ axi->axi_xit_frm = fwnode_property_read_bool(np, "snps,xit_frm");
+ axi->axi_kbbe = fwnode_property_read_bool(np, "snps,axi_kbbe");
+ axi->axi_fb = fwnode_property_read_bool(np, "snps,axi_fb");
+ axi->axi_mb = fwnode_property_read_bool(np, "snps,axi_mb");
+ axi->axi_rb = fwnode_property_read_bool(np, "snps,axi_rb");
+
+ if (fwnode_property_read_u32(np, "snps,wr_osr_lmt", &axi->axi_wr_osr_lmt))
+ axi->axi_wr_osr_lmt = 1;
+ if (fwnode_property_read_u32(np, "snps,rd_osr_lmt", &axi->axi_rd_osr_lmt))
+ axi->axi_rd_osr_lmt = 1;
+ fwnode_property_read_u32_array(np, "snps,blen", axi->axi_blen, AXI_BLEN);
+
+ return axi;
+}
+
+/**
+ * Parse ACPI _DSD parameters for multiple queues configuration
+ */
+static void stmmac_mtl_setup_acpi(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ plat->rx_queues_to_use = 1;
+ plat->tx_queues_to_use = 1;
+
+ /**
+ * First Queue must always be in DCB mode. As MTL_QUEUE_DCB=1 we need
+ * to always set this, otherwise Queue will be classified as AVB
+ * (because MTL_QUEUE_AVB = 0).
+ */
+ plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+ plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+
+ plat->rx_queues_cfg[0].use_prio = true;
+
+ plat->rx_queues_cfg[0].pkt_route = 0x0;
+
+ plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP;
+
+ plat->tx_queues_cfg[0].use_prio = true;
+}
+
+static int stmmac_acpi_phy(struct plat_stmmacenet_data *plat,
+ struct fwnode_handle *np, struct device *dev)
+{
+ plat->mdio_bus_data = devm_kzalloc(dev,
+ sizeof(struct stmmac_mdio_bus_data),
+ GFP_KERNEL);
+
+ return 0;
+}
+
+int fw_get_phy_mode(struct fwnode_handle *np)
+{
+ const char *pm;
+ int err, i;
+
+ err = fwnode_property_read_string(np, "phy-mode", &pm);
+ if (err < 0)
+ err = fwnode_property_read_string(np, "phy-connection-mode", &pm);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
+ if (!strcasecmp(pm, phy_modes(i)))
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+int stmmac_acpi_clock_setup(struct plat_stmmacenet_data *plat,
+ struct platform_device *pdev)
+{
+ struct fwnode_handle *np = dev_fwnode(&(pdev->dev));
+ struct device * dev = &pdev->dev;
+ struct clk *clk = ERR_PTR(-ENODEV);
+ u64 clk_freq = 0;
+ int err;
+
+ err = fwnode_property_read_u64(np, "clock-frequency", &clk_freq);
+ if (err < 0)
+ clk_freq = 125000000; /* default to 125MHz */
+
+ plat->stmmac_clk = devm_clk_get(dev, dev_name(dev));
+ if (IS_ERR(plat->stmmac_clk)) {
+ clk = clk_register_fixed_rate(dev, dev_name(dev), NULL, 0, clk_freq);
+ if (IS_ERR(clk))
+ return -1;
+ if (clk_register_clkdev(clk, dev_name(dev), dev_name(dev)))
+ return -1;
+ plat->stmmac_clk = clk;
+ }
+ clk_prepare_enable(plat->stmmac_clk);
+
+ plat->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(plat->pclk))
+ plat->pclk = NULL;
+ clk_prepare_enable(plat->pclk);
+
+ plat->clk_ptp_ref = devm_clk_get(dev, "ptp_ref");
+ if (IS_ERR(plat->clk_ptp_ref)) {
+ plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk);
+ plat->clk_ptp_ref = NULL;
+ }
+
+ plat->stmmac_rst = devm_reset_control_get(dev,STMMAC_RESOURCE_NAME);
+ if (IS_ERR(plat->stmmac_rst)) {
+ dev_info(dev, "no reset control found\n");
+ plat->stmmac_rst = NULL;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse ACPI driver parameters
+ */
+struct plat_stmmacenet_data *
+stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac)
+{
+ struct fwnode_handle *np;
+ struct plat_stmmacenet_data *plat;
+ struct stmmac_dma_cfg *dma_cfg;
+
+ plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
+ if (!plat)
+ return ERR_PTR(-ENOMEM);
+
+ np = dev_fwnode(&(pdev->dev));
+
+ plat->interface = fw_get_phy_mode(np);
+
+ /* Get max speed of operation from device tree */
+ if (fwnode_property_read_u32(np, "max-speed", &plat->max_speed))
+ plat->max_speed = -1;
+
+ if (fwnode_property_read_u32(np, "bus_id", &plat->bus_id))
+ plat->bus_id = 2;
+
+ /* Default to PHY auto-detection */
+ plat->phy_addr = -1;
+
+ /* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ * and warn of its use. Remove this when PHY node support is added.
+ */
+ if (fwnode_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
+ dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
+
+ if (stmmac_acpi_phy(plat, np, &pdev->dev))
+ return ERR_PTR(-ENODEV);
+
+ fwnode_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
+ fwnode_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
+ if (plat->tx_fifo_size == 0)
+ plat->tx_fifo_size = 0x10000;
+ if (plat->rx_fifo_size == 0)
+ plat->rx_fifo_size = 0x10000;
+
+ plat->force_sf_dma_mode =
+ fwnode_property_read_bool(np, "snps,force_sf_dma_mode");
+ plat->en_tx_lpi_clockgating =
+ fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating");
+
+ /* Set the maxmtu to a default of JUMBO_LEN in case the
+ * parameter is not present.
+ */
+ plat->maxmtu = JUMBO_LEN;
+
+ /* Set default value for multicast hash bins */
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+ /* Set default value for unicast filter entries */
+ plat->unicast_filter_entries = 1;
+
+ /* Only to "snps,dwmac" */
+ fwnode_property_read_u32(np, "max-frame-size", &plat->maxmtu);
+ fwnode_property_read_u32(np, "snps,multicast-filter-bins",
+ &plat->multicast_filter_bins);
+ fwnode_property_read_u32(np, "snps,perfect-filter-entries",
+ &plat->unicast_filter_entries);
+ plat->unicast_filter_entries = dwmac1000_validate_ucast_entries(
+ &pdev->dev, plat->unicast_filter_entries);
+ plat->multicast_filter_bins = dwmac1000_validate_mcast_bins(
+ &pdev->dev, plat->multicast_filter_bins);
+ plat->has_gmac = 1;
+ plat->pmt = 1;
+
+ dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);
+ if (!dma_cfg)
+ return ERR_PTR(-ENOMEM);
+ plat->dma_cfg = dma_cfg;
+
+ fwnode_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ if (!dma_cfg->pbl)
+ dma_cfg->pbl = DEFAULT_DMA_PBL;
+
+ fwnode_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
+ fwnode_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
+ dma_cfg->pblx8 = !fwnode_property_read_bool(np, "snps,no-pbl-x8");
+
+ dma_cfg->aal = fwnode_property_read_bool(np, "snps,aal");
+ dma_cfg->fixed_burst = fwnode_property_read_bool(np, "snps,fixed-burst");
+ dma_cfg->mixed_burst = fwnode_property_read_bool(np, "snps,mixed-burst");
+
+ plat->force_thresh_dma_mode = fwnode_property_read_bool(np, "snps,force_thresh_dma_mode");
+ if (plat->force_thresh_dma_mode)
+ plat->force_sf_dma_mode = 0;
+
+ fwnode_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed);
+
+ plat->axi = stmmac_axi_setup_acpi(pdev);
+
+ stmmac_mtl_setup_acpi(pdev, plat);
+
+ stmmac_acpi_clock_setup(plat,pdev);
+
+ return plat;
+}
+#else
+struct plat_stmmacenet_data *
+stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif /* CONFIG_ACPI */
+EXPORT_SYMBOL_GPL(stmmac_probe_config_acpi);
+
int stmmac_get_platform_resources(struct platform_device *pdev,
struct stmmac_resources *stmmac_res)
{
@@ -710,8 +955,14 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
/* Get IRQ information early to have an ability to ask for deferred
* probe if needed before we went too far with resource allocation.
+ * For ACPI _byname does not work, so we have to trust, that the
+ * first interrupt is the right one
*/
- stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
+ if (has_acpi_companion(&pdev->dev)) {
+ stmmac_res->irq = platform_get_irq(pdev, 0);
+ } else {
+ stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
+ }
if (stmmac_res->irq < 0)
return stmmac_res->irq;
@@ -729,6 +980,7 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
return -EPROBE_DEFER;
dev_info(&pdev->dev, "IRQ eth_wake_irq not found\n");
stmmac_res->wol_irq = stmmac_res->irq;
+ stmmac_res->lpi_irq = -1;
}
stmmac_res->lpi_irq =
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
@@ -15,6 +15,8 @@ struct plat_stmmacenet_data *
stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac);
struct plat_stmmacenet_data *
devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac);
+struct plat_stmmacenet_data *
+stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac);
void stmmac_remove_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat);
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 111111111111..222222222222 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -111,6 +111,11 @@
#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05
#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
+#define AT803X_DEBUG_REG_B 0x0B
+#define AT803X_DEBUG_REG_B_HIBERNATION_ENABLE 0x1
+#define AT803X_DEBUG_REG_B_HIBERNATION_OFFSET 15
+
+
#define AT803X_DEBUG_REG_HIB_CTRL 0x0b
#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10)
#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13)
@@ -397,6 +402,20 @@ static int at803x_enable_rx_delay(struct phy_device *phydev)
AT803X_DEBUG_RX_CLK_DLY_EN);
}
+static inline int at803x_disable_hibernate(struct phy_device *phydev)
+{
+ int ret = 0;
+ u16 val = 0;
+
+ ret = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_B);
+ if (ret < 0)
+ return ret;
+
+ val = ret & 0xffff;
+ val &= (~(AT803X_DEBUG_REG_B_HIBERNATION_ENABLE << AT803X_DEBUG_REG_B_HIBERNATION_OFFSET));
+ return phy_write(phydev, AT803X_DEBUG_DATA, val);
+}
+
static int at803x_enable_tx_delay(struct phy_device *phydev)
{
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0,
@@ -1037,6 +1056,10 @@ static int at803x_config_init(struct phy_device *phydev)
ret = at803x_disable_rx_delay(phydev);
if (ret < 0)
return ret;
+ else
+ ret = at803x_disable_hibernate(phydev);
+ if (ret < 0)
+ return ret;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
--
Armbian
@@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Mon, 2 Oct 2023 17:49:13 +0200
Subject: fix stmmac acpi glue for Feiteng on 6.6.y
---
drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c | 7 ++++---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 7 ++++---
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
@@ -55,7 +55,7 @@ dwmac_phytium_parse_config_acpi(struct platform_device *pdev, const char *mac)
np = dev_fwnode(dev);
plat->phy_interface = fwnode_get_phy_mode(np);
- plat->interface = plat->phy_interface;
+ plat->mac_interface = plat->phy_interface;
/* Get max speed of operation from properties */
if (fwnode_property_read_u32(np, "max-speed", &plat->max_speed))
@@ -80,8 +80,9 @@ dwmac_phytium_parse_config_acpi(struct platform_device *pdev, const char *mac)
plat->force_sf_dma_mode =
fwnode_property_read_bool(np, "snps,force_sf_dma_mode");
- plat->en_tx_lpi_clockgating =
- fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating");
+
+ if (fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating"))
+ plat->flags |= STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
/* Set the maxmtu to a default of JUMBO_LEN in case the
* parameter is not present.
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -851,7 +851,7 @@ stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac)
np = dev_fwnode(&(pdev->dev));
- plat->interface = fw_get_phy_mode(np);
+ plat->mac_interface = fw_get_phy_mode(np);
/* Get max speed of operation from device tree */
if (fwnode_property_read_u32(np, "max-speed", &plat->max_speed))
@@ -881,8 +881,9 @@ stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac)
plat->force_sf_dma_mode =
fwnode_property_read_bool(np, "snps,force_sf_dma_mode");
- plat->en_tx_lpi_clockgating =
- fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating");
+
+ if (fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating"))
+ plat->flags |= STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
/* Set the maxmtu to a default of JUMBO_LEN in case the
* parameter is not present.
--
Armbian
@@ -1,77 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kevin Schmidt <kevin.patrick.schmidt@googlemail.com>
Date: Thu, 31 Aug 2023 11:41:14 +0200
Subject: [ARCHEOLOGY] Add board: HiKey960
> X-Git-Archeology: - Revision d8200e5c383c1c77569596bfd2b8886ef8258c3f: https://github.com/armbian/build/commit/d8200e5c383c1c77569596bfd2b8886ef8258c3f
> X-Git-Archeology: Date: Thu, 31 Aug 2023 11:41:14 +0200
> X-Git-Archeology: From: Kevin Schmidt <kevin.patrick.schmidt@googlemail.com>
> X-Git-Archeology: Subject: Add board: HiKey960
> X-Git-Archeology:
---
arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 35 +++++++++-
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
index 3f13a960f34e..f05edfe378e6 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -197,6 +197,37 @@ optee {
method = "smc";
};
};
+
+ usb_hub_vdd: usb_hub_vdd {
+ compatible = "regulator-fixed";
+ regulator-name = "hub-vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio5 6 0>;
+ enable-active-high;
+ };
+
+ usb-hub {
+ compatible = "hisilicon,usbhub";
+ typec-vbus-gpios = <&gpio25 2 GPIO_ACTIVE_HIGH>;
+ otg-switch-gpios = <&gpio25 6 GPIO_ACTIVE_HIGH>;
+ hub-vdd-supply = <&usb_hub_vdd>;
+ usb-role-switch;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hikey_usb_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&dwc3_role_switch>;
+ };
+ hikey_usb_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&rt1711h_ep>;
+ };
+ };
+ };
};
/*
@@ -564,7 +595,7 @@ port {
rt1711h_ep: endpoint@0 {
reg = <0>;
- remote-endpoint = <&dwc3_role_switch>;
+ remote-endpoint = <&hikey_usb_ep1>;
};
};
};
@@ -686,7 +717,7 @@ port {
#size-cells = <0>;
dwc3_role_switch: endpoint@0 {
reg = <0>;
- remote-endpoint = <&rt1711h_ep>;
+ remote-endpoint = <&hikey_usb_ep0>;
};
dwc3_ss: endpoint@1 {
--
Armbian
@@ -1,660 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Thu, 4 Aug 2022 21:49:10 +0200
Subject: net: stmicro: stmmac: Phytium onboard ethernet drivers and ACPI glue
for 6.x
My board has two eths; only eth1 has an actual PHY and works.
Source is https://gitee.com/atzlinux/atzlinux-kernel/tree/master/debian/patch
rpardini hammered:
- small api change in upstream around 5.19
- hand-merged for 6.5
- use `.remove_new` due to "net: stmmac: Make stmmac_pltfr_remove() return void"
- hand-merged for 6.6:
- OXNAS is no more, Makefile lost reference, fix manually
- Remove Kconfig deps from Feiteng stuff not in mainline
- Default Kconfig to module
- fix stmmac acpi glue for Feiteng on 6.6.y
- drop the (now-qcom) phy hibernate stuff as it landed by 6.12.y
- rework stmmac_probe_config_acpi addition for 6.12.y
- rework for 6.13; remove_new is just remove again
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 +
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 19 +
drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c | 223 ++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 255 +++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | 2 +
7 files changed, 510 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -132,6 +132,16 @@ config DWMAC_MESON
the stmmac device driver. This driver is used for Meson6,
Meson8, Meson8b and GXBB SoCs.
+config DWMAC_PHYTIUM
+ tristate "Phytium DWMAC support"
+ default m
+ depends on ACPI
+ help
+ Support for Ethernet controllers on Phytium SoCs.
+
+ This selects the Phytium DWMAC glue layer support for the stmmac
+ device driver.
+
config DWMAC_QCOM_ETHQOS
tristate "Qualcomm ETHQOS support"
default ARCH_QCOM
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
+obj-$(CONFIG_DWMAC_PHYTIUM) += dwmac-phytium.o
obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o
obj-$(CONFIG_DWMAC_RENESAS_GBETH) += dwmac-renesas-gbeth.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -9,6 +9,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -32,6 +33,12 @@ static int dwmac_generic_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
+ } else if (has_acpi_companion(&pdev->dev)) {
+ plat_dat = stmmac_probe_config_acpi(pdev, stmmac_res.mac);
+ if (!plat_dat) {
+ dev_err(&pdev->dev, "acpi configuration failed\n");
+ return -EINVAL;
+ }
} else {
plat_dat = dev_get_platdata(&pdev->dev);
if (!plat_dat) {
@@ -66,12 +73,24 @@ static const struct of_device_id dwmac_generic_match[] = {
};
MODULE_DEVICE_TABLE(of, dwmac_generic_match);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id dwmac_acpi_ids[] = {
+ { .id = "PHYT0004" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(acpi, dwmac_acpi_ids);
+#else
+#define dwmac_acpi_ids NULL
+#endif
+
static struct platform_driver dwmac_generic_driver = {
.probe = dwmac_generic_probe,
.driver = {
.name = STMMAC_RESOURCE_NAME,
.pm = &stmmac_pltfr_pm_ops,
.of_match_table = dwmac_generic_match,
+ .acpi_match_table = ACPI_PTR(dwmac_acpi_ids),
},
};
module_platform_driver(dwmac_generic_driver);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Phytium DWMAC platform glue driver
+ *
+ * Copyright (C) 2022 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "stmmac.h"
+#include "stmmac_platform.h"
+
+/**
+ * Acquire Phytium DWMAC resources from ACPI
+ */
+int dwmac_phytium_get_resources(struct platform_device *pdev,
+ struct stmmac_resources *stmmac_res)
+{
+ memset(stmmac_res, 0, sizeof(*stmmac_res));
+
+ stmmac_res->irq = platform_get_irq(pdev, 0);
+ if (stmmac_res->irq < 0)
+ return stmmac_res->irq;
+
+ stmmac_res->addr = devm_platform_ioremap_resource(pdev, 0);
+ stmmac_res->wol_irq = stmmac_res->irq;
+ stmmac_res->lpi_irq = -ENOENT;
+
+ return PTR_ERR_OR_ZERO(stmmac_res->addr);
+}
+
+/**
+ * Parse Phytium ACPI properties
+ */
+static struct plat_stmmacenet_data *
+dwmac_phytium_parse_config_acpi(struct platform_device *pdev, const char *mac)
+{
+ struct device *dev = &pdev->dev;
+ struct fwnode_handle *np;
+ struct plat_stmmacenet_data *plat;
+ struct stmmac_dma_cfg *dma_cfg;
+ struct stmmac_axi *axi;
+ struct clk_hw *clk_hw;
+ u64 clk_freq;
+ int ret;
+
+ plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
+ if (!plat)
+ return ERR_PTR(-ENOMEM);
+
+ np = dev_fwnode(dev);
+
+ plat->phy_interface = fwnode_get_phy_mode(np);
+
+
+ /* Get max speed of operation from properties */
+ if (fwnode_property_read_u32(np, "max-speed", &plat->max_speed))
+ plat->max_speed = 1000;
+
+ if (fwnode_property_read_u32(np, "bus_id", &plat->bus_id))
+ plat->bus_id = 2;
+
+ /* Default to PHY auto-detection */
+ plat->phy_addr = -1;
+
+ plat->mdio_bus_data = devm_kzalloc(dev,
+ sizeof(struct stmmac_mdio_bus_data),
+ GFP_KERNEL);
+
+ fwnode_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
+ fwnode_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
+ if (plat->tx_fifo_size == 0)
+ plat->tx_fifo_size = 0x10000;
+ if (plat->rx_fifo_size == 0)
+ plat->rx_fifo_size = 0x10000;
+
+ plat->force_sf_dma_mode =
+ fwnode_property_read_bool(np, "snps,force_sf_dma_mode");
+
+ if (fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating"))
+ plat->flags |= STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
+
+ /* Set the maxmtu to a default of JUMBO_LEN in case the
+ * parameter is not present.
+ */
+ plat->maxmtu = JUMBO_LEN;
+
+ /* Set default value for multicast hash bins */
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+ /* Set default value for unicast filter entries */
+ plat->unicast_filter_entries = 1;
+
+ fwnode_property_read_u32(np, "max-frame-size", &plat->maxmtu);
+ plat->has_gmac = 1;
+ plat->pmt = 1;
+
+ dma_cfg = devm_kzalloc(dev, sizeof(*dma_cfg), GFP_KERNEL);
+ if (!dma_cfg)
+ return ERR_PTR(-ENOMEM);
+ plat->dma_cfg = dma_cfg;
+
+ fwnode_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ if (!dma_cfg->pbl)
+ dma_cfg->pbl = DEFAULT_DMA_PBL;
+
+ fwnode_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
+ fwnode_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
+ dma_cfg->pblx8 = !fwnode_property_read_bool(np, "snps,no-pbl-x8");
+
+ dma_cfg->aal = fwnode_property_read_bool(np, "snps,aal");
+ dma_cfg->fixed_burst = fwnode_property_read_bool(np, "snps,fixed-burst");
+ dma_cfg->mixed_burst = fwnode_property_read_bool(np, "snps,mixed-burst");
+
+ plat->force_thresh_dma_mode = fwnode_property_read_bool(np, "snps,force_thresh_dma_mode");
+ if (plat->force_thresh_dma_mode)
+ plat->force_sf_dma_mode = 0;
+
+ fwnode_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed);
+
+ axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL);
+ if (!axi)
+ return ERR_PTR(-ENOMEM);
+ plat->axi = axi;
+
+ axi->axi_wr_osr_lmt = 1;
+ axi->axi_rd_osr_lmt = 1;
+
+ plat->rx_queues_to_use = 1;
+ plat->tx_queues_to_use = 1;
+
+ /**
+ * First Queue must always be in DCB mode. As MTL_QUEUE_DCB=1 we need
+ * to always set this, otherwise Queue will be classified as AVB
+ * (because MTL_QUEUE_AVB = 0).
+ */
+ plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+ plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+
+ plat->rx_queues_cfg[0].use_prio = true;
+
+ plat->rx_queues_cfg[0].pkt_route = 0x0;
+
+ plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP;
+
+ ret = fwnode_property_read_u64(np, "clock-frequency", &clk_freq);
+ if (ret < 0)
+ clk_freq = 125000000; /* default to 125MHz */
+
+ clk_hw = clk_hw_register_fixed_rate(dev, dev_name(dev), NULL,
+ 0, clk_freq);
+ if (IS_ERR(clk_hw))
+ return ERR_PTR(PTR_ERR(clk_hw));
+ ret = devm_clk_hw_register_clkdev(dev, clk_hw, dev_name(dev),
+ dev_name(dev));
+ if (ret)
+ return ERR_PTR(ret);
+ plat->stmmac_clk = clk_hw->clk;
+ clk_prepare_enable(plat->stmmac_clk);
+
+ return plat;
+}
+
+static int dwmac_phytium_probe(struct platform_device *pdev)
+{
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ int ret;
+
+ ret = dwmac_phytium_get_resources(pdev, &stmmac_res);
+ if (ret)
+ return ret;
+
+ if (has_acpi_companion(&pdev->dev)) {
+ plat_dat = dwmac_phytium_parse_config_acpi(pdev, stmmac_res.mac);
+ if (IS_ERR(plat_dat)) {
+ dev_err(&pdev->dev, "ACPI configuration failed\n");
+ return PTR_ERR(plat_dat);
+ }
+ } else {
+ dev_err(&pdev->dev, "no ACPI properties\n");
+ return -EINVAL;
+ }
+
+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ if (ret)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ if (plat_dat->exit)
+ plat_dat->exit(pdev, plat_dat->bsp_priv);
+
+ return ret;
+}
+
+static const struct acpi_device_id dwmac_phytium_acpi_match[] = {
+ {
+ .id = "PHYT0004",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, dwmac_phytium_acpi_match);
+
+static struct platform_driver dwmac_phytium_driver = {
+ .probe = dwmac_phytium_probe,
+ .remove = stmmac_pltfr_remove,
+ .driver = {
+ .name = "dwmac-phytium",
+ .pm = &stmmac_pltfr_pm_ops,
+ .acpi_match_table = ACPI_PTR(dwmac_phytium_acpi_match),
+ },
+};
+module_platform_driver(dwmac_phytium_driver);
+
+MODULE_DESCRIPTION("Glue driver for Phytium DWMAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -14,6 +14,7 @@
https://bugzilla.stlinux.com/
*******************************************************************************/
+#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,9 @@
*******************************************************************************/
#include <linux/device.h>
+#include <linux/acpi.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -697,6 +700,249 @@ struct clk *stmmac_pltfr_find_clk(struct plat_stmmacenet_data *plat_dat,
}
EXPORT_SYMBOL_GPL(stmmac_pltfr_find_clk);
+#ifdef CONFIG_ACPI
+/*
+ * Parse ACPI _DSD to setup AXI register
+ */
+static struct stmmac_axi * stmmac_axi_setup_acpi(struct platform_device *pdev)
+{
+ struct fwnode_handle *np = dev_fwnode(&(pdev->dev));
+ struct stmmac_axi * axi;
+
+ axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL);
+ if (!axi)
+ return ERR_PTR(-ENOMEM);
+
+ axi->axi_lpi_en = fwnode_property_read_bool(np, "snps,lpi_en");
+ axi->axi_xit_frm = fwnode_property_read_bool(np, "snps,xit_frm");
+ axi->axi_kbbe = fwnode_property_read_bool(np, "snps,axi_kbbe");
+ axi->axi_fb = fwnode_property_read_bool(np, "snps,axi_fb");
+ axi->axi_mb = fwnode_property_read_bool(np, "snps,axi_mb");
+ axi->axi_rb = fwnode_property_read_bool(np, "snps,axi_rb");
+
+ if (fwnode_property_read_u32(np, "snps,wr_osr_lmt", &axi->axi_wr_osr_lmt))
+ axi->axi_wr_osr_lmt = 1;
+ if (fwnode_property_read_u32(np, "snps,rd_osr_lmt", &axi->axi_rd_osr_lmt))
+ axi->axi_rd_osr_lmt = 1;
+ fwnode_property_read_u32_array(np, "snps,blen", axi->axi_blen, AXI_BLEN);
+
+ return axi;
+}
+
+/**
+ * Parse ACPI _DSD parameters for multiple queues configuration
+ */
+static void stmmac_mtl_setup_acpi(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ plat->rx_queues_to_use = 1;
+ plat->tx_queues_to_use = 1;
+
+ /**
+ * First Queue must always be in DCB mode. As MTL_QUEUE_DCB=1 we need
+ * to always set this, otherwise Queue will be classified as AVB
+ * (because MTL_QUEUE_AVB = 0).
+ */
+ plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+ plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+
+ plat->rx_queues_cfg[0].use_prio = true;
+
+ plat->rx_queues_cfg[0].pkt_route = 0x0;
+
+ plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP;
+
+ plat->tx_queues_cfg[0].use_prio = true;
+}
+
+static int stmmac_acpi_phy(struct plat_stmmacenet_data *plat,
+ struct fwnode_handle *np, struct device *dev)
+{
+ plat->mdio_bus_data = devm_kzalloc(dev,
+ sizeof(struct stmmac_mdio_bus_data),
+ GFP_KERNEL);
+
+ return 0;
+}
+
+int fw_get_phy_mode(struct fwnode_handle *np)
+{
+ const char *pm;
+ int err, i;
+
+ err = fwnode_property_read_string(np, "phy-mode", &pm);
+ if (err < 0)
+ err = fwnode_property_read_string(np, "phy-connection-mode", &pm);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
+ if (!strcasecmp(pm, phy_modes(i)))
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+int stmmac_acpi_clock_setup(struct plat_stmmacenet_data *plat,
+ struct platform_device *pdev)
+{
+ struct fwnode_handle *np = dev_fwnode(&(pdev->dev));
+ struct device * dev = &pdev->dev;
+ struct clk *clk = ERR_PTR(-ENODEV);
+ u64 clk_freq = 0;
+ int err;
+
+ err = fwnode_property_read_u64(np, "clock-frequency", &clk_freq);
+ if (err < 0)
+ clk_freq = 125000000; /* default to 125MHz */
+
+ plat->stmmac_clk = devm_clk_get(dev, dev_name(dev));
+ if (IS_ERR(plat->stmmac_clk)) {
+ clk = clk_register_fixed_rate(dev, dev_name(dev), NULL, 0, clk_freq);
+ if (IS_ERR(clk))
+ return -1;
+ if (clk_register_clkdev(clk, dev_name(dev), dev_name(dev)))
+ return -1;
+ plat->stmmac_clk = clk;
+ }
+ clk_prepare_enable(plat->stmmac_clk);
+
+ plat->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(plat->pclk))
+ plat->pclk = NULL;
+ clk_prepare_enable(plat->pclk);
+
+ plat->clk_ptp_ref = devm_clk_get(dev, "ptp_ref");
+ if (IS_ERR(plat->clk_ptp_ref)) {
+ plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk);
+ plat->clk_ptp_ref = NULL;
+ }
+
+ plat->stmmac_rst = devm_reset_control_get(dev,STMMAC_RESOURCE_NAME);
+ if (IS_ERR(plat->stmmac_rst)) {
+ dev_info(dev, "no reset control found\n");
+ plat->stmmac_rst = NULL;
+ }
+
+ return 0;
+}
+
+/**
+ * Parse ACPI driver parameters
+ */
+struct plat_stmmacenet_data *
+stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac)
+{
+ struct fwnode_handle *np;
+ struct plat_stmmacenet_data *plat;
+ struct stmmac_dma_cfg *dma_cfg;
+
+ plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
+ if (!plat)
+ return ERR_PTR(-ENOMEM);
+
+ np = dev_fwnode(&(pdev->dev));
+
+ plat->phy_interface = fw_get_phy_mode(np);
+
+ /* Get max speed of operation from device tree */
+ if (fwnode_property_read_u32(np, "max-speed", &plat->max_speed))
+ plat->max_speed = -1;
+
+ if (fwnode_property_read_u32(np, "bus_id", &plat->bus_id))
+ plat->bus_id = 2;
+
+ /* Default to PHY auto-detection */
+ plat->phy_addr = -1;
+
+ /* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ * and warn of its use. Remove this when PHY node support is added.
+ */
+ if (fwnode_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
+ dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
+
+ if (stmmac_acpi_phy(plat, np, &pdev->dev))
+ return ERR_PTR(-ENODEV);
+
+ fwnode_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
+ fwnode_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
+ if (plat->tx_fifo_size == 0)
+ plat->tx_fifo_size = 0x10000;
+ if (plat->rx_fifo_size == 0)
+ plat->rx_fifo_size = 0x10000;
+
+ plat->force_sf_dma_mode =
+ fwnode_property_read_bool(np, "snps,force_sf_dma_mode");
+
+ if (fwnode_property_read_bool(np, "snps,en-tx-lpi-clockgating"))
+ plat->flags |= STMMAC_FLAG_EN_TX_LPI_CLOCKGATING;
+
+ /* Set the maxmtu to a default of JUMBO_LEN in case the
+ * parameter is not present.
+ */
+ plat->maxmtu = JUMBO_LEN;
+
+ /* Set default value for multicast hash bins */
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+ /* Set default value for unicast filter entries */
+ plat->unicast_filter_entries = 1;
+
+ /* Only to "snps,dwmac" */
+ fwnode_property_read_u32(np, "max-frame-size", &plat->maxmtu);
+ fwnode_property_read_u32(np, "snps,multicast-filter-bins",
+ &plat->multicast_filter_bins);
+ fwnode_property_read_u32(np, "snps,perfect-filter-entries",
+ &plat->unicast_filter_entries);
+ plat->unicast_filter_entries = dwmac1000_validate_ucast_entries(
+ &pdev->dev, plat->unicast_filter_entries);
+ plat->multicast_filter_bins = dwmac1000_validate_mcast_bins(
+ &pdev->dev, plat->multicast_filter_bins);
+ plat->has_gmac = 1;
+ plat->pmt = 1;
+
+ dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);
+ if (!dma_cfg)
+ return ERR_PTR(-ENOMEM);
+ plat->dma_cfg = dma_cfg;
+
+ fwnode_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ if (!dma_cfg->pbl)
+ dma_cfg->pbl = DEFAULT_DMA_PBL;
+
+ fwnode_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
+ fwnode_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
+ dma_cfg->pblx8 = !fwnode_property_read_bool(np, "snps,no-pbl-x8");
+
+ dma_cfg->aal = fwnode_property_read_bool(np, "snps,aal");
+ dma_cfg->fixed_burst = fwnode_property_read_bool(np, "snps,fixed-burst");
+ dma_cfg->mixed_burst = fwnode_property_read_bool(np, "snps,mixed-burst");
+
+ plat->force_thresh_dma_mode = fwnode_property_read_bool(np, "snps,force_thresh_dma_mode");
+ if (plat->force_thresh_dma_mode)
+ plat->force_sf_dma_mode = 0;
+
+ fwnode_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed);
+
+ plat->axi = stmmac_axi_setup_acpi(pdev);
+
+ stmmac_mtl_setup_acpi(pdev, plat);
+
+ stmmac_acpi_clock_setup(plat,pdev);
+
+ return plat;
+}
+#else
+struct plat_stmmacenet_data *
+stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif /* CONFIG_ACPI */
+EXPORT_SYMBOL_GPL(stmmac_probe_config_acpi);
+
int stmmac_get_platform_resources(struct platform_device *pdev,
struct stmmac_resources *stmmac_res)
{
@@ -704,8 +950,14 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
/* Get IRQ information early to have an ability to ask for deferred
* probe if needed before we went too far with resource allocation.
+ * For ACPI _byname does not work, so we have to trust, that the
+ * first interrupt is the right one
*/
- stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
+ if (has_acpi_companion(&pdev->dev)) {
+ stmmac_res->irq = platform_get_irq(pdev, 0);
+ } else {
+ stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
+ }
if (stmmac_res->irq < 0)
return stmmac_res->irq;
@@ -723,6 +975,7 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
return -EPROBE_DEFER;
dev_info(&pdev->dev, "IRQ eth_wake_irq not found\n");
stmmac_res->wol_irq = stmmac_res->irq;
+ stmmac_res->lpi_irq = -1;
}
stmmac_res->sfty_irq =
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
@@ -13,6 +13,8 @@
struct plat_stmmacenet_data *
devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac);
+struct plat_stmmacenet_data *
+stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac);
struct clk *stmmac_pltfr_find_clk(struct plat_stmmacenet_data *plat_dat,
const char *name);
--
Armbian
@@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Mon, 29 Dec 2025 14:35:40 +0100
Subject: net: stmicro: stmmac: Phytium: adapt to "net: stmmac: remove axi_blen
array"
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -724,7 +724,10 @@ static struct stmmac_axi * stmmac_axi_setup_acpi(struct platform_device *pdev)
axi->axi_wr_osr_lmt = 1;
if (fwnode_property_read_u32(np, "snps,rd_osr_lmt", &axi->axi_rd_osr_lmt))
axi->axi_rd_osr_lmt = 1;
- fwnode_property_read_u32_array(np, "snps,blen", axi->axi_blen, AXI_BLEN);
+
+ u32 axi_blen[AXI_BLEN]; // adapt to "net: stmmac: remove axi_blen array"
+ fwnode_property_read_u32_array(np, "snps,blen", axi_blen, AXI_BLEN);
+ stmmac_axi_blen_to_mask(&axi->axi_blen_regval, axi_blen, AXI_BLEN);
return axi;
}
--
Armbian
@@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Mon, 29 Dec 2025 15:20:32 +0100
Subject: net: stmicro: stmmac: Phytium: adapt to "net: stmmac: replace
has_xxxx with core_type"
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c | 4 ++--
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
@@ -55,7 +55,7 @@ dwmac_phytium_parse_config_acpi(struct platform_device *pdev, const char *mac)
np = dev_fwnode(dev);
plat->phy_interface = fwnode_get_phy_mode(np);
-
+
/* Get max speed of operation from properties */
if (fwnode_property_read_u32(np, "max-speed", &plat->max_speed))
@@ -96,7 +96,7 @@ dwmac_phytium_parse_config_acpi(struct platform_device *pdev, const char *mac)
plat->unicast_filter_entries = 1;
fwnode_property_read_u32(np, "max-frame-size", &plat->maxmtu);
- plat->has_gmac = 1;
+ plat->core_type = DWMAC_CORE_GMAC; // adapt to "net: stmmac: replace has_xxxx with core_type"
plat->pmt = 1;
dma_cfg = devm_kzalloc(dev, sizeof(*dma_cfg), GFP_KERNEL);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -903,7 +903,7 @@ stmmac_probe_config_acpi(struct platform_device *pdev, u8 *mac)
&pdev->dev, plat->unicast_filter_entries);
plat->multicast_filter_bins = dwmac1000_validate_mcast_bins(
&pdev->dev, plat->multicast_filter_bins);
- plat->has_gmac = 1;
+ plat->core_type = DWMAC_CORE_GMAC; // adapt to "net: stmmac: replace has_xxxx with core_type"
plat->pmt = 1;
dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);
--
Armbian
@@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Mon, 29 Dec 2025 15:41:31 +0100
Subject: net: stmicro: stmmac: Phytium: adapt to "net: stmmac: pass struct
device to init()/exit() methods"
- ref https://github.com/torvalds/linux/commit/85081acc6b1188f2a6e5e605dc644225fcdf327f
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
@@ -195,7 +195,7 @@ static int dwmac_phytium_probe(struct platform_device *pdev)
err_exit:
if (plat_dat->exit)
- plat_dat->exit(pdev, plat_dat->bsp_priv);
+ plat_dat->exit(&pdev->dev, plat_dat->bsp_priv);
return ret;
}
--
Armbian
@@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Igor <igor@armbian.com>
Date: Mon, 16 Mar 2026 00:00:00 +0000
Subject: fix: stmmac compilation warnings and errors
Fix compilation issues in Phytium ethernet driver patches:
- Make fw_get_phy_mode() static to resolve missing prototype warning
- Make stmmac_acpi_clock_setup() static to resolve missing prototype warning
- Make dwmac_phytium_get_resources() static to resolve missing prototype warning
- Remove invalid stmmac_res->lpi_irq assignments in stmmac_platform.c (member doesn't exist)
- Remove invalid stmmac_res->lpi_irq assignment in dwmac-phytium.c (member doesn't exist)
---
drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c | 3 +--
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 5 ++---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c
@@ -17,7 +17,7 @@
/**
* Acquire Phytium DWMAC resources from ACPI
*/
-int dwmac_phytium_get_resources(struct platform_device *pdev,
+static int dwmac_phytium_get_resources(struct platform_device *pdev,
struct stmmac_resources *stmmac_res)
{
memset(stmmac_res, 0, sizeof(*stmmac_res));
@@ -28,7 +28,6 @@ int dwmac_phytium_get_resources(struct platform_device *pdev,
stmmac_res->addr = devm_platform_ioremap_resource(pdev, 0);
stmmac_res->wol_irq = stmmac_res->irq;
- stmmac_res->lpi_irq = -ENOENT;
return PTR_ERR_OR_ZERO(stmmac_res->addr);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 111111111111..222222222222 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -769,7 +769,7 @@ static int stmmac_acpi_phy(struct plat_stmmacenet_data *plat,
return 0;
}
-int fw_get_phy_mode(struct fwnode_handle *np)
+static int fw_get_phy_mode(struct fwnode_handle *np)
{
const char *pm;
int err, i;
@@ -788,7 +788,7 @@ int fw_get_phy_mode(struct fwnode_handle *np)
return -ENODEV;
}
-int stmmac_acpi_clock_setup(struct plat_stmmacenet_data *plat,
+static int stmmac_acpi_clock_setup(struct plat_stmmacenet_data *plat,
struct platform_device *pdev)
{
struct fwnode_handle *np = dev_fwnode(&(pdev->dev));
@@ -978,7 +978,6 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
return -EPROBE_DEFER;
dev_info(&pdev->dev, "IRQ eth_wake_irq not found\n");
stmmac_res->wol_irq = stmmac_res->irq;
- stmmac_res->lpi_irq = -1;
}
stmmac_res->sfty_irq =
--
Armbian
@@ -1,77 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kevin Schmidt <kevin.patrick.schmidt@googlemail.com>
Date: Thu, 31 Aug 2023 11:41:14 +0200
Subject: [ARCHEOLOGY] Add board: HiKey960
> X-Git-Archeology: - Revision d8200e5c383c1c77569596bfd2b8886ef8258c3f: https://github.com/armbian/build/commit/d8200e5c383c1c77569596bfd2b8886ef8258c3f
> X-Git-Archeology: Date: Thu, 31 Aug 2023 11:41:14 +0200
> X-Git-Archeology: From: Kevin Schmidt <kevin.patrick.schmidt@googlemail.com>
> X-Git-Archeology: Subject: Add board: HiKey960
> X-Git-Archeology:
---
arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 35 +++++++++-
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -197,6 +197,37 @@ optee {
method = "smc";
};
};
+
+ usb_hub_vdd: usb_hub_vdd {
+ compatible = "regulator-fixed";
+ regulator-name = "hub-vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio5 6 0>;
+ enable-active-high;
+ };
+
+ usb-hub {
+ compatible = "hisilicon,usbhub";
+ typec-vbus-gpios = <&gpio25 2 GPIO_ACTIVE_HIGH>;
+ otg-switch-gpios = <&gpio25 6 GPIO_ACTIVE_HIGH>;
+ hub-vdd-supply = <&usb_hub_vdd>;
+ usb-role-switch;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hikey_usb_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&dwc3_role_switch>;
+ };
+ hikey_usb_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&rt1711h_ep>;
+ };
+ };
+ };
};
/*
@@ -564,7 +595,7 @@ port {
rt1711h_ep: endpoint@0 {
reg = <0>;
- remote-endpoint = <&dwc3_role_switch>;
+ remote-endpoint = <&hikey_usb_ep1>;
};
};
};
@@ -683,7 +714,7 @@ port {
#size-cells = <0>;
dwc3_role_switch: endpoint@0 {
reg = <0>;
- remote-endpoint = <&rt1711h_ep>;
+ remote-endpoint = <&hikey_usb_ep0>;
};
dwc3_ss: endpoint@1 {
--
Armbian
@@ -1,128 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mingcong Bai <jeffbai@aosc.io>
Date: Wed, 23 Jul 2025 16:45:13 +0900
Subject: drm/xe/bo: fix alignment with non-4KiB kernel page sizes
The bo/ttm interfaces with kernel memory mapping from dedicated GPU
memory. It is not correct to assume that SZ_4K would suffice for page
alignment as there are a few hardware platforms that commonly uses non-
4KiB pages - for instance, 16KiB is the most commonly used kernel page
size used on Loongson devices (of the LoongArch architecture).
Per our testing, Intel Xe/Alchemist/Battlemage families of GPUs works on
Loongson platforms so long as "Above 4G Decoding" was enabled and
"Resizable BAR" was set to auto in the UEFI firmware settings.
Without this fix, the kernel will hang at a kernel BUG():
[ 7.425445] ------------[ cut here ]------------
[ 7.430032] kernel BUG at drivers/gpu/drm/drm_gem.c:181!
[ 7.435330] Oops - BUG[#1]:
[ 7.438099] CPU: 0 UID: 0 PID: 102 Comm: kworker/0:4 Tainted: G E 6.13.3-aosc-main-00336-g60829239b300-dirty #3
[ 7.449511] Tainted: [E]=UNSIGNED_MODULE
[ 7.453402] Hardware name: Loongson Loongson-3A6000-HV-7A2000-1w-V0.1-EVB/Loongson-3A6000-HV-7A2000-1w-EVB-V1.21, BIOS Loongson-UDK2018-V4.0.05756-prestab
[ 7.467144] Workqueue: events work_for_cpu_fn
[ 7.471472] pc 9000000001045fa4 ra ffff8000025331dc tp 90000001010c8000 sp 90000001010cb960
[ 7.479770] a0 900000012a3e8000 a1 900000010028c000 a2 000000000005d000 a3 0000000000000000
[ 7.488069] a4 0000000000000000 a5 0000000000000000 a6 0000000000000000 a7 0000000000000001
[ 7.496367] t0 0000000000001000 t1 9000000001045000 t2 0000000000000000 t3 0000000000000000
[ 7.504665] t4 0000000000000000 t5 0000000000000000 t6 0000000000000000 t7 0000000000000000
[ 7.504667] t8 0000000000000000 u0 90000000029ea7d8 s9 900000012a3e9360 s0 900000010028c000
[ 7.504668] s1 ffff800002744000 s2 0000000000000000 s3 0000000000000000 s4 0000000000000001
[ 7.504669] s5 900000012a3e8000 s6 0000000000000001 s7 0000000000022022 s8 0000000000000000
[ 7.537855] ra: ffff8000025331dc ___xe_bo_create_locked+0x158/0x3b0 [xe]
[ 7.544893] ERA: 9000000001045fa4 drm_gem_private_object_init+0xcc/0xd0
[ 7.551639] CRMD: 000000b0 (PLV0 -IE -DA +PG DACF=CC DACM=CC -WE)
[ 7.557785] PRMD: 00000004 (PPLV0 +PIE -PWE)
[ 7.562111] EUEN: 00000000 (-FPE -SXE -ASXE -BTE)
[ 7.566870] ECFG: 00071c1d (LIE=0,2-4,10-12 VS=7)
[ 7.571628] ESTAT: 000c0000 [BRK] (IS= ECode=12 EsubCode=0)
[ 7.577163] PRID: 0014d000 (Loongson-64bit, Loongson-3A6000-HV)
[ 7.583128] Modules linked in: xe(E+) drm_gpuvm(E) drm_exec(E) drm_buddy(E) gpu_sched(E) drm_suballoc_helper(E) drm_display_helper(E) loongson(E) r8169(E) cec(E) rc_core(E) realtek(E) i2c_algo_bit(E) tpm_tis_spi(E) led_class(E) hid_generic(E) drm_ttm_helper(E) ttm(E) drm_client_lib(E) drm_kms_helper(E) sunrpc(E) la_ow_syscall(E) i2c_dev(E)
[ 7.613049] Process kworker/0:4 (pid: 102, threadinfo=00000000bc26ebd1, task=0000000055480707)
[ 7.621606] Stack : 0000000000000000 3030303a6963702b 000000000005d000 0000000000000000
[ 7.629563] 0000000000000001 0000000000000000 0000000000000000 8e1bfae42b2f7877
[ 7.637519] 000000000005d000 900000012a3e8000 900000012a3e9360 0000000000000000
[ 7.645475] ffffffffffffffff 0000000000000000 0000000000022022 0000000000000000
[ 7.653431] 0000000000000001 ffff800002533660 0000000000022022 9000000000234470
[ 7.661386] 90000001010cba28 0000000000001000 0000000000000000 000000000005c300
[ 7.669342] 900000012a3e8000 0000000000000000 0000000000000001 900000012a3e8000
[ 7.677298] ffffffffffffffff 0000000000022022 900000012a3e9498 ffff800002533a14
[ 7.685254] 0000000000022022 0000000000000000 900000000209c000 90000000010589e0
[ 7.693209] 90000001010cbab8 ffff8000027c78c0 fffffffffffff000 900000012a3e8000
[ 7.701165] ...
[ 7.703588] Call Trace:
[ 7.703590] [<9000000001045fa4>] drm_gem_private_object_init+0xcc/0xd0
[ 7.712496] [<ffff8000025331d8>] ___xe_bo_create_locked+0x154/0x3b0 [xe]
[ 7.719268] [<ffff80000253365c>] __xe_bo_create_locked+0x228/0x304 [xe]
[ 7.725951] [<ffff800002533a10>] xe_bo_create_pin_map_at_aligned+0x70/0x1b0 [xe]
[ 7.733410] [<ffff800002533c7c>] xe_managed_bo_create_pin_map+0x34/0xcc [xe]
[ 7.740522] [<ffff800002533d58>] xe_managed_bo_create_from_data+0x44/0xb0 [xe]
[ 7.747807] [<ffff80000258d19c>] xe_uc_fw_init+0x3ec/0x904 [xe]
[ 7.753814] [<ffff80000254a478>] xe_guc_init+0x30/0x3dc [xe]
[ 7.759553] [<ffff80000258bc04>] xe_uc_init+0x20/0xf0 [xe]
[ 7.765121] [<ffff800002542abc>] xe_gt_init_hwconfig+0x5c/0xd0 [xe]
[ 7.771461] [<ffff800002537204>] xe_device_probe+0x240/0x588 [xe]
[ 7.777627] [<ffff800002575448>] xe_pci_probe+0x6c0/0xa6c [xe]
[ 7.783540] [<9000000000e9828c>] local_pci_probe+0x4c/0xb4
[ 7.788989] [<90000000002aa578>] work_for_cpu_fn+0x20/0x40
[ 7.794436] [<90000000002aeb50>] process_one_work+0x1a4/0x458
[ 7.800143] [<90000000002af5a0>] worker_thread+0x304/0x3fc
[ 7.805591] [<90000000002bacac>] kthread+0x114/0x138
[ 7.810520] [<9000000000241f64>] ret_from_kernel_thread+0x8/0xa4
[ 7.816489]
[ 7.817961] Code: 4c000020 29c3e2f9 53ff93ff <002a0001> 0015002c 03400000 02ff8063 29c04077 001500f7
[ 7.827651]
[ 7.829140] ---[ end trace 0000000000000000 ]---
Revise all instances of `SZ_4K' with `PAGE_SIZE' and revise the call to
`drm_gem_private_object_init()' in `*___xe_bo_create_locked()' (last call
before BUG()) to use `size_t aligned_size' calculated from `PAGE_SIZE' to
fix the above error.
Cc: <stable@vger.kernel.org>
Fixes: 4e03b584143e ("drm/xe/uapi: Reject bo creation of unaligned size")
Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Tested-by: Mingcong Bai <jeffbai@aosc.io>
Tested-by: Wenbin Fang <fangwenbin@vip.qq.com>
Tested-by: Haien Liang <27873200@qq.com>
Tested-by: Jianfeng Liu <liujianfeng1994@gmail.com>
Tested-by: Shirong Liu <lsr1024@qq.com>
Tested-by: Haofeng Wu <s2600cw2@126.com>
Link: https://github.com/FanFansfan/loongson-linux/commit/22c55ab3931c32410a077b3ddb6dca3f28223360
Link: https://t.me/c/1109254909/768552
Co-developed-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
---
drivers/gpu/drm/xe/xe_bo.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -2169,9 +2169,9 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
flags |= XE_BO_FLAG_INTERNAL_64K;
alignment = align >> PAGE_SHIFT;
} else {
- aligned_size = ALIGN(size, SZ_4K);
+ aligned_size = ALIGN(size, PAGE_SIZE);
flags &= ~XE_BO_FLAG_INTERNAL_64K;
- alignment = SZ_4K >> PAGE_SHIFT;
+ alignment = PAGE_SIZE >> PAGE_SHIFT;
}
if (type == ttm_bo_type_device && aligned_size != size)
@@ -2195,7 +2195,7 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
#endif
INIT_LIST_HEAD(&bo->vram_userfault_link);
- drm_gem_private_object_init(&xe->drm, &bo->ttm.base, size);
+ drm_gem_private_object_init(&xe->drm, &bo->ttm.base, aligned_size);
if (resv) {
ctx.allow_res_evict = !(flags & XE_BO_FLAG_NO_RESV_EVICT);
--
Armbian
@@ -1,325 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mingcong Bai <jeffbai@aosc.io>
Date: Wed, 23 Jul 2025 16:45:14 +0900
Subject: drm/xe/guc: use GUC_SIZE (SZ_4K) for alignment
Per the "Firmware" chapter in "drm/xe Intel GFX Driver", as well as
"Volume 8: Command Stream Programming" in "Intel(r) Arc(tm) A-Series Graphics
and Intel Data Center GPU Flex Series Open-Source Programmer's Reference
Manual For the discrete GPUs code named "Alchemist" and "Arctic Sound-M""
and "Intel(r) Iris(r) Xe MAX Graphics Open Source Programmer's Reference
Manual For the 2020 Discrete GPU formerly named "DG1"":
"The RINGBUF register sets (defined in Memory Interface Registers) are
used to specify the ring buffer memory areas. The ring buffer must start
on a 4KB boundary and be allocated in linear memory. The length of any
one ring buffer is limited to 2MB."
The Graphics micro (m) Controller (GuC) really expects command buffers
aligned to 4KiB boundaries.
Current implementation uses `PAGE_SIZE' as an assumed alignment reference
but 4KiB kernel page sizes is by no means a guarantee. On 16KiB-paged
kernels, this causes driver failures after loading the GuC firmware:
[ 7.398317] xe 0000:09:00.0: [drm] Found dg2/g10 (device ID 56a1) display version 13.00 stepping C0
[ 7.410429] xe 0000:09:00.0: [drm] Using GuC firmware from i915/dg2_guc_70.bin version 70.36.0
[ 10.719989] xe 0000:09:00.0: [drm] *ERROR* GT0: load failed: status = 0x800001EC, time = 3297ms, freq = 2400MHz (req 2400MHz), done = 0
[ 10.732106] xe 0000:09:00.0: [drm] *ERROR* GT0: load failed: status: Reset = 0, BootROM = 0x76, UKernel = 0x01, MIA = 0x00, Auth = 0x02
[ 10.744214] xe 0000:09:00.0: [drm] *ERROR* CRITICAL: Xe has declared device 0000:09:00.0 as wedged.
Please file a _new_ bug report at https://gitlab.freedesktop.org/drm/xe/kernel/issues/new
[ 10.828908] xe 0000:09:00.0: [drm] *ERROR* GT0: GuC mmio request 0x4100: no reply 0x4100
Correct this by defining `GUC_ALIGN' as `SZ_4K' in accordance with the
references above, and revising all instances of `PAGE_SIZE' as
`GUC_ALIGN'. Then, revise `PAGE_ALIGN()' calls as `ALIGN()' with
`GUC_ALIGN' as their second argument (overriding `PAGE_SIZE').
Cc: stable@vger.kernel.org
Fixes: 84d15f426110 ("drm/xe/guc: Add capture size check in GuC log buffer")
Fixes: 9c8c7a7e6f1f ("drm/xe/guc: Prepare GuC register list and update ADS size for error capture")
Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Tested-by: Mingcong Bai <jeffbai@aosc.io>
Tested-by: Wenbin Fang <fangwenbin@vip.qq.com>
Tested-by: Haien Liang <27873200@qq.com>
Tested-by: Jianfeng Liu <liujianfeng1994@gmail.com>
Tested-by: Shirong Liu <lsr1024@qq.com>
Tested-by: Haofeng Wu <s2600cw2@126.com>
Link: https://github.com/FanFansfan/loongson-linux/commit/22c55ab3931c32410a077b3ddb6dca3f28223360
Link: https://t.me/c/1109254909/768552
Co-developed-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
---
drivers/gpu/drm/xe/xe_guc.c | 4 +-
drivers/gpu/drm/xe/xe_guc.h | 3 +
drivers/gpu/drm/xe/xe_guc_ads.c | 32 +++++-----
drivers/gpu/drm/xe/xe_guc_capture.c | 8 +--
drivers/gpu/drm/xe/xe_guc_ct.c | 2 +-
drivers/gpu/drm/xe/xe_guc_log.c | 5 +-
drivers/gpu/drm/xe/xe_guc_pc.c | 4 +-
7 files changed, 31 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -101,7 +101,7 @@ static u32 guc_ctl_feature_flags(struct xe_guc *guc)
static u32 guc_ctl_log_params_flags(struct xe_guc *guc)
{
- u32 offset = guc_bo_ggtt_addr(guc, guc->log.bo) >> PAGE_SHIFT;
+ u32 offset = guc_bo_ggtt_addr(guc, guc->log.bo) >> XE_PTE_SHIFT;
u32 flags;
#if (((CRASH_BUFFER_SIZE) % SZ_1M) == 0)
@@ -146,7 +146,7 @@ static u32 guc_ctl_log_params_flags(struct xe_guc *guc)
static u32 guc_ctl_ads_flags(struct xe_guc *guc)
{
- u32 ads = guc_bo_ggtt_addr(guc, guc->ads.bo) >> PAGE_SHIFT;
+ u32 ads = guc_bo_ggtt_addr(guc, guc->ads.bo) >> XE_PTE_SHIFT;
u32 flags = FIELD_PREP(GUC_ADS_ADDR, ads);
return flags;
diff --git a/drivers/gpu/drm/xe/xe_guc.h b/drivers/gpu/drm/xe/xe_guc.h
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_guc.h
+++ b/drivers/gpu/drm/xe/xe_guc.h
@@ -23,6 +23,9 @@
#define GUC_FIRMWARE_VER(guc) \
MAKE_GUC_VER_STRUCT((guc)->fw.versions.found[XE_UC_FW_VER_RELEASE])
+/* GuC really expects command buffers aligned to 4K boundaries. */
+#define GUC_ALIGN SZ_4K
+
struct drm_printer;
void xe_guc_comm_init_early(struct xe_guc *guc);
diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_guc_ads.c
+++ b/drivers/gpu/drm/xe/xe_guc_ads.c
@@ -144,17 +144,17 @@ static size_t guc_ads_regset_size(struct xe_guc_ads *ads)
static size_t guc_ads_golden_lrc_size(struct xe_guc_ads *ads)
{
- return PAGE_ALIGN(ads->golden_lrc_size);
+ return ALIGN(ads->golden_lrc_size, GUC_ALIGN);
}
static u32 guc_ads_waklv_size(struct xe_guc_ads *ads)
{
- return PAGE_ALIGN(ads->ads_waklv_size);
+ return ALIGN(ads->ads_waklv_size, GUC_ALIGN);
}
static size_t guc_ads_capture_size(struct xe_guc_ads *ads)
{
- return PAGE_ALIGN(ads->capture_size);
+ return ALIGN(ads->capture_size, GUC_ALIGN);
}
static size_t guc_ads_um_queues_size(struct xe_guc_ads *ads)
@@ -169,7 +169,7 @@ static size_t guc_ads_um_queues_size(struct xe_guc_ads *ads)
static size_t guc_ads_private_data_size(struct xe_guc_ads *ads)
{
- return PAGE_ALIGN(ads_to_guc(ads)->fw.private_data_size);
+ return ALIGN(ads_to_guc(ads)->fw.private_data_size, GUC_ALIGN);
}
static size_t guc_ads_regset_offset(struct xe_guc_ads *ads)
@@ -184,7 +184,7 @@ static size_t guc_ads_golden_lrc_offset(struct xe_guc_ads *ads)
offset = guc_ads_regset_offset(ads) +
guc_ads_regset_size(ads);
- return PAGE_ALIGN(offset);
+ return ALIGN(offset, GUC_ALIGN);
}
static size_t guc_ads_waklv_offset(struct xe_guc_ads *ads)
@@ -194,7 +194,7 @@ static size_t guc_ads_waklv_offset(struct xe_guc_ads *ads)
offset = guc_ads_golden_lrc_offset(ads) +
guc_ads_golden_lrc_size(ads);
- return PAGE_ALIGN(offset);
+ return ALIGN(offset, GUC_ALIGN);
}
static size_t guc_ads_capture_offset(struct xe_guc_ads *ads)
@@ -204,7 +204,7 @@ static size_t guc_ads_capture_offset(struct xe_guc_ads *ads)
offset = guc_ads_waklv_offset(ads) +
guc_ads_waklv_size(ads);
- return PAGE_ALIGN(offset);
+ return ALIGN(offset, GUC_ALIGN);
}
static size_t guc_ads_um_queues_offset(struct xe_guc_ads *ads)
@@ -214,7 +214,7 @@ static size_t guc_ads_um_queues_offset(struct xe_guc_ads *ads)
offset = guc_ads_capture_offset(ads) +
guc_ads_capture_size(ads);
- return PAGE_ALIGN(offset);
+ return ALIGN(offset, GUC_ALIGN);
}
static size_t guc_ads_private_data_offset(struct xe_guc_ads *ads)
@@ -224,7 +224,7 @@ static size_t guc_ads_private_data_offset(struct xe_guc_ads *ads)
offset = guc_ads_um_queues_offset(ads) +
guc_ads_um_queues_size(ads);
- return PAGE_ALIGN(offset);
+ return ALIGN(offset, GUC_ALIGN);
}
static size_t guc_ads_size(struct xe_guc_ads *ads)
@@ -277,7 +277,7 @@ static size_t calculate_golden_lrc_size(struct xe_guc_ads *ads)
continue;
real_size = xe_gt_lrc_size(gt, class);
- alloc_size = PAGE_ALIGN(real_size);
+ alloc_size = ALIGN(real_size, GUC_ALIGN);
total_size += alloc_size;
}
@@ -628,12 +628,12 @@ static int guc_capture_prep_lists(struct xe_guc_ads *ads)
offsetof(struct __guc_ads_blob, system_info));
/* first, set aside the first page for a capture_list with zero descriptors */
- total_size = PAGE_SIZE;
+ total_size = GUC_ALIGN;
if (!xe_guc_capture_getnullheader(guc, &ptr, &size))
xe_map_memcpy_to(ads_to_xe(ads), ads_to_map(ads), capture_offset, ptr, size);
null_ggtt = ads_ggtt + capture_offset;
- capture_offset += PAGE_SIZE;
+ capture_offset += GUC_ALIGN;
/*
* Populate capture list : at this point adps is already allocated and
@@ -697,10 +697,10 @@ static int guc_capture_prep_lists(struct xe_guc_ads *ads)
}
}
- if (ads->capture_size != PAGE_ALIGN(total_size))
+ if (ads->capture_size != ALIGN(total_size, GUC_ALIGN))
xe_gt_dbg(gt, "Updated ADS capture size %d (was %d)\n",
- PAGE_ALIGN(total_size), ads->capture_size);
- return PAGE_ALIGN(total_size);
+ ALIGN(total_size, GUC_ALIGN), ads->capture_size);
+ return ALIGN(total_size, GUC_ALIGN);
}
static void guc_mmio_regset_write_one(struct xe_guc_ads *ads,
@@ -952,7 +952,7 @@ static void guc_golden_lrc_populate(struct xe_guc_ads *ads)
xe_gt_assert(gt, gt->default_lrc[class]);
real_size = xe_gt_lrc_size(gt, class);
- alloc_size = PAGE_ALIGN(real_size);
+ alloc_size = ALIGN(real_size, GUC_ALIGN);
total_size += alloc_size;
xe_map_memcpy_to(xe, ads_to_map(ads), offset,
diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_guc_capture.c
+++ b/drivers/gpu/drm/xe/xe_guc_capture.c
@@ -618,8 +618,8 @@ guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type,
return -ENODATA;
if (size)
- *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) +
- (num_regs * sizeof(struct guc_mmio_reg)));
+ *size = ALIGN((sizeof(struct guc_debug_capture_list)) +
+ (num_regs * sizeof(struct guc_mmio_reg)), GUC_ALIGN);
return 0;
}
@@ -766,7 +766,7 @@ size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc)
* sequence, that is, during the pre-hwconfig phase before we have
* the exact engine fusing info.
*/
- total_size = PAGE_SIZE; /* Pad a page in front for empty lists */
+ total_size = GUC_ALIGN; /* Pad a page in front for empty lists */
for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) {
for (j = 0; j < GUC_CAPTURE_LIST_CLASS_MAX; j++) {
if (xe_guc_capture_getlistsize(guc, i,
@@ -786,7 +786,7 @@ size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc)
total_size += global_size;
}
- return PAGE_ALIGN(total_size);
+ return ALIGN(total_size, GUC_ALIGN);
}
static int guc_capture_output_size_est(struct xe_guc *guc)
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -225,7 +225,7 @@ int xe_guc_ct_init_noalloc(struct xe_guc_ct *ct)
struct xe_gt *gt = ct_to_gt(ct);
int err;
- xe_gt_assert(gt, !(guc_ct_size() % PAGE_SIZE));
+ xe_gt_assert(gt, !(guc_ct_size() % GUC_ALIGN));
err = drmm_mutex_init(&xe->drm, &ct->lock);
if (err)
diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_guc_log.c
+++ b/drivers/gpu/drm/xe/xe_guc_log.c
@@ -15,6 +15,7 @@
#include "xe_force_wake.h"
#include "xe_gt.h"
#include "xe_gt_printk.h"
+#include "xe_guc.h"
#include "xe_map.h"
#include "xe_mmio.h"
#include "xe_module.h"
@@ -58,7 +59,7 @@ static size_t guc_log_size(void)
* | Capture logs |
* +===============================+ + CAPTURE_SIZE
*/
- return PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE +
+ return GUC_ALIGN + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE +
CAPTURE_BUFFER_SIZE;
}
@@ -328,7 +329,7 @@ u32 xe_guc_get_log_buffer_size(struct xe_guc_log *log, enum guc_log_buffer_type
u32 xe_guc_get_log_buffer_offset(struct xe_guc_log *log, enum guc_log_buffer_type type)
{
enum guc_log_buffer_type i;
- u32 offset = PAGE_SIZE;/* for the log_buffer_states */
+ u32 offset = GUC_ALIGN; /* for the log_buffer_states */
for (i = GUC_LOG_BUFFER_CRASH_DUMP; i < GUC_LOG_BUFFER_TYPE_MAX; ++i) {
if (i == type)
diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_guc_pc.c
+++ b/drivers/gpu/drm/xe/xe_guc_pc.c
@@ -1222,7 +1222,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
{
struct xe_device *xe = pc_to_xe(pc);
struct xe_gt *gt = pc_to_gt(pc);
- u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));
+ u32 size = ALIGN(sizeof(struct slpc_shared_data), GUC_ALIGN);
unsigned int fw_ref;
ktime_t earlier;
int ret;
@@ -1355,7 +1355,7 @@ int xe_guc_pc_init(struct xe_guc_pc *pc)
struct xe_tile *tile = gt_to_tile(gt);
struct xe_device *xe = gt_to_xe(gt);
struct xe_bo *bo;
- u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));
+ u32 size = ALIGN(sizeof(struct slpc_shared_data), GUC_ALIGN);
int err;
if (xe->info.skip_guc_pc)
--
Armbian
@@ -1,98 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mingcong Bai <jeffbai@aosc.io>
Date: Wed, 23 Jul 2025 16:45:15 +0900
Subject: drm/xe/regs: fix RING_CTL_SIZE(size) calculation
Similar to the preceding patch for GuC (and with the same references),
Intel GPUs expects command buffers to align to 4KiB boundaries.
Current code uses `PAGE_SIZE' as an assumed alignment reference but 4KiB
kernel page sizes is by no means a guarantee. On 16KiB-paged kernels, this
causes driver failures during boot up:
[ 14.018975] ------------[ cut here ]------------
[ 14.023562] xe 0000:09:00.0: [drm] GT0: Kernel-submitted job timed out
[ 14.030084] WARNING: CPU: 3 PID: 564 at drivers/gpu/drm/xe/xe_guc_submit.c:1181 guc_exec_queue_timedout_job+0x1c0/0xacc [xe]
[ 14.041300] Modules linked in: nf_conntrack_netbios_ns(E) nf_conntrack_broadcast(E) nft_fib_inet(E) nft_fib_ipv4(E) nft_fib_ipv6(E) nft_fib(E) nft_reject_inet(E) nf_reject_ipv4(E) nf_reject_ipv6(E) nft_reject(E) nft_ct(E) nft_chain_nat(E) ip6table_nat(E) ip6table_mangle(E) ip6table_raw(E) ip6table_security(E) iptable_nat(E) nf_nat(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) rfkill(E) iptable_mangle(E) iptable_raw(E) iptable_security(E) ip_set(E) nf_tables(E) ip6table_filter(E) ip6_tables(E) iptable_filter(E) snd_hda_codec_conexant(E) snd_hda_codec_generic(E) snd_hda_codec_hdmi(E) nls_iso8859_1(E) snd_hda_intel(E) snd_intel_dspcfg(E) qrtr(E) nls_cp437(E) snd_hda_codec(E) spi_loongson_pci(E) rtc_efi(E) snd_hda_core(E) loongson3_cpufreq(E) spi_loongson_core(E) snd_hwdep(E) snd_pcm(E) snd_timer(E) snd(E) soundcore(E) gpio_loongson_64bit(E) input_leds(E) rtc_loongson(E) i2c_ls2x(E) mousedev(E) sch_fq_codel(E) fuse(E) nfnetlink(E) dmi_sysfs(E) ip_tables(E) x_tables(E) xe(E) d
rm_gpuvm(E) drm_buddy(E) gpu_sched(E)
[ 14.041369] drm_exec(E) drm_suballoc_helper(E) drm_display_helper(E) cec(E) rc_core(E) hid_generic(E) tpm_tis_spi(E) r8169(E) realtek(E) led_class(E) loongson(E) i2c_algo_bit(E) drm_ttm_helper(E) ttm(E) drm_client_lib(E) drm_kms_helper(E) sunrpc(E) i2c_dev(E)
[ 14.153910] CPU: 3 UID: 0 PID: 564 Comm: kworker/u32:2 Tainted: G E 6.14.0-rc4-aosc-main-gbad70b1cd8b0-dirty #7
[ 14.165325] Tainted: [E]=UNSIGNED_MODULE
[ 14.169220] Hardware name: Loongson Loongson-3A6000-HV-7A2000-1w-V0.1-EVB/Loongson-3A6000-HV-7A2000-1w-EVB-V1.21, BIOS Loongson-UDK2018-V4.0.05756-prestab
[ 14.182970] Workqueue: gt-ordered-wq drm_sched_job_timedout [gpu_sched]
[ 14.189549] pc ffff8000024f3760 ra ffff8000024f3760 tp 900000012f150000 sp 900000012f153ca0
[ 14.197853] a0 0000000000000000 a1 0000000000000000 a2 0000000000000000 a3 0000000000000000
[ 14.206156] a4 0000000000000000 a5 0000000000000000 a6 0000000000000000 a7 0000000000000000
[ 14.214458] t0 0000000000000000 t1 0000000000000000 t2 0000000000000000 t3 0000000000000000
[ 14.222761] t4 0000000000000000 t5 0000000000000000 t6 0000000000000000 t7 0000000000000000
[ 14.231064] t8 0000000000000000 u0 900000000195c0c8 s9 900000012e4dcf48 s0 90000001285f3640
[ 14.239368] s1 90000001004f8000 s2 ffff8000026ec000 s3 0000000000000000 s4 900000012e4dc028
[ 14.247672] s5 90000001009f5e00 s6 000000000000137e s7 0000000000000001 s8 900000012f153ce8
[ 14.255975] ra: ffff8000024f3760 guc_exec_queue_timedout_job+0x1c0/0xacc [xe]
[ 14.263379] ERA: ffff8000024f3760 guc_exec_queue_timedout_job+0x1c0/0xacc [xe]
[ 14.270777] CRMD: 000000b0 (PLV0 -IE -DA +PG DACF=CC DACM=CC -WE)
[ 14.276927] PRMD: 00000004 (PPLV0 +PIE -PWE)
[ 14.281258] EUEN: 00000000 (-FPE -SXE -ASXE -BTE)
[ 14.286024] ECFG: 00071c1d (LIE=0,2-4,10-12 VS=7)
[ 14.290790] ESTAT: 000c0000 [BRK] (IS= ECode=12 EsubCode=0)
[ 14.296329] PRID: 0014d000 (Loongson-64bit, Loongson-3A6000-HV)
[ 14.302299] CPU: 3 UID: 0 PID: 564 Comm: kworker/u32:2 Tainted: G E 6.14.0-rc4-aosc-main-gbad70b1cd8b0-dirty #7
[ 14.302302] Tainted: [E]=UNSIGNED_MODULE
[ 14.302302] Hardware name: Loongson Loongson-3A6000-HV-7A2000-1w-V0.1-EVB/Loongson-3A6000-HV-7A2000-1w-EVB-V1.21, BIOS Loongson-UDK2018-V4.0.05756-prestab
[ 14.302304] Workqueue: gt-ordered-wq drm_sched_job_timedout [gpu_sched]
[ 14.302307] Stack : 900000012f153928 d84a6232d48f1ac7 900000000023eb34 900000012f150000
[ 14.302310] 900000012f153900 0000000000000000 900000012f153908 9000000001c31c70
[ 14.302313] 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[ 14.302315] 0000000000000000 d84a6232d48f1ac7 0000000000000000 0000000000000000
[ 14.302318] 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[ 14.302320] 0000000000000000 0000000000000000 00000000072b4000 900000012e4dcf48
[ 14.302323] 9000000001eb8000 0000000000000000 9000000001c31c70 0000000000000004
[ 14.302325] 0000000000000004 0000000000000000 000000000000137e 0000000000000001
[ 14.302328] 900000012f153ce8 9000000001c31c70 9000000000244174 0000555581840b98
[ 14.302331] 00000000000000b0 0000000000000004 0000000000000000 0000000000071c1d
[ 14.302333] ...
[ 14.302335] Call Trace:
[ 14.302336] [<9000000000244174>] show_stack+0x3c/0x16c
[ 14.302341] [<900000000023eb30>] dump_stack_lvl+0x84/0xe0
[ 14.302346] [<9000000000288208>] __warn+0x8c/0x174
[ 14.302350] [<90000000017c1918>] report_bug+0x1c0/0x22c
[ 14.302354] [<90000000017f66e8>] do_bp+0x280/0x344
[ 14.302359]
[ 14.302360] ---[ end trace 0000000000000000 ]---
Revise calculation of `RING_CTL_SIZE(size)' to use `SZ_4K' to fix the
aforementioned issue.
Cc: stable@vger.kernel.org
Fixes: b79e8fd954c4 ("drm/xe: Remove dependency on intel_engine_regs.h")
Tested-by: Mingcong Bai <jeffbai@aosc.io>
Tested-by: Wenbin Fang <fangwenbin@vip.qq.com>
Tested-by: Haien Liang <27873200@qq.com>
Tested-by: Jianfeng Liu <liujianfeng1994@gmail.com>
Tested-by: Shirong Liu <lsr1024@qq.com>
Tested-by: Haofeng Wu <s2600cw2@126.com>
Link: https://github.com/FanFansfan/loongson-linux/commit/22c55ab3931c32410a077b3ddb6dca3f28223360
Link: https://t.me/c/1109254909/768552
Co-developed-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
---
drivers/gpu/drm/xe/regs/xe_engine_regs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
@@ -56,7 +56,7 @@
#define RING_START(base) XE_REG((base) + 0x38)
#define RING_CTL(base) XE_REG((base) + 0x3c)
-#define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */
+#define RING_CTL_SIZE(size) ((size) - SZ_4K) /* in bytes -> pages */
#define RING_START_UDW(base) XE_REG((base) + 0x48)
--
Armbian
@@ -1,121 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mingcong Bai <jeffbai@aosc.io>
Date: Wed, 23 Jul 2025 16:45:16 +0900
Subject: drm/xe: use 4KiB alignment for cursor jumps
It appears that the xe_res_cursor also assumes 4KiB alignment.
Current implementation uses `PAGE_SIZE' as an assumed alignment reference,
but 4KiB kernel page sizes is by no means a guarantee. On 16KiB-paged
kernels, this causes driver failures during boot up:
[ 23.242757] ------------[ cut here ]------------
[ 23.247363] WARNING: CPU: 0 PID: 2036 at drivers/gpu/drm/xe/xe_res_cursor.h:182 emit_pte+0x394/0x3b0 [xe]
[ 23.256962] Modules linked in: nf_conntrack_netbios_ns(E) nf_conntrack_broadcast(E) nft_fib_inet(E) nft_fib_ipv4(E) nft_fib_ipv6(E) nft_fib(E) nft_reject_inet(E) nf_reject_ipv4(E) nf_reject_ipv6(E) nft_reject(E) nft_ct(E) rfkill(E) nft_chain_nat(E) ip6table_nat(E) ip6table_mangle(E) ip6table_raw(E) ip6table_security(E) iptable_nat(E) nf_nat(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) iptable_mangle(E) iptable_raw(E) iptable_security(E) ip_set(E) nf_tables(E) ip6table_filter(E) ip6_tables(E) iptable_filter(E) snd_hda_codec_conexant(E) snd_hda_codec_generic(E) snd_hda_codec_hdmi(E) snd_hda_intel(E) snd_intel_dspcfg(E) snd_hda_codec(E) nls_iso8859_1(E) qrtr(E) nls_cp437(E) snd_hda_core(E) loongson3_cpufreq(E) rtc_efi(E) snd_hwdep(E) snd_pcm(E) spi_loongson_pci(E) snd_timer(E) snd(E) spi_loongson_core(E) soundcore(E) gpio_loongson_64bit(E) rtc_loongson(E) i2c_ls2x(E) mousedev(E) input_leds(E) sch_fq_codel(E) fuse(E) nfnetlink(E) dmi_sysfs(E) ip_tables(E) x_tables(E) xe(E) d
rm_gpuvm(E) drm_buddy(E) gpu_sched(E)
[ 23.257034] drm_exec(E) drm_suballoc_helper(E) drm_display_helper(E) cec(E) rc_core(E) hid_generic(E) tpm_tis_spi(E) r8169(E) loongson(E) i2c_algo_bit(E) realtek(E) drm_ttm_helper(E) led_class(E) ttm(E) drm_client_lib(E) drm_kms_helper(E) sunrpc(E) i2c_dev(E)
[ 23.369697] CPU: 0 UID: 1000 PID: 2036 Comm: QSGRenderThread Tainted: G E 6.14.0-rc4-aosc-main-g7cc07e6e50b0-dirty #8
[ 23.381640] Tainted: [E]=UNSIGNED_MODULE
[ 23.385534] Hardware name: Loongson Loongson-3A6000-HV-7A2000-1w-V0.1-EVB/Loongson-3A6000-HV-7A2000-1w-EVB-V1.21, BIOS Loongson-UDK2018-V4.0.05756-prestab
[ 23.399319] pc ffff80000251efc0 ra ffff80000251eddc tp 900000011fe3c000 sp 900000011fe3f7e0
[ 23.407632] a0 0000000000000001 a1 0000000000000000 a2 0000000000000000 a3 0000000000000000
[ 23.415938] a4 0000000000000000 a5 0000000000000000 a6 0000000000060000 a7 900000010c947b00
[ 23.424240] t0 0000000000000000 t1 0000000000000000 t2 0000000000000000 t3 900000012e456230
[ 23.432543] t4 0000000000000035 t5 0000000000004000 t6 00000001fbc40403 t7 0000000000004000
[ 23.440845] t8 9000000100e688a8 u0 5cc06cee8ef0edee s9 9000000100024420 s0 0000000000000047
[ 23.449147] s1 0000000000004000 s2 0000000000000001 s3 900000012adba000 s4 ffffffffffffc000
[ 23.457450] s5 9000000108939428 s6 0000000000000000 s7 0000000000000000 s8 900000011fe3f8e0
[ 23.465851] ra: ffff80000251eddc emit_pte+0x1b0/0x3b0 [xe]
[ 23.471761] ERA: ffff80000251efc0 emit_pte+0x394/0x3b0 [xe]
[ 23.477557] CRMD: 000000b0 (PLV0 -IE -DA +PG DACF=CC DACM=CC -WE)
[ 23.483732] PRMD: 00000004 (PPLV0 +PIE -PWE)
[ 23.488068] EUEN: 00000003 (+FPE +SXE -ASXE -BTE)
[ 23.492832] ECFG: 00071c1d (LIE=0,2-4,10-12 VS=7)
[ 23.497594] ESTAT: 000c0000 [BRK] (IS= ECode=12 EsubCode=0)
[ 23.503133] PRID: 0014d000 (Loongson-64bit, Loongson-3A6000-HV)
[ 23.509164] CPU: 0 UID: 1000 PID: 2036 Comm: QSGRenderThread Tainted: G E 6.14.0-rc4-aosc-main-g7cc07e6e50b0-dirty #8
[ 23.509168] Tainted: [E]=UNSIGNED_MODULE
[ 23.509168] Hardware name: Loongson Loongson-3A6000-HV-7A2000-1w-V0.1-EVB/Loongson-3A6000-HV-7A2000-1w-EVB-V1.21, BIOS Loongson-UDK2018-V4.0.05756-prestab
[ 23.509170] Stack : ffffffffffffffff ffffffffffffffff 900000000023eb34 900000011fe3c000
[ 23.509176] 900000011fe3f440 0000000000000000 900000011fe3f448 9000000001c31c70
[ 23.509181] 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[ 23.509185] 0000000000000000 5cc06cee8ef0edee 0000000000000000 0000000000000000
[ 23.509190] 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[ 23.509193] 0000000000000000 0000000000000000 00000000066b4000 9000000100024420
[ 23.509197] 9000000001eb8000 0000000000000000 9000000001c31c70 0000000000000004
[ 23.509202] 0000000000000004 0000000000000000 0000000000000000 0000000000000000
[ 23.509206] 900000011fe3f8e0 9000000001c31c70 9000000000244174 00007fffac097534
[ 23.509211] 00000000000000b0 0000000000000004 0000000000000003 0000000000071c1d
[ 23.509216] ...
[ 23.509218] Call Trace:
[ 23.509220] [<9000000000244174>] show_stack+0x3c/0x16c
[ 23.509226] [<900000000023eb30>] dump_stack_lvl+0x84/0xe0
[ 23.509230] [<9000000000288208>] __warn+0x8c/0x174
[ 23.509234] [<90000000017c1918>] report_bug+0x1c0/0x22c
[ 23.509238] [<90000000017f66e8>] do_bp+0x280/0x344
[ 23.509243] [<90000000002428a0>] handle_bp+0x120/0x1c0
[ 23.509247] [<ffff80000251efc0>] emit_pte+0x394/0x3b0 [xe]
[ 23.509295] [<ffff800002520d38>] xe_migrate_clear+0x2d8/0xa54 [xe]
[ 23.509341] [<ffff8000024e6c38>] xe_bo_move+0x324/0x930 [xe]
[ 23.509387] [<ffff800002209468>] ttm_bo_handle_move_mem+0xd0/0x194 [ttm]
[ 23.509392] [<ffff800002209ebc>] ttm_bo_validate+0xd4/0x1cc [ttm]
[ 23.509396] [<ffff80000220a138>] ttm_bo_init_reserved+0x184/0x1dc [ttm]
[ 23.509399] [<ffff8000024e7840>] ___xe_bo_create_locked+0x1e8/0x3d4 [xe]
[ 23.509445] [<ffff8000024e7cf8>] __xe_bo_create_locked+0x2cc/0x390 [xe]
[ 23.509489] [<ffff8000024e7e98>] xe_bo_create_user+0x34/0xe4 [xe]
[ 23.509533] [<ffff8000024e875c>] xe_gem_create_ioctl+0x154/0x4d8 [xe]
[ 23.509578] [<9000000001062784>] drm_ioctl_kernel+0xe0/0x14c
[ 23.509582] [<9000000001062c10>] drm_ioctl+0x420/0x5f4
[ 23.509585] [<ffff8000024ea778>] xe_drm_ioctl+0x64/0xac [xe]
[ 23.509630] [<9000000000653504>] sys_ioctl+0x2b8/0xf98
[ 23.509634] [<90000000017f684c>] do_syscall+0xa0/0x140
[ 23.509637] [<9000000000241e38>] handle_syscall+0xb8/0x158
[ 23.509640]
[ 23.509644] ---[ end trace 0000000000000000 ]---
Revise calls to `xe_res_dma()' and `xe_res_cursor()' to use
`XE_PTE_MASK' (12) and `SZ_4K' to fix this potentially confused use of
`PAGE_SIZE' in relevant code.
Cc: stable@vger.kernel.org
Fixes: e89b384cde62 ("drm/xe/migrate: Update emit_pte to cope with a size level than 4k")
Tested-by: Mingcong Bai <jeffbai@aosc.io>
Tested-by: Wenbin Fang <fangwenbin@vip.qq.com>
Tested-by: Haien Liang <27873200@qq.com>
Tested-by: Jianfeng Liu <liujianfeng1994@gmail.com>
Tested-by: Shirong Liu <lsr1024@qq.com>
Tested-by: Haofeng Wu <s2600cw2@126.com>
Link: https://github.com/FanFansfan/loongson-linux/commit/22c55ab3931c32410a077b3ddb6dca3f28223360
Link: https://t.me/c/1109254909/768552
Co-developed-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
---
drivers/gpu/drm/xe/xe_migrate.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -631,7 +631,7 @@ static void emit_pte(struct xe_migrate *m,
u64 addr, flags = 0;
bool devmem = false;
- addr = xe_res_dma(cur) & PAGE_MASK;
+ addr = xe_res_dma(cur) & ~XE_PTE_MASK;
if (is_vram) {
if (vm->flags & XE_VM_FLAG_64K) {
u64 va = cur_ofs * XE_PAGE_SIZE / 8;
@@ -652,7 +652,7 @@ static void emit_pte(struct xe_migrate *m,
bb->cs[bb->len++] = lower_32_bits(addr);
bb->cs[bb->len++] = upper_32_bits(addr);
- xe_res_next(cur, min_t(u32, size, PAGE_SIZE));
+ xe_res_next(cur, min_t(u32, size, XE_PAGE_SIZE));
cur_ofs += 8;
}
}
--
Armbian
@@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mingcong Bai <jeffbai@aosc.io>
Date: Wed, 23 Jul 2025 16:45:17 +0900
Subject: drm/xe/query: use PAGE_SIZE as the minimum page alignment
As this component hooks into userspace API, it should be assumed that it
will play well with non-4KiB/64KiB pages.
Use `PAGE_SIZE' as the final reference for page alignment instead.
Cc: stable@vger.kernel.org
Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Fixes: 801989b08aff ("drm/xe/uapi: Make constant comments visible in kernel doc")
Tested-by: Mingcong Bai <jeffbai@aosc.io>
Tested-by: Wenbin Fang <fangwenbin@vip.qq.com>
Tested-by: Haien Liang <27873200@qq.com>
Tested-by: Jianfeng Liu <liujianfeng1994@gmail.com>
Tested-by: Shirong Liu <lsr1024@qq.com>
Tested-by: Haofeng Wu <s2600cw2@126.com>
Link: https://github.com/FanFansfan/loongson-linux/commit/22c55ab3931c32410a077b3ddb6dca3f28223360
Link: https://t.me/c/1109254909/768552
Co-developed-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Shang Yatsen <429839446@qq.com>
Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
---
drivers/gpu/drm/xe/xe_query.c | 2 +-
include/uapi/drm/xe_drm.h | 7 +++++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/xe_query.c
+++ b/drivers/gpu/drm/xe/xe_query.c
@@ -345,7 +345,7 @@ static int query_config(struct xe_device *xe, struct drm_xe_device_query *query)
config->info[DRM_XE_QUERY_CONFIG_FLAGS] |=
DRM_XE_QUERY_CONFIG_FLAG_HAS_LOW_LATENCY;
config->info[DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT] =
- xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K;
+ xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : PAGE_SIZE;
config->info[DRM_XE_QUERY_CONFIG_VA_BITS] = xe->info.va_bits;
config->info[DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY] =
xe_exec_queue_device_get_max_priority(xe);
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 111111111111..222222222222 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -403,8 +403,11 @@ struct drm_xe_query_mem_regions {
* has low latency hint support
* - %DRM_XE_QUERY_CONFIG_FLAG_HAS_CPU_ADDR_MIRROR - Flag is set if the
* device has CPU address mirroring support
- * - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment
- * required by this device, typically SZ_4K or SZ_64K
+ * - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment required
+ * by this device and the CPU. The minimum page size for the device is
+ * usually SZ_4K or SZ_64K, while for the CPU, it is PAGE_SIZE. This value
+ * is calculated by max(min_gpu_page_size, PAGE_SIZE). This alignment is
+ * enforced on buffer object allocations and VM binds.
* - %DRM_XE_QUERY_CONFIG_VA_BITS - Maximum bits of a virtual address
* - %DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY - Value of the highest
* available exec queue priority
--
Armbian
@@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jianfeng Liu <liujianfeng1994@gmail.com>
Date: Tue, 16 Sep 2025 09:14:47 +0800
Subject: gpu: xe: enable build with 16KB page size
---
drivers/gpu/drm/xe/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -5,7 +5,7 @@ config DRM_XE
depends on KUNIT || !KUNIT
depends on INTEL_VSEC || !INTEL_VSEC
depends on X86_PLATFORM_DEVICES || !(X86 && ACPI)
- depends on PAGE_SIZE_4KB || COMPILE_TEST || BROKEN
+ depends on PAGE_SIZE_4KB || PAGE_SIZE_16KB || COMPILE_TEST || BROKEN
select INTERVAL_TREE
# we need shmfs for the swappable backing store, and in particular
# the shmem_readpage() which depends upon tmpfs
--
Armbian
File diff suppressed because it is too large Load Diff
@@ -1,77 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Redecorating <69827514+Redecorating@users.noreply.github.com>
Date: Mon, 7 Nov 2022 14:56:34 +0530
Subject: Put apple-bce in drivers/staging
- rpardini: 6.12: in drivers/staging/Makefile do it at the top to avoid
conflicts with Armbian's (wifi?) patching.
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
drivers/staging/Kconfig | 2 ++
drivers/staging/Makefile | 1 +
drivers/staging/apple-bce/Kconfig | 18 ++++++++++
drivers/staging/apple-bce/Makefile | 2 +-
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -48,4 +48,6 @@ source "drivers/staging/axis-fifo/Kconfig"
source "drivers/staging/vme_user/Kconfig"
+source "drivers/staging/apple-bce/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 111111111111..222222222222 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -2,6 +2,7 @@
# Makefile for staging directory
obj-y += media/
+obj-$(CONFIG_APPLE_BCE) += apple-bce/
obj-$(CONFIG_RTL8723BS) += rtl8723bs/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_VME_BUS) += vme_user/
diff --git a/drivers/staging/apple-bce/Kconfig b/drivers/staging/apple-bce/Kconfig
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/staging/apple-bce/Kconfig
@@ -0,0 +1,18 @@
+config APPLE_BCE
+ tristate "Apple BCE driver (VHCI and Audio support)"
+ default m
+ depends on X86
+ select SOUND
+ select SND
+ select SND_PCM
+ select SND_JACK
+ help
+ VHCI and audio support on Apple MacBooks with the T2 Chip.
+ This driver is divided in three components:
+ - BCE (Buffer Copy Engine): which establishes a basic communication
+ channel with the T2 chip. This component is required by the other two:
+ - VHCI (Virtual Host Controller Interface): Access to keyboard, mouse
+ and other system devices depend on this virtual USB host controller
+ - Audio: a driver for the T2 audio interface.
+
+ If "M" is selected, the module will be called apple-bce.'
diff --git a/drivers/staging/apple-bce/Makefile b/drivers/staging/apple-bce/Makefile
index 111111111111..222222222222 100644
--- a/drivers/staging/apple-bce/Makefile
+++ b/drivers/staging/apple-bce/Makefile
@@ -1,5 +1,5 @@
modname := apple-bce
-obj-m += $(modname).o
+obj-$(CONFIG_APPLE_BCE) += $(modname).o
apple-bce-objs := apple_bce.o mailbox.o queue.o queue_dma.o vhci/vhci.o vhci/queue.o vhci/transfer.o audio/audio.o audio/protocol.o audio/protocol_bce.o audio/pcm.o
--
Armbian
@@ -1,72 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: mnural <mehmet.nrl@hotmail.com>
Date: Mon, 14 Apr 2025 14:44:20 +0530
Subject: Fix freezing on turning off camera
Detailed logs and reason behind can be seen here:
https://github.com/t2linux/T2-Debian-and-Ubuntu-Kernel/issues/130#issuecomment-2799130835
---
drivers/staging/apple-bce/vhci/transfer.c | 16 ++++++++--
drivers/staging/apple-bce/vhci/transfer.h | 4 ++-
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/apple-bce/vhci/transfer.c b/drivers/staging/apple-bce/vhci/transfer.c
index 111111111111..222222222222 100644
--- a/drivers/staging/apple-bce/vhci/transfer.c
+++ b/drivers/staging/apple-bce/vhci/transfer.c
@@ -400,6 +400,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
struct bce_vhci_urb *vurb;
unsigned long flags;
int ret;
+ enum bce_vhci_urb_state old_state;
spin_lock_irqsave(&q->urb_lock, flags);
if ((ret = usb_hcd_check_unlink_urb(q->vhci->hcd, urb, status))) {
@@ -408,8 +409,19 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
}
vurb = urb->hcpriv;
+
+ old_state = vurb->state; /* save old state to use later because we'll set state as cancelled */
+
+ if (old_state == BCE_VHCI_URB_CANCELLED) {
+ spin_unlock_irqrestore(&q->urb_lock, flags);
+ pr_debug("bce-vhci: URB %p is already cancelled, skipping\n", urb);
+ return 0;
+ }
+
+ vurb->state = BCE_VHCI_URB_CANCELLED;
+
/* If the URB wasn't posted to the device yet, we can still remove it on the host without pausing the queue. */
- if (vurb->state != BCE_VHCI_URB_INIT_PENDING) {
+ if (old_state != BCE_VHCI_URB_INIT_PENDING) {
pr_debug("bce-vhci: [%02x] Cancelling URB\n", q->endp_addr);
spin_unlock_irqrestore(&q->urb_lock, flags);
@@ -425,7 +437,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
usb_hcd_giveback_urb(q->vhci->hcd, urb, status);
- if (vurb->state != BCE_VHCI_URB_INIT_PENDING)
+ if (old_state != BCE_VHCI_URB_INIT_PENDING)
bce_vhci_transfer_queue_resume(q, BCE_VHCI_PAUSE_INTERNAL_WQ);
kfree(vurb);
diff --git a/drivers/staging/apple-bce/vhci/transfer.h b/drivers/staging/apple-bce/vhci/transfer.h
index 111111111111..222222222222 100644
--- a/drivers/staging/apple-bce/vhci/transfer.h
+++ b/drivers/staging/apple-bce/vhci/transfer.h
@@ -44,7 +44,9 @@ enum bce_vhci_urb_state {
BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_REQUEST,
BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_COMPLETION,
- BCE_VHCI_URB_CONTROL_COMPLETE
+ BCE_VHCI_URB_CONTROL_COMPLETE,
+
+ BCE_VHCI_URB_CANCELLED
};
struct bce_vhci_urb {
struct urb *urb;
--
Armbian
@@ -1,76 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
Date: Fri, 28 Jun 2024 04:43:50 +0000
Subject: i915: 4 lane quirk for mbp15,1
Needed to use iGPU when dGPU was boot GPU
Patch written by Kerem Karabay <kekrby@gmail.com>
---
drivers/gpu/drm/i915/display/intel_ddi.c | 3 ++
drivers/gpu/drm/i915/display/intel_quirks.c | 15 ++++++++++
drivers/gpu/drm/i915/display/intel_quirks.h | 1 +
3 files changed, 19 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4938,6 +4938,9 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
if (dig_port->ddi_a_4_lanes)
return false;
+ if (intel_has_quirk(display, QUIRK_DDI_A_FORCE_4_LANES))
+ return true;
+
/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
* supported configuration
*/
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
@@ -66,6 +66,18 @@ static void quirk_increase_ddi_disabled_time(struct intel_display *display)
drm_info(display->drm, "Applying Increase DDI Disabled quirk\n");
}
+/*
+ * In some cases, the firmware might not set the lane count to 4 (for example,
+ * when booting in some dual GPU Macs with the dGPU as the default GPU), this
+ * quirk is used to force it as otherwise it might not be possible to compute a
+ * valid link configuration.
+ */
+static void quirk_ddi_a_force_4_lanes(struct intel_display *display)
+{
+ intel_set_quirk(display, QUIRK_DDI_A_FORCE_4_LANES);
+ drm_info(display->drm, "Applying DDI A Forced 4 Lanes quirk\n");
+}
+
static void quirk_no_pps_backlight_power_hook(struct intel_display *display)
{
intel_set_quirk(display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK);
@@ -240,6 +252,9 @@ static struct intel_quirk intel_quirks[] = {
/* Dell XPS 13 7390 2-in-1 */
{ 0x8a52, 0x1028, 0x08b0, quirk_edp_limit_rate_hbr2 },
+
+ /* Apple MacBookPro15,1 */
+ { 0x3e9b, 0x106b, 0x0176, quirk_ddi_a_force_4_lanes },
};
static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.h
+++ b/drivers/gpu/drm/i915/display/intel_quirks.h
@@ -21,6 +21,7 @@ enum intel_quirk_id {
QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK,
QUIRK_FW_SYNC_LEN,
QUIRK_EDP_LIMIT_RATE_HBR2,
+ QUIRK_DDI_A_FORCE_4_LANES,
};
void intel_init_quirks(struct intel_display *display);
--
Armbian
@@ -1,109 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
Date: Fri, 10 Feb 2023 22:45:00 +1100
Subject: apple-gmux: allow switching to igpu at probe
This means user don't need to set the gpu-power-prefs efivar to use the
igpu while runtime switching isn't working, so macOS will be unaffected.
This isn't really upstreamable, what we want upstream is the ability to
switch at runtime (so both gpus need to be able to probe the eDP panel).
Based off of work by Kerem Karabay <kekrby@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++
drivers/gpu/vga/vga_switcheroo.c | 7 +---
drivers/pci/vgaarb.c | 1 +
drivers/platform/x86/apple-gmux.c | 18 ++++++++++
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2393,6 +2393,9 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
int ret, retry = 0, i;
bool supports_atomic = false;
+ if (vga_switcheroo_client_probe_defer(pdev))
+ return -EPROBE_DEFER;
+
if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA ||
(pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) {
if (drm_firmware_drivers_only() && amdgpu_modeset == -1)
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -438,12 +438,7 @@ find_active_client(struct list_head *head)
bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev)
{
if (pci_is_display(pdev)) {
- /*
- * apple-gmux is needed on pre-retina MacBook Pro
- * to probe the panel if pdev is the inactive GPU.
- */
- if (apple_gmux_present() && pdev != vga_default_device() &&
- !vgasr_priv.handler_flags)
+ if (apple_gmux_present() && !vgasr_priv.handler_flags)
return true;
}
diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c
index 111111111111..222222222222 100644
--- a/drivers/pci/vgaarb.c
+++ b/drivers/pci/vgaarb.c
@@ -143,6 +143,7 @@ void vga_set_default_device(struct pci_dev *pdev)
pci_dev_put(vga_default);
vga_default = pci_dev_get(pdev);
}
+EXPORT_SYMBOL_GPL(vga_set_default_device);
/**
* vga_remove_vgacon - deactivate VGA console
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 111111111111..222222222222 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -21,6 +21,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/vga_switcheroo.h>
+#include <linux/vgaarb.h>
#include <linux/debugfs.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -107,6 +108,10 @@ struct apple_gmux_config {
# define MMIO_GMUX_MAX_BRIGHTNESS 0xffff
+static bool force_igd;
+module_param(force_igd, bool, 0);
+MODULE_PARM_DESC(force_idg, "Switch gpu to igd on module load. Make sure that you have apple-set-os set up and the iGPU is in `lspci -s 00:02.0`. (default: false) (bool)");
+
static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port)
{
return inb(gmux_data->iostart + port);
@@ -945,6 +950,19 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
gmux_enable_interrupts(gmux_data);
gmux_read_switch_state(gmux_data);
+ if (force_igd) {
+ struct pci_dev *pdev;
+
+ pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(2, 0));
+ if (pdev) {
+ pr_info("Switching to IGD");
+ gmux_switchto(VGA_SWITCHEROO_IGD);
+ vga_set_default_device(pdev);
+ } else {
+ pr_err("force_idg is true, but couldn't find iGPU at 00:02.0! Is apple-set-os working?");
+ }
+ }
+
/*
* Retina MacBook Pros cannot switch the panel's AUX separately
* and need eDP pre-calibration. They are distinguishable from
--
Armbian
@@ -1,312 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Pawlowski <paul@mrarm.io>
Date: Sun, 17 Nov 2019 23:11:56 +0100
Subject: applesmc: make io port base addr dynamic
This change makes the port base runtime configurable.
The reason why this change is made is so that when we switch to an
acpi_device we can resolve the port base addr from ACPI.
This change is not strictly required for T2 support - the base
address is still 0x300 on T2 Macs.
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 91 +++++-----
1 file changed, 49 insertions(+), 42 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -35,10 +35,11 @@
#include <linux/err.h>
#include <linux/bits.h>
+#define APPLESMC_PORT_BASE 0x300
/* data port used by Apple SMC */
-#define APPLESMC_DATA_PORT 0x300
+#define APPLESMC_DATA_PORT 0
/* command/status port used by Apple SMC */
-#define APPLESMC_CMD_PORT 0x304
+#define APPLESMC_CMD_PORT 4
#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
@@ -140,6 +141,8 @@ struct applesmc_device {
struct platform_device *dev;
struct applesmc_registers reg;
+ u16 port_base;
+
s16 rest_x;
s16 rest_y;
@@ -169,7 +172,7 @@ static const int debug;
* run out past 500ms.
*/
-static int wait_status(u8 val, u8 mask)
+static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
{
u8 status;
int us;
@@ -177,7 +180,7 @@ static int wait_status(u8 val, u8 mask)
us = APPLESMC_MIN_WAIT;
for (i = 0; i < 24 ; i++) {
- status = inb(APPLESMC_CMD_PORT);
+ status = inb(smc->port_base + APPLESMC_CMD_PORT);
if ((status & mask) == val)
return 0;
usleep_range(us, us * 2);
@@ -189,11 +192,11 @@ static int wait_status(u8 val, u8 mask)
/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
-static int send_byte(u8 cmd, u16 port)
+static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
{
int status;
- status = wait_status(0, SMC_STATUS_IB_CLOSED);
+ status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (status)
return status;
/*
@@ -202,24 +205,24 @@ static int send_byte(u8 cmd, u16 port)
* this extra read may not happen if status returns both
* simultaneously and this would appear to be required.
*/
- status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
+ status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
if (status)
return status;
- outb(cmd, port);
+ outb(cmd, smc->port_base + port);
return 0;
}
/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
-static int send_command(u8 cmd)
+static int send_command(struct applesmc_device *smc, u8 cmd)
{
int ret;
- ret = wait_status(0, SMC_STATUS_IB_CLOSED);
+ ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (ret)
return ret;
- outb(cmd, APPLESMC_CMD_PORT);
+ outb(cmd, smc->port_base + APPLESMC_CMD_PORT);
return 0;
}
@@ -229,108 +232,112 @@ static int send_command(u8 cmd)
* If busy is stuck high after the command then the SMC is jammed.
*/
-static int smc_sane(void)
+static int smc_sane(struct applesmc_device *smc)
{
int ret;
- ret = wait_status(0, SMC_STATUS_BUSY);
+ ret = wait_status(smc, 0, SMC_STATUS_BUSY);
if (!ret)
return ret;
- ret = send_command(APPLESMC_READ_CMD);
+ ret = send_command(smc, APPLESMC_READ_CMD);
if (ret)
return ret;
- return wait_status(0, SMC_STATUS_BUSY);
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int send_argument(const char *key)
+static int send_argument(struct applesmc_device *smc, const char *key)
{
int i;
for (i = 0; i < 4; i++)
- if (send_byte(key[i], APPLESMC_DATA_PORT))
+ if (send_byte(smc, key[i], APPLESMC_DATA_PORT))
return -EIO;
return 0;
}
-static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
+static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+ u8 *buffer, u8 len)
{
u8 status, data = 0;
int i;
int ret;
- ret = smc_sane();
+ ret = smc_sane(smc);
if (ret)
return ret;
- if (send_command(cmd) || send_argument(key)) {
+ if (send_command(smc, cmd) || send_argument(smc, key)) {
pr_warn("%.4s: read arg fail\n", key);
return -EIO;
}
/* This has no effect on newer (2012) SMCs */
- if (send_byte(len, APPLESMC_DATA_PORT)) {
+ if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: read len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
+ if (wait_status(smc,
+ SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
pr_warn("%.4s: read data[%d] fail\n", key, i);
return -EIO;
}
- buffer[i] = inb(APPLESMC_DATA_PORT);
+ buffer[i] = inb(smc->port_base + APPLESMC_DATA_PORT);
}
/* Read the data port until bit0 is cleared */
for (i = 0; i < 16; i++) {
udelay(APPLESMC_MIN_WAIT);
- status = inb(APPLESMC_CMD_PORT);
+ status = inb(smc->port_base + APPLESMC_CMD_PORT);
if (!(status & SMC_STATUS_AWAITING_DATA))
break;
- data = inb(APPLESMC_DATA_PORT);
+ data = inb(smc->port_base + APPLESMC_DATA_PORT);
}
if (i)
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
- return wait_status(0, SMC_STATUS_BUSY);
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
+static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+ const u8 *buffer, u8 len)
{
int i;
int ret;
- ret = smc_sane();
+ ret = smc_sane(smc);
if (ret)
return ret;
- if (send_command(cmd) || send_argument(key)) {
+ if (send_command(smc, cmd) || send_argument(smc, key)) {
pr_warn("%s: write arg fail\n", key);
return -EIO;
}
- if (send_byte(len, APPLESMC_DATA_PORT)) {
+ if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: write len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
+ if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
pr_warn("%s: write data fail\n", key);
return -EIO;
}
}
- return wait_status(0, SMC_STATUS_BUSY);
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int read_register_count(unsigned int *count)
+static int read_register_count(struct applesmc_device *smc,
+ unsigned int *count)
{
__be32 be;
int ret;
- ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
+ ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
if (ret)
return ret;
@@ -353,7 +360,7 @@ static int applesmc_read_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len);
+ ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
@@ -367,7 +374,7 @@ static int applesmc_write_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len);
+ ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
}
@@ -388,10 +395,10 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
if (cache->valid)
goto out;
be = cpu_to_be32(index);
- ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
+ ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
if (ret)
goto out;
- ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
+ ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
if (ret)
goto out;
@@ -589,7 +596,7 @@ static int applesmc_init_smcreg_try(struct applesmc_device *smc)
if (s->init_complete)
return 0;
- ret = read_register_count(&count);
+ ret = read_register_count(smc, &count);
if (ret)
return ret;
@@ -1472,7 +1479,7 @@ static int __init applesmc_init(void)
goto out;
}
- if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
+ if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS,
"applesmc")) {
ret = -ENXIO;
goto out;
@@ -1494,7 +1501,7 @@ static int __init applesmc_init(void)
out_driver:
platform_driver_unregister(&applesmc_driver);
out_region:
- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
+ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
out:
pr_warn("driver init failed (ret=%d)!\n", ret);
return ret;
@@ -1504,7 +1511,7 @@ static void __exit applesmc_exit(void)
{
platform_device_unregister(pdev);
platform_driver_unregister(&applesmc_driver);
- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
+ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
}
module_init(applesmc_init);
--
Armbian
@@ -1,265 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Pawlowski <paul@mrarm.io>
Date: Sat, 29 Jun 2024 04:49:16 +0000
Subject: applesmc: switch to acpi_device (from platform)
This change makes the change from platform_device
to acpi_device. The rationale for this change is
that on T2 Macs, an additional FixedMemory32
region is needed for device operation, and it can
be easily resolved via ACPI tables (this will be
done in another commit).
Additionally, on older Macs, the OS X driver also
looks for the specified ACPI device to resolve
its memory regions, and therefore this change
should not result in any incompatibilities.
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 124 +++++++---
1 file changed, 84 insertions(+), 40 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -19,7 +19,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/delay.h>
-#include <linux/platform_device.h>
+#include <linux/acpi.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -35,7 +35,6 @@
#include <linux/err.h>
#include <linux/bits.h>
-#define APPLESMC_PORT_BASE 0x300
/* data port used by Apple SMC */
#define APPLESMC_DATA_PORT 0
/* command/status port used by Apple SMC */
@@ -138,9 +137,10 @@ struct applesmc_registers {
};
struct applesmc_device {
- struct platform_device *dev;
+ struct acpi_device *dev;
struct applesmc_registers reg;
+ bool port_base_set;
u16 port_base;
s16 rest_x;
@@ -692,9 +692,13 @@ static int applesmc_init_smcreg(struct applesmc_device *smc)
}
/* Device model stuff */
+
+static int applesmc_init_resources(struct applesmc_device *smc);
+static void applesmc_free_resources(struct applesmc_device *smc);
static int applesmc_create_modules(struct applesmc_device *smc);
static void applesmc_destroy_modules(struct applesmc_device *smc);
-static int applesmc_probe(struct platform_device *dev)
+
+static int applesmc_add(struct acpi_device *dev)
{
struct applesmc_device *smc;
int ret;
@@ -705,12 +709,16 @@ static int applesmc_probe(struct platform_device *dev)
smc->dev = dev;
mutex_init(&smc->reg.mutex);
- platform_set_drvdata(dev, smc);
+ dev_set_drvdata(&dev->dev, smc);
- ret = applesmc_init_smcreg(smc);
+ ret = applesmc_init_resources(smc);
if (ret)
goto out_mem;
+ ret = applesmc_init_smcreg(smc);
+ if (ret)
+ goto out_res;
+
applesmc_device_init(smc);
ret = applesmc_create_modules(smc);
@@ -721,20 +729,23 @@ static int applesmc_probe(struct platform_device *dev)
out_reg:
applesmc_destroy_smcreg(smc);
+out_res:
+ applesmc_free_resources(smc);
out_mem:
- platform_set_drvdata(dev, NULL);
+ dev_set_drvdata(&dev->dev, NULL);
mutex_destroy(&smc->reg.mutex);
kfree(smc);
return ret;
}
-static int applesmc_remove(struct platform_device *dev)
+static int applesmc_remove(struct acpi_device *dev)
{
- struct applesmc_device *smc = platform_get_drvdata(dev);
+ struct applesmc_device *smc = dev_get_drvdata(&dev->dev);
applesmc_destroy_modules(smc);
applesmc_destroy_smcreg(smc);
+ applesmc_free_resources(smc);
mutex_destroy(&smc->reg.mutex);
kfree(smc);
@@ -742,6 +753,52 @@ static int applesmc_remove(struct platform_device *dev)
return 0;
}
+static acpi_status applesmc_walk_resources(struct acpi_resource *res,
+ void *data)
+{
+ struct applesmc_device *smc = data;
+
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IO:
+ if (!smc->port_base_set) {
+ if (res->data.io.address_length < APPLESMC_NR_PORTS)
+ return AE_ERROR;
+ smc->port_base = res->data.io.minimum;
+ smc->port_base_set = true;
+ }
+ return AE_OK;
+
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ if (smc->port_base_set)
+ return AE_OK;
+ else
+ return AE_NOT_FOUND;
+
+ default:
+ return AE_OK;
+ }
+}
+
+static int applesmc_init_resources(struct applesmc_device *smc)
+{
+ int ret;
+
+ ret = acpi_walk_resources(smc->dev->handle, METHOD_NAME__CRS,
+ applesmc_walk_resources, smc);
+ if (ACPI_FAILURE(ret))
+ return -ENXIO;
+
+ if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc"))
+ return -ENXIO;
+
+ return 0;
+}
+
+static void applesmc_free_resources(struct applesmc_device *smc)
+{
+ release_region(smc->port_base, APPLESMC_NR_PORTS);
+}
+
/* Synchronize device with memorized backlight state */
static int applesmc_pm_resume(struct device *dev)
{
@@ -763,17 +820,26 @@ static int applesmc_pm_restore(struct device *dev)
return applesmc_pm_resume(dev);
}
+static const struct acpi_device_id applesmc_ids[] = {
+ {"APP0001", 0},
+ {"", 0},
+};
+
static const struct dev_pm_ops applesmc_pm_ops = {
.resume = applesmc_pm_resume,
.restore = applesmc_pm_restore,
};
-static struct platform_driver applesmc_driver = {
- .probe = applesmc_probe,
- .remove = applesmc_remove,
- .driver = {
- .name = "applesmc",
- .pm = &applesmc_pm_ops,
+static struct acpi_driver applesmc_driver = {
+ .name = "applesmc",
+ .class = "applesmc",
+ .ids = applesmc_ids,
+ .ops = {
+ .add = applesmc_add,
+ .remove = applesmc_remove
+ },
+ .drv = {
+ .pm = &applesmc_pm_ops
},
};
@@ -1262,7 +1328,6 @@ static int applesmc_create_nodes(struct applesmc_device *smc,
static int applesmc_create_accelerometer(struct applesmc_device *smc)
{
int ret;
-
if (!smc->reg.has_accelerometer)
return 0;
@@ -1467,8 +1532,6 @@ static void applesmc_destroy_modules(struct applesmc_device *smc)
applesmc_destroy_nodes(smc, info_group);
}
-static struct platform_device *pdev;
-
static int __init applesmc_init(void)
{
int ret;
@@ -1479,29 +1542,12 @@ static int __init applesmc_init(void)
goto out;
}
- if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS,
- "applesmc")) {
- ret = -ENXIO;
- goto out;
- }
-
- ret = platform_driver_register(&applesmc_driver);
+ ret = acpi_bus_register_driver(&applesmc_driver);
if (ret)
- goto out_region;
-
- pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
- NULL, 0);
- if (IS_ERR(pdev)) {
- ret = PTR_ERR(pdev);
- goto out_driver;
- }
+ goto out;
return 0;
-out_driver:
- platform_driver_unregister(&applesmc_driver);
-out_region:
- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
out:
pr_warn("driver init failed (ret=%d)!\n", ret);
return ret;
@@ -1509,9 +1555,7 @@ static int __init applesmc_init(void)
static void __exit applesmc_exit(void)
{
- platform_device_unregister(pdev);
- platform_driver_unregister(&applesmc_driver);
- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
+ acpi_bus_unregister_driver(&applesmc_driver);
}
module_init(applesmc_init);
--
Armbian
@@ -1,298 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Pawlowski <paul@mrarm.io>
Date: Sun, 17 Nov 2019 23:12:14 +0100
Subject: applesmc: key interface wrappers
This change replaces the read_smc and write_smc
methods with wrappers, additionally removing the
command id parameter from them (and introducing
get_smc_key_by_index and get_smc_key_info).
This is done as to allow simple implementation
replacement on T2 Macs. The newly introduced
methods mentioned in the previous paragraph need
special handling on T2 and as such had to be
separated.
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 119 ++++++----
1 file changed, 79 insertions(+), 40 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -172,7 +172,7 @@ static const int debug;
* run out past 500ms.
*/
-static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
+static int port_wait_status(struct applesmc_device *smc, u8 val, u8 mask)
{
u8 status;
int us;
@@ -190,13 +190,13 @@ static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
return -EIO;
}
-/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
+/* port_send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
-static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
+static int port_send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
{
int status;
- status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
+ status = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (status)
return status;
/*
@@ -205,7 +205,7 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
* this extra read may not happen if status returns both
* simultaneously and this would appear to be required.
*/
- status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
+ status = port_wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
if (status)
return status;
@@ -213,15 +213,16 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
return 0;
}
-/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
+/* port_send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
-static int send_command(struct applesmc_device *smc, u8 cmd)
+static int port_send_command(struct applesmc_device *smc, u8 cmd)
{
int ret;
- ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
+ ret = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (ret)
return ret;
+
outb(cmd, smc->port_base + APPLESMC_CMD_PORT);
return 0;
}
@@ -232,53 +233,53 @@ static int send_command(struct applesmc_device *smc, u8 cmd)
* If busy is stuck high after the command then the SMC is jammed.
*/
-static int smc_sane(struct applesmc_device *smc)
+static int port_smc_sane(struct applesmc_device *smc)
{
int ret;
- ret = wait_status(smc, 0, SMC_STATUS_BUSY);
+ ret = port_wait_status(smc, 0, SMC_STATUS_BUSY);
if (!ret)
return ret;
- ret = send_command(smc, APPLESMC_READ_CMD);
+ ret = port_send_command(smc, APPLESMC_READ_CMD);
if (ret)
return ret;
- return wait_status(smc, 0, SMC_STATUS_BUSY);
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int send_argument(struct applesmc_device *smc, const char *key)
+static int port_send_argument(struct applesmc_device *smc, const char *key)
{
int i;
for (i = 0; i < 4; i++)
- if (send_byte(smc, key[i], APPLESMC_DATA_PORT))
+ if (port_send_byte(smc, key[i], APPLESMC_DATA_PORT))
return -EIO;
return 0;
}
-static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+static int port_read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
u8 *buffer, u8 len)
{
u8 status, data = 0;
int i;
int ret;
- ret = smc_sane(smc);
+ ret = port_smc_sane(smc);
if (ret)
return ret;
- if (send_command(smc, cmd) || send_argument(smc, key)) {
+ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) {
pr_warn("%.4s: read arg fail\n", key);
return -EIO;
}
/* This has no effect on newer (2012) SMCs */
- if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
+ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: read len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (wait_status(smc,
+ if (port_wait_status(smc,
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
pr_warn("%.4s: read data[%d] fail\n", key, i);
@@ -298,37 +299,80 @@ static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
if (i)
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
- return wait_status(smc, 0, SMC_STATUS_BUSY);
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+static int port_write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
const u8 *buffer, u8 len)
{
int i;
int ret;
- ret = smc_sane(smc);
+ ret = port_smc_sane(smc);
if (ret)
return ret;
- if (send_command(smc, cmd) || send_argument(smc, key)) {
+ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) {
pr_warn("%s: write arg fail\n", key);
return -EIO;
}
- if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
+ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: write len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
+ if (port_send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
pr_warn("%s: write data fail\n", key);
return -EIO;
}
}
- return wait_status(smc, 0, SMC_STATUS_BUSY);
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
+}
+
+static int port_get_smc_key_info(struct applesmc_device *smc,
+ const char *key, struct applesmc_entry *info)
+{
+ int ret;
+ u8 raw[6];
+
+ ret = port_read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, raw, 6);
+ if (ret)
+ return ret;
+ info->len = raw[0];
+ memcpy(info->type, &raw[1], 4);
+ info->flags = raw[5];
+ return 0;
+}
+
+static int read_smc(struct applesmc_device *smc, const char *key,
+ u8 *buffer, u8 len)
+{
+ return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
+}
+
+static int write_smc(struct applesmc_device *smc, const char *key,
+ const u8 *buffer, u8 len)
+{
+ return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
+}
+
+static int get_smc_key_by_index(struct applesmc_device *smc,
+ unsigned int index, char *key)
+{
+ __be32 be;
+
+ be = cpu_to_be32(index);
+ return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
+ (const char *) &be, (u8 *) key, 4);
+}
+
+static int get_smc_key_info(struct applesmc_device *smc, const char *key,
+ struct applesmc_entry *info)
+{
+ return port_get_smc_key_info(smc, key, info);
}
static int read_register_count(struct applesmc_device *smc,
@@ -337,8 +381,8 @@ static int read_register_count(struct applesmc_device *smc,
__be32 be;
int ret;
- ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
- if (ret)
+ ret = read_smc(smc, KEY_COUNT_KEY, (u8 *)&be, 4);
+ if (ret < 0)
return ret;
*count = be32_to_cpu(be);
@@ -360,7 +404,7 @@ static int applesmc_read_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len);
+ ret = read_smc(smc, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
@@ -374,7 +418,7 @@ static int applesmc_write_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len);
+ ret = write_smc(smc, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
}
@@ -383,8 +427,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
struct applesmc_device *smc, int index)
{
struct applesmc_entry *cache = &smc->reg.cache[index];
- u8 key[4], info[6];
- __be32 be;
+ char key[4];
int ret = 0;
if (cache->valid)
@@ -394,18 +437,14 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
if (cache->valid)
goto out;
- be = cpu_to_be32(index);
- ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
+ ret = get_smc_key_by_index(smc, index, key);
if (ret)
goto out;
- ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
+ memcpy(cache->key, key, 4);
+
+ ret = get_smc_key_info(smc, key, cache);
if (ret)
goto out;
-
- memcpy(cache->key, key, 4);
- cache->len = info[0];
- memcpy(cache->type, &info[1], 4);
- cache->flags = info[5];
cache->valid = true;
out:
--
Armbian
@@ -1,343 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aun-Ali Zaidi <admin@kodeit.net>
Date: Sun, 17 Nov 2019 23:12:16 +0100
Subject: applesmc: basic mmio interface implementation
This change introduces a basic MMIO-based
interface implementation required to communicate
with the SMC on T2 Macs. The MMIO interface is
enabled only when it's supported on the running
system.
The MMIO interface replaces legacy port-based SMC
key reads, writes and metadata requests (getting
key by index and getting key info).
(Based on patch by @mcmrarm)
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 237 +++++++++-
1 file changed, 231 insertions(+), 6 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -42,6 +42,18 @@
#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
+#define APPLESMC_IOMEM_KEY_DATA 0
+#define APPLESMC_IOMEM_KEY_STATUS 0x4005
+#define APPLESMC_IOMEM_KEY_NAME 0x78
+#define APPLESMC_IOMEM_KEY_DATA_LEN 0x7D
+#define APPLESMC_IOMEM_KEY_SMC_ID 0x7E
+#define APPLESMC_IOMEM_KEY_CMD 0x7F
+#define APPLESMC_IOMEM_MIN_SIZE 0x4006
+
+#define APPLESMC_IOMEM_KEY_TYPE_CODE 0
+#define APPLESMC_IOMEM_KEY_TYPE_DATA_LEN 5
+#define APPLESMC_IOMEM_KEY_TYPE_FLAGS 6
+
#define APPLESMC_MAX_DATA_LENGTH 32
/* Apple SMC status bits */
@@ -138,10 +150,13 @@ struct applesmc_registers {
struct applesmc_device {
struct acpi_device *dev;
+ struct device *ldev;
struct applesmc_registers reg;
- bool port_base_set;
+ bool port_base_set, iomem_base_set;
u16 port_base;
+ u8 *__iomem iomem_base;
+ u32 iomem_base_addr, iomem_base_size;
s16 rest_x;
s16 rest_y;
@@ -347,16 +362,156 @@ static int port_get_smc_key_info(struct applesmc_device *smc,
return 0;
}
+
+/*
+ * MMIO based communication.
+ * TODO: Use updated mechanism for cmd timeout/retry
+ */
+
+static void iomem_clear_status(struct applesmc_device *smc)
+{
+ if (ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS))
+ iowrite8(0, smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS);
+}
+
+static int iomem_wait_read(struct applesmc_device *smc)
+{
+ u8 status;
+ int us;
+ int i;
+
+ us = APPLESMC_MIN_WAIT;
+ for (i = 0; i < 24 ; i++) {
+ status = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS);
+ if (status & 0x20)
+ return 0;
+ usleep_range(us, us * 2);
+ if (i > 9)
+ us <<= 1;
+ }
+
+ dev_warn(smc->ldev, "%s... timeout\n", __func__);
+ return -EIO;
+}
+
+static int iomem_read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+ u8 *buffer, u8 len)
+{
+ u8 err, remote_len;
+ u32 key_int = *((u32 *) key);
+
+ iomem_clear_status(smc);
+ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME);
+ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID);
+ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
+
+ if (iomem_wait_read(smc))
+ return -EIO;
+
+ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
+ if (err != 0) {
+ dev_warn(smc->ldev, "read_smc_mmio(%x %8x/%.4s) failed: %u\n",
+ cmd, key_int, key, err);
+ return -EIO;
+ }
+
+ if (cmd == APPLESMC_READ_CMD) {
+ remote_len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN);
+ if (remote_len != len) {
+ dev_warn(smc->ldev,
+ "read_smc_mmio(%x %8x/%.4s) failed: buffer length mismatch (remote = %u, requested = %u)\n",
+ cmd, key_int, key, remote_len, len);
+ return -EINVAL;
+ }
+ } else {
+ remote_len = len;
+ }
+
+ memcpy_fromio(buffer, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA,
+ remote_len);
+
+ dev_dbg(smc->ldev, "read_smc_mmio(%x %8x/%.4s): buflen=%u reslen=%u\n",
+ cmd, key_int, key, len, remote_len);
+ print_hex_dump_bytes("read_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, remote_len);
+ return 0;
+}
+
+static int iomem_get_smc_key_type(struct applesmc_device *smc, const char *key,
+ struct applesmc_entry *e)
+{
+ u8 err;
+ u8 cmd = APPLESMC_GET_KEY_TYPE_CMD;
+ u32 key_int = *((u32 *) key);
+
+ iomem_clear_status(smc);
+ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME);
+ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID);
+ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
+
+ if (iomem_wait_read(smc))
+ return -EIO;
+
+ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
+ if (err != 0) {
+ dev_warn(smc->ldev, "get_smc_key_type_mmio(%.4s) failed: %u\n", key, err);
+ return -EIO;
+ }
+
+ e->len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_DATA_LEN);
+ *((uint32_t *) e->type) = ioread32(
+ smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_CODE);
+ e->flags = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_FLAGS);
+
+ dev_dbg(smc->ldev, "get_smc_key_type_mmio(%.4s): len=%u type=%.4s flags=%x\n",
+ key, e->len, e->type, e->flags);
+ return 0;
+}
+
+static int iomem_write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+ const u8 *buffer, u8 len)
+{
+ u8 err;
+ u32 key_int = *((u32 *) key);
+
+ iomem_clear_status(smc);
+ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME);
+ memcpy_toio(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA, buffer, len);
+ iowrite32(len, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN);
+ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID);
+ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
+
+ if (iomem_wait_read(smc))
+ return -EIO;
+
+ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
+ if (err != 0) {
+ dev_warn(smc->ldev, "write_smc_mmio(%x %.4s) failed: %u\n", cmd, key, err);
+ print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len);
+ return -EIO;
+ }
+
+ dev_dbg(smc->ldev, "write_smc_mmio(%x %.4s): buflen=%u\n", cmd, key, len);
+ print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len);
+ return 0;
+}
+
+
static int read_smc(struct applesmc_device *smc, const char *key,
u8 *buffer, u8 len)
{
- return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
+ if (smc->iomem_base_set)
+ return iomem_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
+ else
+ return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
}
static int write_smc(struct applesmc_device *smc, const char *key,
const u8 *buffer, u8 len)
{
- return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
+ if (smc->iomem_base_set)
+ return iomem_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
+ else
+ return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
}
static int get_smc_key_by_index(struct applesmc_device *smc,
@@ -365,14 +520,21 @@ static int get_smc_key_by_index(struct applesmc_device *smc,
__be32 be;
be = cpu_to_be32(index);
- return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
- (const char *) &be, (u8 *) key, 4);
+ if (smc->iomem_base_set)
+ return iomem_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
+ (const char *) &be, (u8 *) key, 4);
+ else
+ return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
+ (const char *) &be, (u8 *) key, 4);
}
static int get_smc_key_info(struct applesmc_device *smc, const char *key,
struct applesmc_entry *info)
{
- return port_get_smc_key_info(smc, key, info);
+ if (smc->iomem_base_set)
+ return iomem_get_smc_key_type(smc, key, info);
+ else
+ return port_get_smc_key_info(smc, key, info);
}
static int read_register_count(struct applesmc_device *smc,
@@ -746,6 +908,7 @@ static int applesmc_add(struct acpi_device *dev)
if (!smc)
return -ENOMEM;
smc->dev = dev;
+ smc->ldev = &dev->dev;
mutex_init(&smc->reg.mutex);
dev_set_drvdata(&dev->dev, smc);
@@ -807,6 +970,20 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res,
}
return AE_OK;
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ if (!smc->iomem_base_set) {
+ if (res->data.fixed_memory32.address_length <
+ APPLESMC_IOMEM_MIN_SIZE) {
+ dev_warn(smc->ldev, "found iomem but it's too small: %u\n",
+ res->data.fixed_memory32.address_length);
+ return AE_OK;
+ }
+ smc->iomem_base_addr = res->data.fixed_memory32.address;
+ smc->iomem_base_size = res->data.fixed_memory32.address_length;
+ smc->iomem_base_set = true;
+ }
+ return AE_OK;
+
case ACPI_RESOURCE_TYPE_END_TAG:
if (smc->port_base_set)
return AE_OK;
@@ -818,6 +995,8 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res,
}
}
+static int applesmc_try_enable_iomem(struct applesmc_device *smc);
+
static int applesmc_init_resources(struct applesmc_device *smc)
{
int ret;
@@ -830,11 +1009,57 @@ static int applesmc_init_resources(struct applesmc_device *smc)
if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc"))
return -ENXIO;
+ if (smc->iomem_base_set) {
+ if (applesmc_try_enable_iomem(smc))
+ smc->iomem_base_set = false;
+ }
+
return 0;
}
+static int applesmc_try_enable_iomem(struct applesmc_device *smc)
+{
+ u8 test_val, ldkn_version;
+
+ dev_dbg(smc->ldev, "Trying to enable iomem based communication\n");
+ smc->iomem_base = ioremap(smc->iomem_base_addr, smc->iomem_base_size);
+ if (!smc->iomem_base)
+ goto out;
+
+ /* Apple's driver does this check for some reason */
+ test_val = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS);
+ if (test_val == 0xff) {
+ dev_warn(smc->ldev,
+ "iomem enable failed: initial status is 0xff (is %x)\n",
+ test_val);
+ goto out_iomem;
+ }
+
+ if (read_smc(smc, "LDKN", &ldkn_version, 1)) {
+ dev_warn(smc->ldev, "iomem enable failed: ldkn read failed\n");
+ goto out_iomem;
+ }
+
+ if (ldkn_version < 2) {
+ dev_warn(smc->ldev,
+ "iomem enable failed: ldkn version %u is less than minimum (2)\n",
+ ldkn_version);
+ goto out_iomem;
+ }
+
+ return 0;
+
+out_iomem:
+ iounmap(smc->iomem_base);
+
+out:
+ return -ENXIO;
+}
+
static void applesmc_free_resources(struct applesmc_device *smc)
{
+ if (smc->iomem_base_set)
+ iounmap(smc->iomem_base);
release_region(smc->port_base, APPLESMC_NR_PORTS);
}
--
Armbian
@@ -1,227 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Pawlowski <paul@mrarm.io>
Date: Sun, 17 Nov 2019 23:12:18 +0100
Subject: applesmc: fan support on T2 Macs
T2 Macs changed the fan values from shorts to
floats, and changed the fan manual override
setting from a bitmask to a per-fan boolean
named F0Md (thanks to @kleuter for mentioning
it).
A minimal soft-float implementation has been
written for convert floats to integers (and vice
versa).
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 119 ++++++++--
1 file changed, 102 insertions(+), 17 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -87,6 +87,7 @@
#define FAN_ID_FMT "F%dID" /* r-o char[16] */
#define TEMP_SENSOR_TYPE "sp78"
+#define FLOAT_TYPE "flt "
/* List of keys used to read/write fan speeds */
static const char *const fan_speed_fmt[] = {
@@ -96,6 +97,7 @@ static const char *const fan_speed_fmt[] = {
"F%dSf", /* safe speed - not all models */
"F%dTg", /* target speed (manual: rw) */
};
+#define FAN_MANUAL_FMT "F%dMd"
#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
@@ -734,6 +736,42 @@ static int applesmc_read_s16(struct applesmc_device *smc,
return 0;
}
+/**
+ * applesmc_float_to_u32 - Retrieve the integral part of a float.
+ * This is needed because Apple made fans use float values in the T2.
+ * The fractional point is not significantly useful though, and the integral
+ * part can be easily extracted.
+ */
+static inline u32 applesmc_float_to_u32(u32 d)
+{
+ u8 sign = (u8) ((d >> 31) & 1);
+ s32 exp = (s32) ((d >> 23) & 0xff) - 0x7f;
+ u32 fr = d & ((1u << 23) - 1);
+
+ if (sign || exp < 0)
+ return 0;
+
+ return (u32) ((1u << exp) + (fr >> (23 - exp)));
+}
+
+/**
+ * applesmc_u32_to_float - Convert an u32 into a float.
+ * See applesmc_float_to_u32 for a rationale.
+ */
+static inline u32 applesmc_u32_to_float(u32 d)
+{
+ u32 dc = d, bc = 0, exp;
+
+ if (!d)
+ return 0;
+
+ while (dc >>= 1)
+ ++bc;
+ exp = 0x7f + bc;
+
+ return (u32) ((exp << 23) |
+ ((d << (23 - (exp - 0x7f))) & ((1u << 23) - 1)));
+}
/*
* applesmc_device_init - initialize the accelerometer. Can sleep.
*/
@@ -1241,6 +1279,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
struct device_attribute *attr, char *sysfsbuf)
{
struct applesmc_device *smc = dev_get_drvdata(dev);
+ const struct applesmc_entry *entry;
int ret;
unsigned int speed = 0;
char newkey[5];
@@ -1249,11 +1288,21 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)],
to_index(attr));
- ret = applesmc_read_key(smc, newkey, buffer, 2);
+ entry = applesmc_get_entry_by_key(smc, newkey);
+ if (IS_ERR(entry))
+ return PTR_ERR(entry);
+
+ if (!strcmp(entry->type, FLOAT_TYPE)) {
+ ret = applesmc_read_entry(smc, entry, (u8 *) &speed, 4);
+ speed = applesmc_float_to_u32(speed);
+ } else {
+ ret = applesmc_read_entry(smc, entry, buffer, 2);
+ speed = ((buffer[0] << 8 | buffer[1]) >> 2);
+ }
+
if (ret)
return ret;
- speed = ((buffer[0] << 8 | buffer[1]) >> 2);
return sysfs_emit(sysfsbuf, "%u\n", speed);
}
@@ -1262,6 +1311,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev,
const char *sysfsbuf, size_t count)
{
struct applesmc_device *smc = dev_get_drvdata(dev);
+ const struct applesmc_entry *entry;
int ret;
unsigned long speed;
char newkey[5];
@@ -1273,9 +1323,18 @@ static ssize_t applesmc_store_fan_speed(struct device *dev,
scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)],
to_index(attr));
- buffer[0] = (speed >> 6) & 0xff;
- buffer[1] = (speed << 2) & 0xff;
- ret = applesmc_write_key(smc, newkey, buffer, 2);
+ entry = applesmc_get_entry_by_key(smc, newkey);
+ if (IS_ERR(entry))
+ return PTR_ERR(entry);
+
+ if (!strcmp(entry->type, FLOAT_TYPE)) {
+ speed = applesmc_u32_to_float(speed);
+ ret = applesmc_write_entry(smc, entry, (u8 *) &speed, 4);
+ } else {
+ buffer[0] = (speed >> 6) & 0xff;
+ buffer[1] = (speed << 2) & 0xff;
+ ret = applesmc_write_key(smc, newkey, buffer, 2);
+ }
if (ret)
return ret;
@@ -1290,12 +1349,26 @@ static ssize_t applesmc_show_fan_manual(struct device *dev,
int ret;
u16 manual = 0;
u8 buffer[2];
+ char newkey[5];
+ bool has_newkey = false;
+
+ scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr));
+
+ ret = applesmc_has_key(smc, newkey, &has_newkey);
+ if (ret)
+ return ret;
+
+ if (has_newkey) {
+ ret = applesmc_read_key(smc, newkey, buffer, 1);
+ manual = buffer[0];
+ } else {
+ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
+ manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
+ }
- ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
if (ret)
return ret;
- manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
return sysfs_emit(sysfsbuf, "%d\n", manual);
}
@@ -1306,27 +1379,39 @@ static ssize_t applesmc_store_fan_manual(struct device *dev,
struct applesmc_device *smc = dev_get_drvdata(dev);
int ret;
u8 buffer[2];
+ char newkey[5];
+ bool has_newkey = false;
unsigned long input;
u16 val;
if (kstrtoul(sysfsbuf, 10, &input) < 0)
return -EINVAL;
- ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
+ scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr));
+
+ ret = applesmc_has_key(smc, newkey, &has_newkey);
if (ret)
- goto out;
+ return ret;
- val = (buffer[0] << 8 | buffer[1]);
+ if (has_newkey) {
+ buffer[0] = input & 1;
+ ret = applesmc_write_key(smc, newkey, buffer, 1);
+ } else {
+ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
+ val = (buffer[0] << 8 | buffer[1]);
+ if (ret)
+ goto out;
- if (input)
- val = val | (0x01 << to_index(attr));
- else
- val = val & ~(0x01 << to_index(attr));
+ if (input)
+ val = val | (0x01 << to_index(attr));
+ else
+ val = val & ~(0x01 << to_index(attr));
- buffer[0] = (val >> 8) & 0xFF;
- buffer[1] = val & 0xFF;
+ buffer[0] = (val >> 8) & 0xFF;
+ buffer[1] = val & 0xFF;
- ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2);
+ ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2);
+ }
out:
if (ret)
--
Armbian
@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orlando Chamberlain <redecorating@protonmail.com>
Date: Sun, 9 Oct 2022 15:59:01 +0530
Subject: applesmc: Add iMacPro to applesmc_whitelist
The iMacPro1,1 is the only iMacPro released before the line was
discontinued. Add it to the applesmc_whitelist.
Signed-off-by: Orlando Chamberlain <redecorating@protonmail.com>
---
drivers/hwmon/applesmc.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -1803,6 +1803,10 @@ static const struct dmi_system_id applesmc_whitelist[] __initconst = {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") },
},
+ { applesmc_dmi_match, "Apple iMacPro", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMacPro") },
+ },
{ applesmc_dmi_match, "Apple MacPro", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
--
Armbian
@@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
Date: Tue, 24 Jan 2023 15:46:48 +1100
Subject: applesmc: make applesmc_remove void
for linux6.2 compatibility
---
drivers/hwmon/applesmc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -979,7 +979,7 @@ static int applesmc_add(struct acpi_device *dev)
return ret;
}
-static int applesmc_remove(struct acpi_device *dev)
+static void applesmc_remove(struct acpi_device *dev)
{
struct applesmc_device *smc = dev_get_drvdata(&dev->dev);
@@ -990,7 +990,7 @@ static int applesmc_remove(struct acpi_device *dev)
mutex_destroy(&smc->reg.mutex);
kfree(smc);
- return 0;
+ return;
}
static acpi_status applesmc_walk_resources(struct acpi_resource *res,
--
Armbian
@@ -1,96 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
Date: Mon, 30 Jan 2023 18:42:21 +1100
Subject: applesmc: battery charge limiter
---
drivers/hwmon/applesmc.c | 42 +++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -1477,6 +1477,35 @@ static void applesmc_brightness_set(struct led_classdev *led_cdev,
dev_dbg(led_cdev->dev, "work was already on the queue.\n");
}
+static ssize_t applesmc_BCLM_store(struct device *dev,
+ struct device_attribute *attr, char *sysfsbuf, size_t count)
+{
+ struct applesmc_device *smc = dev_get_drvdata(dev);
+ u8 val;
+
+ if (kstrtou8(sysfsbuf, 10, &val) < 0)
+ return -EINVAL;
+
+ if (val < 0 || val > 100)
+ return -EINVAL;
+
+ if (applesmc_write_key(smc, "BCLM", &val, 1))
+ return -ENODEV;
+ return count;
+}
+
+static ssize_t applesmc_BCLM_show(struct device *dev,
+ struct device_attribute *attr, char *sysfsbuf)
+{
+ struct applesmc_device *smc = dev_get_drvdata(dev);
+ u8 val;
+
+ if (applesmc_read_key(smc, "BCLM", &val, 1))
+ return -ENODEV;
+
+ return sysfs_emit(sysfsbuf, "%d\n", val);
+}
+
static ssize_t applesmc_key_count_show(struct device *dev,
struct device_attribute *attr, char *sysfsbuf)
{
@@ -1611,6 +1640,11 @@ static struct applesmc_node_group temp_group[] = {
{ }
};
+static struct applesmc_node_group BCLM_group[] = {
+ { "battery_charge_limit", applesmc_BCLM_show, applesmc_BCLM_store },
+ { }
+};
+
/* Module stuff */
/*
@@ -1829,10 +1863,13 @@ static int applesmc_create_modules(struct applesmc_device *smc)
ret = applesmc_create_nodes(smc, info_group, 1);
if (ret)
goto out;
+ ret = applesmc_create_nodes(smc, BCLM_group, 1);
+ if (ret)
+ goto out_info;
ret = applesmc_create_nodes(smc, fan_group, smc->reg.fan_count);
if (ret)
- goto out_info;
+ goto out_bclm;
ret = applesmc_create_nodes(smc, temp_group, smc->reg.index_count);
if (ret)
@@ -1868,6 +1905,8 @@ static int applesmc_create_modules(struct applesmc_device *smc)
applesmc_destroy_nodes(smc, temp_group);
out_fans:
applesmc_destroy_nodes(smc, fan_group);
+out_bclm:
+ applesmc_destroy_nodes(smc, BCLM_group);
out_info:
applesmc_destroy_nodes(smc, info_group);
out:
@@ -1882,6 +1921,7 @@ static void applesmc_destroy_modules(struct applesmc_device *smc)
applesmc_release_accelerometer(smc);
applesmc_destroy_nodes(smc, temp_group);
applesmc_destroy_nodes(smc, fan_group);
+ applesmc_destroy_nodes(smc, BCLM_group);
applesmc_destroy_nodes(smc, info_group);
}
--
Armbian
File diff suppressed because it is too large Load Diff
@@ -1,81 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aditya Garg <gargaditya08@live.com>
Date: Fri, 12 Sep 2025 12:09:01 +0000
Subject: HID: apple: ignore the trackpad on T2 Macs
In order to manage the trackpad on T2 Macs by hid-magicmouse driver
we need to ensure that it is not bound by the hid-apple driver. Use
the existing APPLE_IGNORE_MOUSE quirk for the same.
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/hid-apple.c | 27 ++++++----
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -30,7 +30,7 @@
#include "hid-ids.h"
#define APPLE_RDESC_JIS BIT(0)
-/* BIT(1) reserved, was: APPLE_IGNORE_MOUSE */
+#define APPLE_IGNORE_MOUSE BIT(1)
#define APPLE_HAS_FN BIT(2)
/* BIT(3) reserved, was: APPLE_HIDDEV */
#define APPLE_ISO_TILDE_QUIRK BIT(4)
@@ -954,6 +954,9 @@ static int apple_probe(struct hid_device *hdev,
hdev->type != HID_TYPE_SPI_KEYBOARD)
return -ENODEV;
+ if (quirks & APPLE_IGNORE_MOUSE && hdev->type == HID_TYPE_USBMOUSE)
+ return -ENODEV;
+
asc = devm_kzalloc(&hdev->dev, sizeof(*asc), GFP_KERNEL);
if (asc == NULL) {
hid_err(hdev, "can't alloc apple descriptor\n");
@@ -1176,27 +1179,31 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K),
- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
+ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
+ APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132),
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
- APPLE_DISABLE_FKEYS },
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680),
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
- APPLE_DISABLE_FKEYS },
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT),
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
- APPLE_DISABLE_FKEYS },
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213),
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
- APPLE_DISABLE_FKEYS },
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K),
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS |
+ APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223),
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS |
+ APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K),
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_IGNORE_MOUSE },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F),
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS |
+ APPLE_IGNORE_MOUSE },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
--
Armbian
@@ -1,417 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aditya Garg <gargaditya08@live.com>
Date: Tue, 11 Mar 2025 18:44:06 +0530
Subject: HID: magicmouse: Add support for trackpads found on T2 Macs
This patch adds support for trackpads found on Macs with the T2
Security Chip. The touch report format differs from other trackpads.
It is the same format as type 4 in bcm5974.c
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/hid-magicmouse.c | 296 +++++++++-
1 file changed, 275 insertions(+), 21 deletions(-)
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -118,6 +118,105 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
#define TRACKPAD2_RES_Y \
((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100))
+#define J140K_TP_DIMENSION_X (float)12100
+#define J140K_TP_MIN_X -5318
+#define J140K_TP_MAX_X 5787
+#define J140K_TP_RES_X \
+ ((J140K_TP_MAX_X - J140K_TP_MIN_X) / (J140K_TP_DIMENSION_X / 100))
+#define J140K_TP_DIMENSION_Y (float)8200
+#define J140K_TP_MIN_Y -157
+#define J140K_TP_MAX_Y 7102
+#define J140K_TP_RES_Y \
+ ((J140K_TP_MAX_Y - J140K_TP_MIN_Y) / (J140K_TP_DIMENSION_Y / 100))
+
+#define J132_TP_DIMENSION_X (float)13500
+#define J132_TP_MIN_X -6243
+#define J132_TP_MAX_X 6749
+#define J132_TP_RES_X \
+ ((J132_TP_MAX_X - J132_TP_MIN_X) / (J132_TP_DIMENSION_X / 100))
+#define J132_TP_DIMENSION_Y (float)8400
+#define J132_TP_MIN_Y -170
+#define J132_TP_MAX_Y 7685
+#define J132_TP_RES_Y \
+ ((J132_TP_MAX_Y - J132_TP_MIN_Y) / (J132_TP_DIMENSION_Y / 100))
+
+#define J680_TP_DIMENSION_X (float)16000
+#define J680_TP_MIN_X -7456
+#define J680_TP_MAX_X 7976
+#define J680_TP_RES_X \
+ ((J680_TP_MAX_X - J680_TP_MIN_X) / (J680_TP_DIMENSION_X / 100))
+#define J680_TP_DIMENSION_Y (float)10000
+#define J680_TP_MIN_Y -163
+#define J680_TP_MAX_Y 9283
+#define J680_TP_RES_Y \
+ ((J680_TP_MAX_Y - J680_TP_MIN_Y) / (J680_TP_DIMENSION_Y / 100))
+
+#define J680_ALT_TP_DIMENSION_X (float)16000
+#define J680_ALT_TP_MIN_X -7456
+#define J680_ALT_TP_MAX_X 7976
+#define J680_ALT_TP_RES_X \
+ ((J680_ALT_TP_MAX_X - J680_ALT_TP_MIN_X) / (J680_ALT_TP_DIMENSION_X / 100))
+#define J680_ALT_TP_DIMENSION_Y (float)10000
+#define J680_ALT_TP_MIN_Y -163
+#define J680_ALT_TP_MAX_Y 9283
+#define J680_ALT_TP_RES_Y \
+ ((J680_ALT_TP_MAX_Y - J680_ALT_TP_MIN_Y) / (J680_ALT_TP_DIMENSION_Y / 100))
+
+#define J213_TP_DIMENSION_X (float)13500
+#define J213_TP_MIN_X -6243
+#define J213_TP_MAX_X 6749
+#define J213_TP_RES_X \
+ ((J213_TP_MAX_X - J213_TP_MIN_X) / (J213_TP_DIMENSION_X / 100))
+#define J213_TP_DIMENSION_Y (float)8400
+#define J213_TP_MIN_Y -170
+#define J213_TP_MAX_Y 7685
+#define J213_TP_RES_Y \
+ ((J213_TP_MAX_Y - J213_TP_MIN_Y) / (J213_TP_DIMENSION_Y / 100))
+
+#define J214K_TP_DIMENSION_X (float)13200
+#define J214K_TP_MIN_X -6046
+#define J214K_TP_MAX_X 6536
+#define J214K_TP_RES_X \
+ ((J214K_TP_MAX_X - J214K_TP_MIN_X) / (J214K_TP_DIMENSION_X / 100))
+#define J214K_TP_DIMENSION_Y (float)8200
+#define J214K_TP_MIN_Y -164
+#define J214K_TP_MAX_Y 7439
+#define J214K_TP_RES_Y \
+ ((J214K_TP_MAX_Y - J214K_TP_MIN_Y) / (J214K_TP_DIMENSION_Y / 100))
+
+#define J223_TP_DIMENSION_X (float)13200
+#define J223_TP_MIN_X -6046
+#define J223_TP_MAX_X 6536
+#define J223_TP_RES_X \
+ ((J223_TP_MAX_X - J223_TP_MIN_X) / (J223_TP_DIMENSION_X / 100))
+#define J223_TP_DIMENSION_Y (float)8200
+#define J223_TP_MIN_Y -164
+#define J223_TP_MAX_Y 7439
+#define J223_TP_RES_Y \
+ ((J223_TP_MAX_Y - J223_TP_MIN_Y) / (J223_TP_DIMENSION_Y / 100))
+
+#define J230K_TP_DIMENSION_X (float)12100
+#define J230K_TP_MIN_X -5318
+#define J230K_TP_MAX_X 5787
+#define J230K_TP_RES_X \
+ ((J230K_TP_MAX_X - J230K_TP_MIN_X) / (J230K_TP_DIMENSION_X / 100))
+#define J230K_TP_DIMENSION_Y (float)8200
+#define J230K_TP_MIN_Y -157
+#define J230K_TP_MAX_Y 7102
+#define J230K_TP_RES_Y \
+ ((J230K_TP_MAX_Y - J230K_TP_MIN_Y) / (J230K_TP_DIMENSION_Y / 100))
+
+#define J152F_TP_DIMENSION_X (float)16000
+#define J152F_TP_MIN_X -7456
+#define J152F_TP_MAX_X 7976
+#define J152F_TP_RES_X \
+ ((J152F_TP_MAX_X - J152F_TP_MIN_X) / (J152F_TP_DIMENSION_X / 100))
+#define J152F_TP_DIMENSION_Y (float)10000
+#define J152F_TP_MIN_Y -163
+#define J152F_TP_MAX_Y 9283
+#define J152F_TP_RES_Y \
+ ((J152F_TP_MAX_Y - J152F_TP_MIN_Y) / (J152F_TP_DIMENSION_Y / 100))
+
/* These are fallback values, since the real values will be queried from the device. */
#define J314_TP_DIMENSION_X (float)13000
#define J314_TP_MIN_X -5900
@@ -130,7 +229,11 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
#define J314_TP_RES_Y \
((J314_TP_MAX_Y - J314_TP_MIN_Y) / (J314_TP_DIMENSION_Y / 100))
-#define J314_TP_MAX_FINGER_ORIENTATION 16384
+#define T2_TOUCHPAD_ENTRY(model) \
+ { USB_DEVICE_ID_APPLE_WELLSPRINGT2_##model, model##_TP_MIN_X, model##_TP_MIN_Y, \
+model##_TP_MAX_X, model##_TP_MAX_Y, model##_TP_RES_X, model##_TP_RES_Y }
+
+#define INTERNAL_TP_MAX_FINGER_ORIENTATION 16384
struct magicmouse_input_ops {
int (*raw_event)(struct hid_device *hdev,
@@ -733,7 +836,7 @@ static void report_finger_data(struct input_dev *input, int slot,
input_report_abs(input, ABS_MT_WIDTH_MINOR,
le16_to_int(f->tool_minor) << 1);
input_report_abs(input, ABS_MT_ORIENTATION,
- J314_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation));
+ INTERNAL_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation));
input_report_abs(input, ABS_MT_PRESSURE, le16_to_int(f->pressure));
input_report_abs(input, ABS_MT_POSITION_X, pos->x);
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
@@ -821,6 +924,20 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
}
+static int magicmouse_raw_event_t2(struct hid_device *hdev,
+ struct hid_report *report, u8 *data, int size)
+{
+ const size_t hdr_sz = sizeof(struct tp_mouse_report);
+
+ if (!size)
+ return 0;
+
+ if (data[0] != TRACKPAD2_USB_REPORT_ID || size < hdr_sz)
+ return 0;
+
+ return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
+}
+
static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
@@ -1018,8 +1135,32 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
return 0;
}
-static int magicmouse_setup_input_mtp(struct input_dev *input,
- struct hid_device *hdev)
+struct magicmouse_t2_properties {
+ u32 id;
+ int min_x;
+ int min_y;
+ int max_x;
+ int max_y;
+ int res_x;
+ int res_y;
+};
+
+static const struct magicmouse_t2_properties magicmouse_t2_configs[] = {
+ T2_TOUCHPAD_ENTRY(J140K),
+ T2_TOUCHPAD_ENTRY(J132),
+ T2_TOUCHPAD_ENTRY(J680),
+ T2_TOUCHPAD_ENTRY(J680_ALT),
+ T2_TOUCHPAD_ENTRY(J213),
+ T2_TOUCHPAD_ENTRY(J214K),
+ T2_TOUCHPAD_ENTRY(J223),
+ T2_TOUCHPAD_ENTRY(J230K),
+ T2_TOUCHPAD_ENTRY(J152F),
+};
+
+static int magicmouse_setup_input_int_tpd(struct input_dev *input,
+ struct hid_device *hdev, int min_x, int min_y,
+ int max_x, int max_y, int res_x, int res_y,
+ bool query_dimensions)
{
int error;
int mt_flags = 0;
@@ -1060,19 +1201,17 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
input_abs_set_res(input, ABS_MT_PRESSURE, 1);
/* finger orientation */
- input_set_abs_params(input, ABS_MT_ORIENTATION, -J314_TP_MAX_FINGER_ORIENTATION,
- J314_TP_MAX_FINGER_ORIENTATION, 0, 0);
+ input_set_abs_params(input, ABS_MT_ORIENTATION, -INTERNAL_TP_MAX_FINGER_ORIENTATION,
+ INTERNAL_TP_MAX_FINGER_ORIENTATION, 0, 0);
/* finger position */
- input_set_abs_params(input, ABS_MT_POSITION_X, J314_TP_MIN_X, J314_TP_MAX_X,
- 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_X, min_x, max_x, 0, 0);
/* Y axis is inverted */
- input_set_abs_params(input, ABS_MT_POSITION_Y, -J314_TP_MAX_Y, -J314_TP_MIN_Y,
- 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, -max_y, -min_y, 0, 0);
/* X/Y resolution */
- input_abs_set_res(input, ABS_MT_POSITION_X, J314_TP_RES_X);
- input_abs_set_res(input, ABS_MT_POSITION_Y, J314_TP_RES_Y);
+ input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
+ input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
input_set_events_per_packet(input, 60);
@@ -1099,7 +1238,20 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
*/
input->open = magicmouse_open;
input->close = magicmouse_close;
- msc->query_dimensions = true;
+ msc->query_dimensions = query_dimensions;
+
+ return 0;
+}
+
+static int magicmouse_setup_input_mtp(struct input_dev *input,
+ struct hid_device *hdev)
+{
+ int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X,
+ J314_TP_MIN_Y, J314_TP_MAX_X,
+ J314_TP_MAX_Y, J314_TP_RES_X,
+ J314_TP_RES_Y, true);
+ if (ret)
+ return ret;
return 0;
}
@@ -1107,7 +1259,34 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
static int magicmouse_setup_input_spi(struct input_dev *input,
struct hid_device *hdev)
{
- int ret = magicmouse_setup_input_mtp(input, hdev);
+ int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X,
+ J314_TP_MIN_Y, J314_TP_MAX_X,
+ J314_TP_MAX_Y, J314_TP_RES_X,
+ J314_TP_RES_Y, true);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int magicmouse_setup_input_t2(struct input_dev *input,
+ struct hid_device *hdev)
+{
+ int min_x, min_y, max_x, max_y, res_x, res_y;
+
+ for (size_t i = 0; i < ARRAY_SIZE(magicmouse_t2_configs); i++) {
+ if (magicmouse_t2_configs[i].id == hdev->product) {
+ min_x = magicmouse_t2_configs[i].min_x;
+ min_y = magicmouse_t2_configs[i].min_y;
+ max_x = magicmouse_t2_configs[i].max_x;
+ max_y = magicmouse_t2_configs[i].max_y;
+ res_x = magicmouse_t2_configs[i].res_x;
+ res_y = magicmouse_t2_configs[i].res_y;
+ }
+ }
+
+ int ret = magicmouse_setup_input_int_tpd(input, hdev, min_x, min_y,
+ max_x, max_y, res_x, res_y, false);
if (ret)
return ret;
@@ -1185,6 +1364,18 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev)
feature = feature_mt_trackpad2_usb;
}
break;
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
+ feature_size = sizeof(feature_mt_trackpad2_usb);
+ feature = feature_mt_trackpad2_usb;
+ break;
case USB_DEVICE_ID_APPLE_MAGICMOUSE2:
case USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC:
feature_size = sizeof(feature_mt_mouse2);
@@ -1278,8 +1469,23 @@ static int magicmouse_probe(struct hid_device *hdev,
int ret;
if ((id->bus == BUS_SPI || id->bus == BUS_HOST) && id->vendor == SPI_VENDOR_ID_APPLE &&
- hdev->type != HID_TYPE_SPI_MOUSE)
- return -ENODEV;
+ hdev->type != HID_TYPE_SPI_MOUSE)
+ return -ENODEV;
+
+ switch (id->product) {
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
+ if (hdev->type != HID_TYPE_USBMOUSE)
+ return -ENODEV;
+ break;
+ }
msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
if (msc == NULL) {
@@ -1289,15 +1495,33 @@ static int magicmouse_probe(struct hid_device *hdev,
// internal trackpad use a data format use input ops to avoid
// conflicts with the report ID.
- if (id->bus == BUS_HOST) {
+ switch (id->bus) {
+ case BUS_HOST:
msc->input_ops.raw_event = magicmouse_raw_event_mtp;
msc->input_ops.setup_input = magicmouse_setup_input_mtp;
- } else if (id->bus == BUS_SPI) {
+ break;
+ case BUS_SPI:
msc->input_ops.raw_event = magicmouse_raw_event_spi;
msc->input_ops.setup_input = magicmouse_setup_input_spi;
- } else {
- msc->input_ops.raw_event = magicmouse_raw_event_usb;
- msc->input_ops.setup_input = magicmouse_setup_input_usb;
+ break;
+ default:
+ switch (id->product) {
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
+ msc->input_ops.raw_event = magicmouse_raw_event_t2;
+ msc->input_ops.setup_input = magicmouse_setup_input_t2;
+ break;
+ default:
+ msc->input_ops.raw_event = magicmouse_raw_event_usb;
+ msc->input_ops.setup_input = magicmouse_setup_input_usb;
+ }
}
msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
@@ -1358,6 +1582,18 @@ static int magicmouse_probe(struct hid_device *hdev,
TRACKPAD2_USB_REPORT_ID, 0);
}
break;
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
+ TRACKPAD2_USB_REPORT_ID, 0);
+ break;
case HID_ANY_ID:
switch (id->bus) {
case BUS_HOST:
@@ -1467,6 +1703,24 @@ static const struct hid_device_id magic_mice[] = {
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), .driver_data = 0 },
{ HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID),
.driver_data = 0 },
{ HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE,
--
Armbian
@@ -1,53 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aditya Garg <gargaditya08@live.com>
Date: Wed, 8 Oct 2025 01:48:18 +0000
Subject: HID: magicmouse: fix regression breaking support for Magic Trackpad 1
The case HID_ANY_ID and default are technically the same, but the first
one was assigning no report to the Magic Trackpad 1, while the second
one assigns the correct report. Since the first case is matched first,
the Magic Trackpad 1 was not being assigned any report, breaking
support for it.
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/hid-magicmouse.c | 15 ++++------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -1594,7 +1594,7 @@ static int magicmouse_probe(struct hid_device *hdev,
report = hid_register_report(hdev, HID_INPUT_REPORT,
TRACKPAD2_USB_REPORT_ID, 0);
break;
- case HID_ANY_ID:
+ default:
switch (id->bus) {
case BUS_HOST:
report = hid_register_report(hdev, HID_INPUT_REPORT, MTP_REPORT_ID, 0);
@@ -1602,15 +1602,12 @@ static int magicmouse_probe(struct hid_device *hdev,
case BUS_SPI:
report = hid_register_report(hdev, HID_INPUT_REPORT, SPI_REPORT_ID, 0);
break;
- default:
- break;
+ default: /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
+ TRACKPAD_REPORT_ID, 0);
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
+ DOUBLE_REPORT_ID, 0);
}
- break;
- default: /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
- report = hid_register_report(hdev, HID_INPUT_REPORT,
- TRACKPAD_REPORT_ID, 0);
- report = hid_register_report(hdev, HID_INPUT_REPORT,
- DOUBLE_REPORT_ID, 0);
}
if (!report) {
--
Armbian
@@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ashish Arora <ashisharora.linux@outlook.com>
Date: Sat, 8 Jan 2022 21:43:18 +1100
Subject: drm/i915: Discard large BIOS framebuffers causing display corruption
On certain 4k panels, the BIOS framebuffer is larger than what panel
requires causing display corruption. Introduce a check for the same.
Signed-off-by: Ashish Arora <ashisharora.linux@outlook.com>
---
drivers/gpu/drm/i915/display/intel_fbdev.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -278,10 +278,10 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
ifbdev->fb = NULL;
if (fb &&
- (sizes->fb_width > fb->base.width ||
- sizes->fb_height > fb->base.height)) {
+ (sizes->fb_width != fb->base.width ||
+ sizes->fb_height != fb->base.height)) {
drm_dbg_kms(display->drm,
- "BIOS fb too small (%dx%d), we require (%dx%d),"
+ "BIOS fb not valid (%dx%d), we require (%dx%d),"
" releasing it\n",
fb->base.width, fb->base.height,
sizes->fb_width, sizes->fb_height);
--
Armbian