Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
eb92b74
arm64: configs: bcm2712: Enable CONFIG_SUSPEND
PineappleBeech Jul 21, 2026
d2be4e2
watchdog: bcm2835: Stop watchdog during suspend/resume
PineappleBeech Jul 21, 2026
8df5a5b
arm64: dts: bcm2712: wifi: Power off wifi during suspend/resume
PineappleBeech Jul 21, 2026
dfe038e
ACPI: PCI: bcm2712: Set acpi_storage_d3 to true on bcm2712
PineappleBeech Jul 23, 2026
f8692b1
iommu: bcm2712-iommu: Add suspend/resume support
PineappleBeech Aug 12, 2026
1190e36
drm/vc4: hdmi: Add suspend/resume support
PineappleBeech Aug 12, 2026
fcedc45
drm/vc4: Add suspend/resume support
PineappleBeech Aug 12, 2026
4cd36e6
drm/vc4: hvs: Add suspend/resume support
PineappleBeech Aug 12, 2026
0bdee42
gpio-brcmstb: Enable hibernation support
PineappleBeech Aug 14, 2026
09dda5c
bcm2385: mailbox: Add resumer hander for S3 wakeup on Pi5
timg236 Aug 17, 2026
3cd3df6
arm64: configs: bcm2712: Enable DPM watchdog
PineappleBeech Sep 2, 2026
abd985f
arm64: configs: bcm2712: Enable hibernation
PineappleBeech Sep 2, 2026
1756e29
pinctrl: pinctrl-brcmstb: Save pin mux and pad during suspend
PineappleBeech Aug 17, 2026
8e1bb66
serial: amba-pl011: Add start_rx to re-enable interrupts
PineappleBeech Aug 18, 2026
79f317f
irqchip: bcm2712-mip: Restore registers after suspend
PineappleBeech Aug 18, 2026
9000659
mailbox: rp1: check received event bits more carefully
P33M Aug 19, 2026
de37b53
mmc: sdhci-brcmstb: Reconfigure on resume
PineappleBeech Aug 19, 2026
0ed80cf
media: pisp_be: Add suspend/resume support
PineappleBeech Aug 21, 2026
fe30ab6
drm/rp1: dsi: Add suspend/resume support
PineappleBeech Aug 24, 2026
b8cc801
dt-bindings: bluetooth: Add power-off-in-suspend property
PineappleBeech Sep 4, 2026
bb127bd
Bluetooth: hci_bcm: Add support for powering off during suspend
PineappleBeech Sep 4, 2026
32f3f1f
arm64: dts: broadcom: bcm2712: Power off bluetooth in suspend
PineappleBeech Aug 25, 2026
1b9f707
arm64: dts: bcm2712: Add a regulator for pcie 3v3
PineappleBeech Aug 25, 2026
bc20083
drivers: rtc-rpi: Clear a pending alarm on resume and when setting an…
PineappleBeech Aug 25, 2026
aec21fa
media: imx708: Stop streaming during system suspend.
PineappleBeech Aug 28, 2026
6daaa49
usb: dwc3: HACK power-off in suspend flag
P33M Sep 7, 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
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ properties:
if the device's initial baud rate in normal mode is not supported by the
host or if the device requires autobaud mode startup before loading FW.

brcm,power-off-in-suspend:
type: boolean
description:
The controller's supply is not maintained while the system is in a sleep
state; the controller loses its firmware and its entire configuration
across a suspend/resume cycle.

interrupts:
items:
- description: Handle to the line HOST_WAKE used to wake
Expand Down
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 the regulator on the PCIe 3v3 supply.
This leaves it always enabled.


[ 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 on the PCIe 3v3 supply.
* Its is enabled by default by the firmware.
*/
fragment@4 {
target = <&pcie1_3v3>;
__dormant__ {
status = "disabled";
};
};

__overrides__ {
l1ss = <0>, "+0";
no-l0s = <0>, "+1";
no-mip = <0>, "+2";
mmio-hi = <0>, "+3";
no-pwr-ctrl = <0>, "+4";
};
};
31 changes: 31 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,24 @@ rp1_target: &pcie2 {

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

/*
* Hack to get linux to probe this pcie after pcie2.
* The pcie-brcmstb driver does not defer probe if
* the regulator is not found yet. This forces pcie1
* to be probed after pcie2 so that the regulator
* is found.
*/
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 @@ -374,6 +403,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { };
compatible = "brcm,bcm43438-bt";
max-speed = <3000000>;
shutdown-gpios = <&gio 29 GPIO_ACTIVE_HIGH>;
brcm,power-off-in-suspend;
local-bd-address = [ 00 00 00 00 00 00 ];
};
};
Expand Down Expand Up @@ -426,6 +456,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
2 changes: 2 additions & 0 deletions arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { };
compatible = "brcm,bcm43438-bt";
max-speed = <3000000>;
shutdown-gpios = <&gio 29 GPIO_ACTIVE_HIGH>;
brcm,power-off-in-suspend;
local-bd-address = [ 00 00 00 00 00 00 ];
};
};
Expand Down Expand Up @@ -411,6 +412,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
33 changes: 33 additions & 0 deletions arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5io.dtsi
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
// SPDX-License-Identifier: GPL-2.0

/ {
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>;
};
};

&pcie1 {
/*
* Hack to get linux to probe this pcie after pcie2.
* The pcie-brcmstb driver does not defer probe if
* the regulator is not found yet. This forces pcie1
* to be probed after pcie2 so that the regulator
* is found.
*/
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>;
};
};

