Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e88338e
arm64: configs: Enable CONFIG_SUSPEND
PineappleBeech Jul 21, 2026
f06b1e5
watchdog: bcm2835: Stop watchdog during suspend/resume
PineappleBeech Jul 21, 2026
b07e653
arm64: dts: broadcom: bcm2712: Power off wireless during suspend/resume
PineappleBeech Jul 21, 2026
bd60a51
ACPI: PCI: bcm2712: Set acpi_storage_d3 to true on bcm2712
PineappleBeech Jul 23, 2026
9b38702
iommu: bcm2712-iommu: Add suspend/resume support
PineappleBeech Aug 12, 2026
964750b
drm/vc4: hdmi: Add suspend/resume support
PineappleBeech Aug 12, 2026
3a8d259
drm/vc4: Add suspend/resume support
PineappleBeech Aug 12, 2026
50238c7
drm/vc4: hvs: Add suspend/resume support
PineappleBeech Aug 12, 2026
0981b46
gpio-brcmstb: Enable hibernation support
PineappleBeech Aug 14, 2026
6b593a7
bcm2385: mailbox: Add resumer hander for S3 wakeup on Pi5
timg236 Aug 17, 2026
b7e14c2
arm64: configs: Enable PM Watchdog and Hibernation for testing
PineappleBeech Aug 17, 2026
0e9b665
pinctrl: pinctrl-brcmstb: Save pin mux and pad during suspend
PineappleBeech Aug 17, 2026
a8b7247
serial: amba-pl011: Add start_rx to re-enable interrupts
PineappleBeech Aug 18, 2026
d627f4f
drm/vc4: hdmi: Ignore the hsm clock on resume
PineappleBeech Aug 18, 2026
e2fe239
irqchip: bcm2712-mip: Restore registers after suspend
PineappleBeech Aug 18, 2026
33b71af
mailbox: rp1: check received event bits more carefully
P33M Aug 19, 2026
35fcd28
mmc: sdhci-brcmstb: Reconfigure on resume
PineappleBeech Aug 19, 2026
09b301e
arm64: dts: bcm2712: Add 3v3 regulator for pcie1
PineappleBeech Aug 20, 2026
a6f3b97
overlays: pciex1-compat-pi5: Add parameter to keep pcie 3v3 enabled
PineappleBeech Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions arch/arm/boot/dts/overlays/README
Original file line number Diff line number Diff line change
Expand Up @@ -3992,6 +3992,8 @@ Params: l1ss Enable RC ASPM L1 sub-state support. Requires
requires DMA and MSI addresses to be 32bit.
mmio-hi Move the start of outbound 32bit addresses to
2GB and expand 64bit outbound space to 14GB.
no-pwr-ctrl Disable power control for 3v3. It is left
permanently powered on.


[ The pcf2127-rtc overlay has been deleted. See i2c-rtc. ]
Expand Down
12 changes: 12 additions & 0 deletions arch/arm/boot/dts/overlays/pciex1-compat-pi5-overlay.dts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,22 @@
};
};

/*
* Disable the regulator control for 3v3.
* This stops the device from losing power
*/
fragment@4 {
target = <&pcie1_3v3>;
__dormant__ {
regulator-always-on;
};
};

__overrides__ {
l1ss = <0>, "+0";
no-l0s = <0>, "+1";
no-mip = <0>, "+2";
mmio-hi = <0>, "+3";
no-pwr-ctrl = <0>, "+4";
};
};
25 changes: 25 additions & 0 deletions arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@
gpio = <&rp1_gpio 46 0>; // CD1_IO0_MICCLK, to MIPI 1 connector
};

pcie1_3v3: pcie1_3v3 {
compatible = "regulator-fixed";
regulator-name = "pcie1-3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
enable-active-high;
gpio = <&rp1_gpio 28 GPIO_ACTIVE_HIGH>; // PCIE_RP1_WAKE
startup-delay-us = <20000>;
};

