Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 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
97a4845
drm/vc4: hdmi: Add suspend/resume support
PineappleBeech Aug 12, 2026
fe0f6a4
drm/vc4: Add suspend/resume support
PineappleBeech Aug 12, 2026
1cea704
drm/vc4: hvs: Add suspend/resume support
PineappleBeech Aug 12, 2026
3bb6cae
gpio-brcmstb: Enable hibernation support
PineappleBeech Aug 14, 2026
45a2c42
bcm2385: mailbox: Add resumer hander for S3 wakeup on Pi5
timg236 Aug 17, 2026
4675988
arm64: configs: bcm2712: Enable DPM watchdog
PineappleBeech Sep 2, 2026
a742d4b
arm64: configs: bcm2712: Enable hibernation
PineappleBeech Sep 2, 2026
6ed825c
pinctrl: pinctrl-brcmstb: Save pin mux and pad during suspend
PineappleBeech Aug 17, 2026
181495d
serial: amba-pl011: Add start_rx to re-enable interrupts
PineappleBeech Aug 18, 2026
bf45fa3
drm/vc4: hdmi: Ignore the hsm clock on resume
PineappleBeech Aug 18, 2026
fd1ceb6
irqchip: bcm2712-mip: Restore registers after suspend
PineappleBeech Aug 18, 2026
58ecfd7
mailbox: rp1: check received event bits more carefully
P33M Aug 19, 2026
2acdeba
mmc: sdhci-brcmstb: Reconfigure on resume
PineappleBeech Aug 19, 2026
6edd879
media: pisp_be: Add suspend/resume support
PineappleBeech Aug 21, 2026
2c119f0
drm/rp1: dsi: Add suspend/resume support
PineappleBeech Aug 24, 2026
1f67cab
bluetooth: hci_bcm: Add support for powering off the device in suspend
PineappleBeech Aug 25, 2026
38a83df
arm64: dts: broadcom: bcm2712: Power off bluetooth in suspend
PineappleBeech Aug 25, 2026
6e5fcf3
arm64: dts: bcm2712: Add a regulator for pcie 3v3
PineappleBeech Aug 25, 2026
6893992
drivers: rtc-rpi: Clear a pending alarm on resume and when setting an…
PineappleBeech Aug 25, 2026
17a7254
media: imx708: Stop streaming during system suspend.
PineappleBeech Aug 28, 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,12 @@ 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:
Set this property if the controller is powered off during a system
suspend.

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
80 changes: 73 additions & 7 deletions drivers/bluetooth/hci_bcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ 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 and
* has to be rebuilt on resume
* @hci_registered: whether the hci_uart currently has a registered hci_dev
* @max_autobaud_speed: max baudrate supported by device in autobaud mode
*/
struct bcm_device {
Expand Down Expand Up @@ -147,6 +150,8 @@ struct bcm_device {
bool drive_rts_on_open;
bool no_uart_clock_set;
bool use_autobaud_mode;
bool power_off_in_suspend;
bool hci_registered;
u8 pcm_int_params[5];
u32 max_autobaud_speed;
};
Expand All @@ -159,6 +164,8 @@ struct bcm_data {
struct bcm_device *dev;
};

static const struct hci_uart_proto bcm_proto;

/* List of BCM BT UART devices */
static DEFINE_MUTEX(bcm_device_lock);
static LIST_HEAD(bcm_device_list);
Expand Down Expand Up @@ -485,6 +492,14 @@ 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 (IS_ENABLED(CONFIG_PM_SLEEP) && hu->serdev &&
bcm->dev->power_off_in_suspend)
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 @@ -825,6 +840,21 @@ static int bcm_suspend(struct device *dev)

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

/*
* Unregister the device before suspend since it will lose power.
* Flush power_on so that bcm_setup is not running. This avoids a
* timeout when the device is being unregistered during bcm_setup
*/
if (bdev->power_off_in_suspend && bdev->hu && bdev->hci_registered) {
struct hci_dev *hdev = bdev->hu->hdev;

if (hdev)
disable_work_sync(&hdev->power_on);

hci_uart_unregister_device(bdev->hu);
bdev->hci_registered = false;
}

/*
* 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 All @@ -836,10 +866,11 @@ static int bcm_suspend(struct device *dev)
if (!bdev->hu)
goto unlock;

if (pm_runtime_active(dev))
if (!bdev->power_off_in_suspend && pm_runtime_active(dev))
bcm_suspend_device(dev);

if (device_may_wakeup(dev) && bdev->irq > 0) {
if (!bdev->power_off_in_suspend && device_may_wakeup(dev) &&
bdev->irq > 0) {
error = enable_irq_wake(bdev->irq);
if (!error)
bt_dev_dbg(bdev, "BCM irq: enabled");
Expand All @@ -855,6 +886,7 @@ static int bcm_suspend(struct device *dev)
static int bcm_resume(struct device *dev)
{
struct bcm_device *bdev = dev_get_drvdata(dev);
struct hci_uart *hu;
int err = 0;

bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
Expand All @@ -867,15 +899,18 @@ static int bcm_resume(struct device *dev)
*/
mutex_lock(&bcm_device_lock);

if (!bdev->hu)
hu = bdev->hu;
if (!hu)
goto unlock;

if (device_may_wakeup(dev) && bdev->irq > 0) {
if (!bdev->power_off_in_suspend && device_may_wakeup(dev) &&
bdev->irq > 0) {
disable_irq_wake(bdev->irq);
bt_dev_dbg(bdev, "BCM irq: disabled");
}

err = bcm_resume_device(dev);
if (!bdev->power_off_in_suspend)
err = bcm_resume_device(dev);

unlock:
mutex_unlock(&bcm_device_lock);
Expand All @@ -886,6 +921,26 @@ static int bcm_resume(struct device *dev)
pm_runtime_enable(dev);
}

/*
* On boards flagged with brcm,power-off-in-suspend the controller is
* powered down entirely across a system suspend.
*
* Register the HCI device again.
*
* This has to be outside bcm_device_lock, which bcm_open() takes.
*/
if (hu && hu->serdev && bdev->power_off_in_suspend &&
!bdev->hci_registered) {
int rerr;

rerr = hci_uart_register_device(hu, &bcm_proto);
if (rerr)
dev_err(dev, "Failed to register HCI device: %d\n",
rerr);
else
bdev->hci_registered = true;
}

return 0;
}
#endif
Expand Down Expand Up @@ -1229,6 +1284,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 Expand Up @@ -1557,14 +1614,23 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
bcmdev->oper_speed = data->max_speed;
}

return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
err = hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
if (err)
return err;

bcmdev->hci_registered = true;

return 0;
}

static void bcm_serdev_remove(struct serdev_device *serdev)
{
struct bcm_device *bcmdev = serdev_device_get_drvdata(serdev);

hci_uart_unregister_device(&bcmdev->serdev_hu);
if (bcmdev->hci_registered) {
hci_uart_unregister_device(&bcmdev->serdev_hu);
bcmdev->hci_registered = false;
}
}

#ifdef CONFIG_OF
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