i2c_csi_dsi1: &i2c0 { // Note: This is for CAM/DISP 1 connector
symlink = "i2c-11";
};
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
81 changes: 80 additions & 1 deletion drivers/bluetooth/hci_bcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/dmi.h>
#include <linux/pm_runtime.h>
#include <linux/serdev.h>
#include <linux/workqueue.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
Expand Down Expand Up @@ -107,6 +108,8 @@ struct bcm_device_data {
* @no_uart_clock_set: UART clock set command for >3Mbps mode is unavailable
* @pcm_int_params: keep the initial PCM configuration
* @use_autobaud_mode: start Bluetooth device in autobaud mode
* @power_off_in_suspend: controller loses power during a system suspend, so
* the device is reprobed on resume
* @max_autobaud_speed: max baudrate supported by device in autobaud mode
*/
struct bcm_device {
Expand Down Expand Up @@ -147,6 +150,7 @@ struct bcm_device {
bool drive_rts_on_open;
bool no_uart_clock_set;
bool use_autobaud_mode;
bool power_off_in_suspend;
u8 pcm_int_params[5];
u32 max_autobaud_speed;
};
Expand All @@ -159,6 +163,36 @@ struct bcm_data {
struct bcm_device *dev;
};

/* True when the controller will be powered off across a system suspend and
* rebuilt by a reprobe. Runtime PM is switched off for these devices, so the
* runtime callbacks cannot race the suspend path.
*/
static bool bcm_powers_off_in_suspend(const struct bcm_device *bdev)
{
return IS_ENABLED(CONFIG_PM_SLEEP) && bdev &&
bdev->power_off_in_suspend && bdev->hu && bdev->hu->serdev;
}

struct bcm_reprobe {
struct device *dev;
struct work_struct work;
};

static void bcm_reprobe_worker(struct work_struct *work)
{
struct bcm_reprobe *reprobe =
container_of(work, struct bcm_reprobe, work);
int ret;

ret = device_reprobe(reprobe->dev);
if (ret && ret != -EPROBE_DEFER)
dev_err(reprobe->dev, "Reprobe error %d\n", ret);

put_device(reprobe->dev);
kfree(reprobe);
module_put(THIS_MODULE);
}

/* List of BCM BT UART devices */
static DEFINE_MUTEX(bcm_device_lock);
static LIST_HEAD(bcm_device_list);
Expand Down Expand Up @@ -485,6 +519,12 @@ static int bcm_open(struct hci_uart *hu)

out:
if (bcm->dev) {
/* Since bcm_resume() reprobes the device, the suspend handling
* done by the hci_suspend_notifier is not necessary.
*/
if (bcm_powers_off_in_suspend(bcm->dev))
set_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags);

if (bcm->dev->use_autobaud_mode)
hci_uart_set_flow_control(hu, false); /* Assert BT_UART_CTS_N */
else if (bcm->dev->drive_rts_on_open)
Expand Down Expand Up @@ -546,6 +586,7 @@ static int bcm_close(struct hci_uart *hu)

if (bdev) {
if (IS_ENABLED(CONFIG_PM) && bdev->irq_acquired) {
bdev->irq_acquired = false;
devm_free_irq(bdev->dev, bdev->irq, bdev);
device_init_wakeup(bdev->dev, false);
pm_runtime_disable(bdev->dev);
Expand Down Expand Up @@ -646,7 +687,7 @@ static int bcm_setup(struct hci_uart *hu)
if (hci_test_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR))
hci_set_quirk(hu->hdev, HCI_QUIRK_USE_BDADDR_PROPERTY);

if (!bcm_request_irq(bcm))
if (!bcm_powers_off_in_suspend(bcm->dev) && !bcm_request_irq(bcm))
err = bcm_setup_sleep(hu);

return err;
Expand Down Expand Up @@ -825,6 +866,25 @@ static int bcm_suspend(struct device *dev)

bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);

/* The controller loses power across the suspend and bcm_resume()
* reprobes it, so there is no state here worth preserving. Stop the
* UART and drive the controller off, as h5_btrtl_suspend() does.
*/
if (bcm_powers_off_in_suspend(bdev)) {
struct hci_dev *hdev = bdev->hu->hdev;

/* Wait for power_on before suspending. bcm_setup causes
* a timeout if a suspend occurs duriung it
*/
if (hdev)
flush_work(&hdev->power_on);

hci_uart_set_flow_control(bdev->hu, true);
bcm_gpio_set_power(bdev, false);

return 0;
}

/*
* When used with a device instantiated as platform_device, bcm_suspend
* can be called at any time as long as the platform device is bound,
Expand Down Expand Up @@ -859,6 +919,23 @@ static int bcm_resume(struct device *dev)

bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);

/* The device has lost all of its firmware and state so reprobe it. */
if (bcm_powers_off_in_suspend(bdev)) {
struct bcm_reprobe *reprobe;

reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL);
if (!reprobe)
return -ENOMEM;

__module_get(THIS_MODULE);

INIT_WORK(&reprobe->work, bcm_reprobe_worker);
reprobe->dev = get_device(bdev->dev);
queue_work(system_long_wq, &reprobe->work);

return 0;
}

/*
* When used with a device instantiated as platform_device, bcm_resume
* can be called at any time as long as platform device is bound,
Expand Down Expand Up @@ -1229,6 +1306,8 @@ static int bcm_of_probe(struct bcm_device *bdev)
{
bdev->use_autobaud_mode = device_property_read_bool(bdev->dev,
"brcm,requires-autobaud-mode");
bdev->power_off_in_suspend = device_property_read_bool(bdev->dev,
"brcm,power-off-in-suspend");
device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed);
device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params",
bdev->pcm_int_params, 5);
Expand Down
4 changes: 2 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,7 @@ 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,
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(brcmstb_gpio_suspend, brcmstb_gpio_resume)
};

static int brcmstb_gpio_probe(struct platform_device *pdev)
Expand Down
Loading