cam_dummy_reg: cam_dummy_reg {
compatible = "regulator-fixed";
regulator-name = "cam-dummy-reg";
Expand All @@ -125,6 +136,19 @@ rp1_target: &pcie2 {

&pcie1 {
brcm,fifo-qos-map = /bits/ 8 <3 3 3 3>;

// Make this a consumer of rp1
vpcie3v3-supply = <&pcie1_3v3>;

pci@0,0 {
device_type = "pci";
reg = <0 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
ranges;

vpcie3v3-supply = <&pcie1_3v3>;
};
};

// The system SPI for the bootloader EEPROM
Expand Down Expand Up @@ -426,6 +450,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { };
vmmc-supply = <&wl_on_reg>;
sd-uhs-ddr50;
non-removable;
cap-power-off-card;
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
Expand Down
25 changes: 25 additions & 0 deletions arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@
gpio = <&rp1_gpio 34 0>; // CD0_IO0_MICCLK, to CAM_GPIO on connector
};

pcie1_3v3: pcie1_3v3 {
compatible = "regulator-fixed";
regulator-name = "pcie1-3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
enable-active-high;
gpio = <&rp1_gpio 28 GPIO_ACTIVE_HIGH>; // PCIE_PWR_EN
startup-delay-us = <20000>;
};

cam_dummy_reg: cam_dummy_reg {
compatible = "regulator-fixed";
regulator-name = "cam-dummy-reg";
Expand All @@ -112,6 +123,19 @@ rp1_target: &pcie2 {

&pcie1 {
brcm,fifo-qos-map = /bits/ 8 <3 3 3 3>;

// Make this a consumer of rp1
vpcie3v3-supply = <&pcie1_3v3>;

@P33M P33M Aug 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the devicetree binding in Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml this should be under the child node (and not duplicated). It's also unrelated to rp1, so why the comment?


pci@0,0 {
device_type = "pci";
reg = <0 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
ranges;

vpcie3v3-supply = <&pcie1_3v3>;
};
};

// The system SPI for the bootloader EEPROM
Expand Down Expand Up @@ -411,6 +435,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { };
vmmc-supply = <&wl_on_reg>;
sd-uhs-ddr50;
non-removable;
cap-power-off-card;
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
Expand Down
7 changes: 4 additions & 3 deletions arch/arm64/configs/bcm2712_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ CONFIG_ARM64_ERRATUM_2441009=y
CONFIG_ARM64_16K_PAGES=y
CONFIG_ARM64_VA_BITS_47=y
CONFIG_NR_CPUS=4
CONFIG_HOTPLUG_CPU=y
CONFIG_NUMA=y
CONFIG_COMPAT=y
CONFIG_ARMV8_DEPRECATED=y
Expand All @@ -59,9 +58,11 @@ CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
# CONFIG_SUSPEND is not set
CONFIG_PM=y
CONFIG_HIBERNATION=y
CONFIG_PM_DEBUG=y
CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=30
CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT=5
CONFIG_CPU_IDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
Expand Down
12 changes: 10 additions & 2 deletions drivers/gpio/gpio-brcmstb.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/string_choices.h>

enum gio_reg_index {
Expand Down Expand Up @@ -576,8 +577,15 @@ static int brcmstb_gpio_resume(struct device *dev)
#endif /* CONFIG_PM_SLEEP */

static const struct dev_pm_ops brcmstb_gpio_pm_ops = {
.suspend_noirq = brcmstb_gpio_suspend,
.resume_noirq = brcmstb_gpio_resume,
/*
* A hibernate power cycle wipes this GPIO bank's registers, same
* as a suspend-to-RAM transition. Only wiring .suspend_noirq/
* .resume_noirq left the save/restore logic below unreachable on
* the freeze/thaw and poweroff/restore phases hibernate actually
* uses, so an output pin's level (and anything else save/restore
* covers) was silently lost across hibernate specifically.
*/
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(brcmstb_gpio_suspend, brcmstb_gpio_resume)
};

static int brcmstb_gpio_probe(struct platform_device *pdev)
Expand Down
17 changes: 17 additions & 0 deletions drivers/gpu/drm/vc4/vc4_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,22 @@ static void vc4_platform_drm_shutdown(struct platform_device *pdev)
drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
}

static int vc4_drm_suspend(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);

return drm_mode_config_helper_suspend(drm);
}

static int vc4_drm_resume(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);

return drm_mode_config_helper_resume(drm);
}

static DEFINE_SIMPLE_DEV_PM_OPS(vc4_drm_pm_ops, vc4_drm_suspend, vc4_drm_resume);

static const struct of_device_id vc4_of_match[] = {
{ .compatible = "brcm,bcm2711-vc5", .data = (void *)VC4_GEN_5 },
/* NB GEN_6_C will be corrected on D0 hw to GEN_6_D via vc4_hvs_bind */
Expand All @@ -511,6 +527,7 @@ static struct platform_driver vc4_platform_driver = {
.driver = {
.name = "vc4-drm",
.of_match_table = vc4_of_match,
.pm = pm_sleep_ptr(&vc4_drm_pm_ops),
},
};

Expand Down
18 changes: 7 additions & 11 deletions drivers/gpu/drm/vc4/vc4_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3091,19 +3091,13 @@ static int vc4_hdmi_runtime_resume(struct device *dev)
return ret;

/*
* Whenever the RaspberryPi boots without an HDMI monitor
* plugged in, the firmware won't have initialized the HSM clock
* rate and it will be reported as 0.
*
* If we try to access a register of the controller in such a
* case, it will lead to a silent CPU stall. Let's make sure we
* prevent such a case.
* The clock rate may be reported wrong after suspend to RAM.
* This may cause a cpu stall.
*/
rate = clk_get_rate(vc4_hdmi->hsm_clock);
if (!rate) {
ret = -EINVAL;
goto err_disable_clk;
}
if (!rate)
dev_warn(&vc4_hdmi->pdev->dev,
"hsm_clock rate is 0, proceeding anyway\n");

ret = clk_prepare_enable(vc4_hdmi->audio_clock);
if (ret)
Expand Down Expand Up @@ -3441,6 +3435,8 @@ static const struct dev_pm_ops vc4_hdmi_pm_ops = {
SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend,
vc4_hdmi_runtime_resume,
NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};

struct platform_driver vc4_hdmi_driver = {
Expand Down
64 changes: 52 additions & 12 deletions drivers/gpu/drm/vc4/vc4_hvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/platform_device.h>
#include <linux/pm.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
Expand Down Expand Up @@ -437,12 +438,28 @@ static const u32 nearest_neighbour_kernel[] =
VC4_LINEAR_PHASE_KERNEL(0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 255, 255, 255, 255);

static void vc4_hvs_write_linear_kernel(struct vc4_hvs *hvs,
struct drm_mm_node *space,
const u32 *kernel)
{
u32 __iomem *dst_kernel = hvs->dlist + space->start;
unsigned int i;

for (i = 0; i < VC4_KERNEL_DWORDS; i++) {
if (i < VC4_LINEAR_PHASE_KERNEL_DWORDS)
writel(kernel[i], &dst_kernel[i]);
else {
writel(kernel[VC4_KERNEL_DWORDS - i - 1],
&dst_kernel[i]);
}
}
}

static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
struct drm_mm_node *space,
const u32 *kernel)
{
int ret, i;
u32 __iomem *dst_kernel;
int ret;

/*
* NOTE: We don't need a call to drm_dev_enter()/drm_dev_exit()
Expand All @@ -456,16 +473,7 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
return ret;
}

dst_kernel = hvs->dlist + space->start;

for (i = 0; i < VC4_KERNEL_DWORDS; i++) {
if (i < VC4_LINEAR_PHASE_KERNEL_DWORDS)
writel(kernel[i], &dst_kernel[i]);
else {
writel(kernel[VC4_KERNEL_DWORDS - i - 1],
&dst_kernel[i]);
}
}
vc4_hvs_write_linear_kernel(hvs, space, kernel);

return 0;
}
Expand Down Expand Up @@ -2109,6 +2117,8 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
if (IS_ERR(hvs))
return PTR_ERR(hvs);

platform_set_drvdata(pdev, hvs);

hvs->regset.base = hvs->regs;

if (vc4->gen == VC4_GEN_6_C) {
Expand Down Expand Up @@ -2291,6 +2301,35 @@ static void vc4_hvs_dev_remove(struct platform_device *pdev)
component_del(&pdev->dev, &vc4_hvs_ops);
}

static int vc4_hvs_resume_early(struct device *dev)
{
struct vc4_hvs *hvs = platform_get_drvdata(to_platform_device(dev));
struct vc4_dev *vc4;
int ret;

if (!hvs)
return 0;

vc4 = hvs->vc4;
if (vc4->gen >= VC4_GEN_6_C)
ret = vc6_hvs_hw_init(hvs);
else
ret = vc4_hvs_hw_init(hvs);
if (ret)
return ret;

vc4_hvs_write_linear_kernel(hvs, &hvs->mitchell_netravali_filter,
mitchell_netravali_1_3_1_3_kernel);
vc4_hvs_write_linear_kernel(hvs, &hvs->nearest_neighbour_filter,
nearest_neighbour_kernel);

return vc4_hvs_cob_init(hvs);
}

static const struct dev_pm_ops vc4_hvs_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, vc4_hvs_resume_early)
};

static const struct of_device_id vc4_hvs_dt_match[] = {
{ .compatible = "brcm,bcm2711-hvs" },
{ .compatible = "brcm,bcm2712-hvs" },
Expand All @@ -2304,5 +2343,6 @@ struct platform_driver vc4_hvs_driver = {
.driver = {
.name = "vc4_hvs",
.of_match_table = vc4_hvs_dt_match,
.pm = pm_sleep_ptr(&vc4_hvs_pm_ops),
},
};
Loading