+++ /dev/null
-From c6cd3e6878e32548ea90c4160c534e952221c194 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.com>
-Date: Wed, 28 Apr 2021 17:46:01 +0100
-Subject: [PATCH 0536/1085] dmaengine: dw-axi-dmac: Fixes for RP1
-
-Don't assume that DMA addresses of devices are the same as their
-physical addresses - convert correctly.
-
-The CFG2 register layout is used when there are more than 8 channels,
-but also when configured for more than 16 target peripheral devices
-because the index of the handshake signal has to be made wider.
-
-Reset the DMAC on probe
-
-The driver goes to the trouble of tracking when transfers have been
-paused, but then doesn't report that state when queried.
-
-Not having APB registers is not an error - for most use cases it's
-not even of interest, it's expected. Demote the message to debug level,
-which is disabled by default.
-
-Each channel has a descriptor pool, which is shared between transfers.
-It is unsafe to treat the total number of descriptors allocated from a
-pool as the number allocated to a specific transfer; doing so leads
-to releasing buffers that shouldn't be released and walking off the
-ends of descriptor lists. Instead, give each transfer descriptor its
-own count.
-
-Support partial transfers:
-Some use cases involve streaming from a device where the transfer only
-proceeds when the device's FIFO occupancy exceeds a certain threshold.
-In such cases (e.g. when pulling data from a UART) it is important to
-know how much data has been transferred so far, in order that remaining
-bytes can be read from the FIFO directly by software.
-
-Add the necessary code to provide this "residue" value with a finer,
-sub-transfer granularity.
-
-In order to prevent the occasional byte getting stuck in the DMA
-controller's internal buffers, restrict the destination memory width
-to the source register width.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.com>
----
- .../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 132 +++++++++++++++---
- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 1 +
- 2 files changed, 113 insertions(+), 20 deletions(-)
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -12,6 +12,7 @@
- #include <linux/device.h>
- #include <linux/dmaengine.h>
- #include <linux/dmapool.h>
-+#include <linux/dma-direct.h>
- #include <linux/dma-mapping.h>
- #include <linux/err.h>
- #include <linux/interrupt.h>
-@@ -84,6 +85,17 @@ axi_chan_iowrite64(struct axi_dma_chan *
- iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4);
- }
-
-+static inline u64
-+axi_chan_ioread64(struct axi_dma_chan *chan, u32 reg)
-+{
-+ /*
-+ * We split one 64 bit read into two 32 bit reads as some HW doesn't
-+ * support 64 bit access.
-+ */
-+ return ((u64)ioread32(chan->chan_regs + reg + 4) << 32) +
-+ ioread32(chan->chan_regs + reg);
-+}
-+
- static inline void axi_chan_config_write(struct axi_dma_chan *chan,
- struct axi_dma_chan_config *config)
- {
-@@ -220,7 +232,18 @@ static void axi_dma_hw_init(struct axi_d
- {
- int ret;
- u32 i;
-+ int retries = 1000;
-
-+ axi_dma_iowrite32(chip, DMAC_RESET, 1);
-+ while (axi_dma_ioread32(chip, DMAC_RESET)) {
-+ retries--;
-+ if (!retries) {
-+ dev_err(chip->dev, "%s: DMAC failed to reset\n",
-+ __func__);
-+ return;
-+ }
-+ cpu_relax();
-+ }
- for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
- axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
- axi_chan_disable(&chip->dw->chan[i]);
-@@ -283,7 +306,7 @@ static struct axi_dma_lli *axi_desc_get(
- static void axi_desc_put(struct axi_dma_desc *desc)
- {
- struct axi_dma_chan *chan = desc->chan;
-- int count = desc->nr_hw_descs;
-+ u32 count = desc->hw_desc_count;
- struct axi_dma_hw_desc *hw_desc;
- int descs_put;
-
-@@ -305,6 +328,48 @@ static void vchan_desc_put(struct virt_d
- axi_desc_put(vd_to_axi_desc(vdesc));
- }
-
-+static u32 axi_dma_desc_src_pos(struct axi_dma_desc *desc, dma_addr_t addr)
-+{
-+ unsigned int idx = 0;
-+ u32 pos = 0;
-+
-+ while (pos < desc->length) {
-+ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++];
-+ u32 len = hw_desc->len;
-+ dma_addr_t start = le64_to_cpu(hw_desc->lli->sar);
-+
-+ if (addr >= start && addr <= (start + len)) {
-+ pos += addr - start;
-+ break;
-+ }
-+
-+ pos += len;
-+ }
-+
-+ return pos;
-+}
-+
-+static u32 axi_dma_desc_dst_pos(struct axi_dma_desc *desc, dma_addr_t addr)
-+{
-+ unsigned int idx = 0;
-+ u32 pos = 0;
-+
-+ while (pos < desc->length) {
-+ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++];
-+ u32 len = hw_desc->len;
-+ dma_addr_t start = le64_to_cpu(hw_desc->lli->dar);
-+
-+ if (addr >= start && addr <= (start + len)) {
-+ pos += addr - start;
-+ break;
-+ }
-+
-+ pos += len;
-+ }
-+
-+ return pos;
-+}
-+
- static enum dma_status
- dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
- struct dma_tx_state *txstate)
-@@ -314,10 +379,7 @@ dma_chan_tx_status(struct dma_chan *dcha
- enum dma_status status;
- u32 completed_length;
- unsigned long flags;
-- u32 completed_blocks;
- size_t bytes = 0;
-- u32 length;
-- u32 len;
-
- status = dma_cookie_status(dchan, cookie, txstate);
- if (status == DMA_COMPLETE || !txstate)
-@@ -326,16 +388,31 @@ dma_chan_tx_status(struct dma_chan *dcha
- spin_lock_irqsave(&chan->vc.lock, flags);
-
- vdesc = vchan_find_desc(&chan->vc, cookie);
-- if (vdesc) {
-- length = vd_to_axi_desc(vdesc)->length;
-- completed_blocks = vd_to_axi_desc(vdesc)->completed_blocks;
-- len = vd_to_axi_desc(vdesc)->hw_desc[0].len;
-- completed_length = completed_blocks * len;
-- bytes = length - completed_length;
-+ if (vdesc && vdesc == vchan_next_desc(&chan->vc)) {
-+ /* This descriptor is in-progress */
-+ struct axi_dma_desc *desc = vd_to_axi_desc(vdesc);
-+ dma_addr_t addr;
-+
-+ if (chan->direction == DMA_MEM_TO_DEV) {
-+ addr = axi_chan_ioread64(chan, CH_SAR);
-+ completed_length = axi_dma_desc_src_pos(desc, addr);
-+ } else if (chan->direction == DMA_DEV_TO_MEM) {
-+ addr = axi_chan_ioread64(chan, CH_DAR);
-+ completed_length = axi_dma_desc_dst_pos(desc, addr);
-+ } else {
-+ completed_length = 0;
-+ }
-+ bytes = desc->length - completed_length;
-+ } else if (vdesc) {
-+ /* Still in the queue so not started */
-+ bytes = vd_to_axi_desc(vdesc)->length;
- }
-
-- spin_unlock_irqrestore(&chan->vc.lock, flags);
-+ if (chan->is_paused && status == DMA_IN_PROGRESS)
-+ status = DMA_PAUSED;
-+
- dma_set_residue(txstate, bytes);
-+ spin_unlock_irqrestore(&chan->vc.lock, flags);
-
- return status;
- }
-@@ -523,7 +600,7 @@ static void dw_axi_dma_set_hw_channel(st
- unsigned long reg_value, val;
-
- if (!chip->apb_regs) {
-- dev_err(chip->dev, "apb_regs not initialized\n");
-+ dev_dbg(chip->dev, "apb_regs not initialized\n");
- return;
- }
-
-@@ -627,18 +704,25 @@ static int dw_axi_dma_set_hw_desc(struct
- switch (chan->direction) {
- case DMA_MEM_TO_DEV:
- reg_width = __ffs(chan->config.dst_addr_width);
-- device_addr = chan->config.dst_addr;
-+ device_addr = phys_to_dma(chan->chip->dev, chan->config.dst_addr);
- ctllo = reg_width << CH_CTL_L_DST_WIDTH_POS |
- mem_width << CH_CTL_L_SRC_WIDTH_POS |
-+ DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_DST_MSIZE_POS |
-+ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS |
- DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS |
- DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS;
- block_ts = len >> mem_width;
- break;
- case DMA_DEV_TO_MEM:
- reg_width = __ffs(chan->config.src_addr_width);
-- device_addr = chan->config.src_addr;
-+ /* Prevent partial access units getting lost */
-+ if (mem_width > reg_width)
-+ mem_width = reg_width;
-+ device_addr = phys_to_dma(chan->chip->dev, chan->config.src_addr);
- ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS |
- mem_width << CH_CTL_L_DST_WIDTH_POS |
-+ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
-+ DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_SRC_MSIZE_POS |
- DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS |
- DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS;
- block_ts = len >> reg_width;
-@@ -674,9 +758,6 @@ static int dw_axi_dma_set_hw_desc(struct
- }
-
- hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
--
-- ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
-- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
- hw_desc->lli->ctl_lo = cpu_to_le32(ctllo);
-
- set_desc_src_master(hw_desc);
-@@ -771,6 +852,8 @@ dw_axi_dma_chan_prep_cyclic(struct dma_c
- src_addr += segment_len;
- }
-
-+ desc->hw_desc_count = total_segments;
-+
- llp = desc->hw_desc[0].llp;
-
- /* Managed transfer list */
-@@ -850,6 +933,8 @@ dw_axi_dma_chan_prep_slave_sg(struct dma
- } while (len >= segment_len);
- }
-
-+ desc->hw_desc_count = loop;
-+
- /* Set end-of-link to the last link descriptor of list */
- set_desc_last(&desc->hw_desc[num_sgs - 1]);
-
-@@ -957,6 +1042,8 @@ dma_chan_prep_dma_memcpy(struct dma_chan
- num++;
- }
-
-+ desc->hw_desc_count = num;
-+
- /* Set end-of-link to the last link descriptor of list */
- set_desc_last(&desc->hw_desc[num - 1]);
- /* Managed transfer list */
-@@ -1005,7 +1092,7 @@ static void axi_chan_dump_lli(struct axi
- static void axi_chan_list_dump_lli(struct axi_dma_chan *chan,
- struct axi_dma_desc *desc_head)
- {
-- int count = atomic_read(&chan->descs_allocated);
-+ u32 count = desc_head->hw_desc_count;
- int i;
-
- for (i = 0; i < count; i++)
-@@ -1048,11 +1135,11 @@ out:
-
- static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
- {
-- int count = atomic_read(&chan->descs_allocated);
- struct axi_dma_hw_desc *hw_desc;
- struct axi_dma_desc *desc;
- struct virt_dma_desc *vd;
- unsigned long flags;
-+ u32 count;
- u64 llp;
- int i;
-
-@@ -1074,6 +1161,7 @@ static void axi_chan_block_xfer_complete
- if (chan->cyclic) {
- desc = vd_to_axi_desc(vd);
- if (desc) {
-+ count = desc->hw_desc_count;
- llp = lo_hi_readq(chan->chan_regs + CH_LLP);
- for (i = 0; i < count; i++) {
- hw_desc = &desc->hw_desc[i];
-@@ -1323,6 +1411,10 @@ static int parse_device_properties(struc
-
- chip->dw->hdata->nr_masters = tmp;
-
-+ ret = device_property_read_u32(dev, "snps,dma-targets", &tmp);
-+ if (!ret && tmp > 16)
-+ chip->dw->hdata->use_cfg2 = true;
-+
- ret = device_property_read_u32(dev, "snps,data-width", &tmp);
- if (ret)
- return ret;
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-@@ -101,6 +101,7 @@ struct axi_dma_desc {
-
- struct virt_dma_desc vd;
- struct axi_dma_chan *chan;
-+ u32 hw_desc_count;
- u32 completed_blocks;
- u32 length;
- u32 period_len;
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -466,8 +466,6 @@ static void axi_chan_block_xfer_start(st
+@@ -389,8 +389,6 @@ static void axi_chan_block_xfer_start(st
return;
}
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -917,6 +917,9 @@ dw_axi_dma_chan_prep_slave_sg(struct dma
+@@ -834,6 +834,9 @@ dw_axi_dma_chan_prep_slave_sg(struct dma
mem = sg_dma_address(sg);
len = sg_dma_len(sg);
num_segments = DIV_ROUND_UP(sg_dma_len(sg), axi_block_len);
--- /dev/null
+From 5c0f94088e0694220a2f0d8ad6e8216b50a80f2e Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.com>
+Date: Thu, 13 Jun 2024 15:01:02 +0100
+Subject: [PATCH 1133/1145] drivers: mmc: sdhci-brcmstb: improve bcm2712 card
+ removal handling
+
+If the controller is being reset, then the CQE needs to be reset as well.
+
+For removable cards, CQHCI_SSC1 must specify a polling mode (CBC=0)
+otherwise it's possible that the controller stops emitting periodic
+CMD13s on card removal, without raising an error status interrupt.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
+---
+ drivers/mmc/host/sdhci-brcmstb.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+--- a/drivers/mmc/host/sdhci-brcmstb.c
++++ b/drivers/mmc/host/sdhci-brcmstb.c
+@@ -365,8 +365,21 @@ static void sdhci_brcmstb_cqe_enable(str
+
+ sdhci_cqe_enable(mmc);
+
+- /* Reset CMD13 polling timer back to eMMC specification default */
+- cqhci_writel(cq_host, 0x00011000, CQHCI_SSC1);
++ /*
++ * The controller resets this register to a very short default interval
++ * whenever CQHCI is disabled.
++ *
++ * For removable cards CBC needs to be clear or card removal can hang
++ * the CQE. In polling mode, a CIT of 0x4000 "cycles" seems to produce the best
++ * throughput.
++ *
++ * For nonremovable cards, the specification default of CBC=1 CIT=0x1000
++ * suffices.
++ */
++ if (mmc->caps & MMC_CAP_NONREMOVABLE)
++ cqhci_writel(cq_host, 0x00011000, CQHCI_SSC1);
++ else
++ cqhci_writel(cq_host, 0x00004000, CQHCI_SSC1);
+ }
+
+ static const struct cqhci_host_ops sdhci_brcmstb_cqhci_ops = {
+@@ -386,7 +399,7 @@ static struct sdhci_ops sdhci_brcmstb_op
+ .set_clock = sdhci_bcm2712_set_clock,
+ .set_power = sdhci_brcmstb_set_power,
+ .set_bus_width = sdhci_set_bus_width,
+- .reset = sdhci_reset,
++ .reset = brcmstb_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+ .init_sd_express = bcm2712_init_sd_express,
+ };
--- /dev/null
+From a1d3defcca200077e1e382fe049ca613d16efd2b Mon Sep 17 00:00:00 2001
+From: Cavon Lee <cavonxx@gmail.com>
+Date: Tue, 18 Jun 2024 14:01:23 +0800
+Subject: [PATCH 1136/1145] feat: Add support for SunFounder PiPower 3 overlay
+ fix: Fix wrong Pironman 5 ir default pin number fix: Change space indentation
+ to tab
+
+Signed-off-by: Cavon Lee <cavonxx@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile | 1 +
+ arch/arm/boot/dts/overlays/README | 8 +-
+ .../overlays/sunfounder-pipower3-overlay.dts | 44 ++++++++++
+ .../overlays/sunfounder-pironman5-overlay.dts | 88 ++++++++++---------
+ 4 files changed, 98 insertions(+), 43 deletions(-)
+ create mode 100644 arch/arm/boot/dts/overlays/sunfounder-pipower3-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -275,6 +275,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+ ssd1306-spi.dtbo \
+ ssd1331-spi.dtbo \
+ ssd1351-spi.dtbo \
++ sunfounder-pipower3.dtbo \
+ sunfounder-pironman5.dtbo \
+ superaudioboard.dtbo \
+ sx150x.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -4695,11 +4695,17 @@ Params: speed SPI bus
+ reset_pin GPIO pin for RESET (default 25)
+
+
++Name: sunfounder-pipower3
++Info: Overlay for SunFounder PiPower 3
++Load: dtoverlay=sunfounder-pipower3,<param>=<val>
++Params: poweroff_pin Change poweroff pin (default 26)
++
++
+ Name: sunfounder-pironman5
+ Info: Overlay for SunFounder Pironman 5
+ Load: dtoverlay=sunfounder-pironman5,<param>=<val>
+ Params: ir Enable IR or not (on or off, default on)
+- ir_pins Change IR receiver pin (default 12)
++ ir_pins Change IR receiver pin (default 13)
+
+
+ Name: superaudioboard
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/sunfounder-pipower3-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "brcm,bcm2835";
++
++ fragment@0 {
++ target-path = "/chosen";
++ __overlay__ {
++ power: power {
++ hat_current_supply = <5000>;
++ };
++ };
++ };
++ fragment@1 {
++ target = <&i2c1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++ fragment@2 {
++ target-path = "/";
++ __overlay__ {
++ power_ctrl: power_ctrl {
++ compatible = "gpio-poweroff";
++ gpios = <&gpio 26 0>;
++ force;
++ };
++ };
++ };
++ fragment@3 {
++ target = <&gpio>;
++ __overlay__ {
++ power_ctrl_pins: power_ctrl_pins {
++ brcm,pins = <26>;
++ brcm,function = <1>; // out
++ };
++ };
++ };
++ __overrides__ {
++ poweroff_pin = <&power_ctrl>,"gpios:4",
++ <&power_ctrl_pins>,"brcm,pins:0";
++ };
++};
+--- a/arch/arm/boot/dts/overlays/sunfounder-pironman5-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sunfounder-pironman5-overlay.dts
+@@ -2,50 +2,54 @@
+ /plugin/;
+
+ / {
+- compatible = "brcm,bcm2835";
++ compatible = "brcm,bcm2835";
+
+- fragment@0 {
+- target = <&i2c1>;
+- __overlay__ {
+- status = "okay";
+- };
+- };
+- fragment@1 {
+- target = <&spi0>;
+- __overlay__ {
+- status = "okay";
+- };
+- };
+- fragment@2 {
+- target-path = "/";
+- __overlay__ {
+- gpio_ir: ir-receiver@c {
+- compatible = "gpio-ir-receiver";
+- pinctrl-names = "default";
+- pinctrl-0 = <&gpio_ir_pins>;
++ fragment@0 {
++ target = <&i2c1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++ fragment@1 {
++ target = <&spi0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++ fragment@2 {
++ target-path = "/";
++ __overlay__ {
++ gpio_ir: ir-receiver@d {
++ compatible = "gpio-ir-receiver";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpio_ir_pins>;
+
+- // pin number, high or low
+- gpios = <&gpio 12 1>;
++ // pin number, high or low
++ gpios = <&gpio 13 1>;
+
+- // parameter for keymap name
+- linux,rc-map-name = "rc-rc6-mce";
++ // parameter for keymap name
++ linux,rc-map-name = "rc-rc6-mce";
+
+- status = "okay";
+- };
+- };
+- };
+- fragment@3 {
+- target = <&gpio>;
+- __overlay__ {
+- gpio_ir_pins: gpio_ir_pins@c {
+- brcm,pins = <12>;
+- brcm,function = <0>;
+- brcm,pull = <2>;
+- };
+- };
+- };
+- __overrides__ {
+- ir = <&gpio_ir>,"status";
+- ir_pins = <&gpio_ir>,"gpios:4", <&gpio_ir>,"reg:0", <&gpio_ir_pins>,"brcm,pins:0", <&gpio_ir_pins>,"reg:0";
+- };
++ status = "okay";
++ };
++ };
++ };
++ fragment@3 {
++ target = <&gpio>;
++ __overlay__ {
++ gpio_ir_pins: gpio_ir_pins@d {
++ brcm,pins = <13>;
++ brcm,function = <0>;
++ brcm,pull = <2>;
++ };
++ };
++ };
++ __overrides__ {
++ ir = <&gpio_ir>,"status";
++ ir_pins =
++ <&gpio_ir>,"gpios:4",
++ <&gpio_ir>,"reg:0",
++ <&gpio_ir_pins>,"brcm,pins:0",
++ <&gpio_ir_pins>,"reg:0";
++ };
+ };
--- /dev/null
+From cd92a9591833ea06d1f12391f6b027fcecf436a9 Mon Sep 17 00:00:00 2001
+From: Ratchanan Srirattanamet <peathot@hotmail.com>
+Date: Tue, 18 Jun 2024 15:44:13 +0700
+Subject: [PATCH 1137/1145] pwm: gpio-pwm: follow pwm_apply_might_sleep()
+ rename
+
+Fixes: 03286093be68("drivers/gpio: Add a driver that wraps the PWM API as a GPIO controller")
+Signed-off-by: Ratchanan Srirattanamet <peathot@hotmail.com>
+---
+ drivers/gpio/gpio-pwm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpio/gpio-pwm.c
++++ b/drivers/gpio/gpio-pwm.c
+@@ -34,7 +34,7 @@ static void pwm_gpio_set(struct gpio_chi
+
+ pwm_get_state(pwm_gpio->pwm[off], &state);
+ state.duty_cycle = val ? state.period : 0;
+- pwm_apply_state(pwm_gpio->pwm[off], &state);
++ pwm_apply_might_sleep(pwm_gpio->pwm[off], &state);
+ }
+
+ static int pwm_gpio_parse_dt(struct pwm_gpio *pwm_gpio,
+@@ -79,7 +79,7 @@ static int pwm_gpio_parse_dt(struct pwm_
+ pwm_init_state(pwm_gpio->pwm[i], &state);
+
+ state.duty_cycle = 0;
+- pwm_apply_state(pwm_gpio->pwm[i], &state);
++ pwm_apply_might_sleep(pwm_gpio->pwm[i], &state);
+ }
+
+ pwm_gpio->gc.ngpio = num_gpios;
--- /dev/null
+From da87f91ad8450ccc5274cd7b6ba8d823b396c96f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 18 Jun 2024 15:33:30 +0100
+Subject: [PATCH 1138/1145] drm/bridge: panel: Ensure backlight is reachable
+
+Ensure that the various options of modules vs builtin results
+in being able to call into the backlight code.
+
+https://github.com/raspberrypi/linux/issues/6198
+
+Fixes: 573f8fd0abf1 ("drm/bridge: panel: Name an associated backlight device")
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/bridge/panel.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/bridge/panel.c
++++ b/drivers/gpu/drm/bridge/panel.c
+@@ -87,8 +87,10 @@ static int panel_bridge_attach(struct dr
+ drm_connector_attach_encoder(&panel_bridge->connector,
+ bridge->encoder);
+
++#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE)
+ backlight_set_display_name(panel_bridge->panel->backlight,
+ panel_bridge->connector.name);
++#endif
+
+ if (bridge->dev->registered) {
+ if (connector->funcs->reset)
--- /dev/null
+From 7af85d54e39733bb9a236b95ea5ed1ab8277d560 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Tue, 11 Jun 2024 16:12:47 +0100
+Subject: [PATCH 1141/1145] fs/ntfs3: Fix memory corruption when page_size
+ changes
+
+The rework in fs/ntfs3: Reduce stack usage
+changes log->page_size but doesn't change the associated
+log->page_mask and log->page_bits.
+
+That results in the bytes value in read_log_page
+getting a negative value, which is bad when it is
+passed to memcpy.
+
+The kernel panic can be observed when connecting an
+ntfs formatted drive that has previously been connected
+to a Windows machine to a Raspberry Pi 5, which by defauilt
+uses a 16K kernel pagesize.
+
+Fixes: 865e7a7700d9 ("fs/ntfs3: Reduce stack usage")
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ fs/ntfs3/fslog.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/ntfs3/fslog.c
++++ b/fs/ntfs3/fslog.c
+@@ -3907,6 +3907,8 @@ check_restart_area:
+ log->l_size = log->orig_file_size;
+ log->page_size = norm_file_page(t32, &log->l_size,
+ t32 == DefaultLogPageSize);
++ log->page_mask = log->page_size - 1;
++ log->page_bits = blksize_bits(log->page_size);
+ }
+
+ if (log->page_size != t32 ||
--- /dev/null
+From d2813c02131b9ddf938277f4123da7ccbd113ea7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 24 Jun 2024 22:35:42 +0100
+Subject: [PATCH 1142/1145] fixup! drivers: mmc: sdhci-brcmstb: bcm2712
+ supports HS400es and clock gating
+
+Declaring auto-clockgate support for a host that can interface with
+SDIO cards is a bug.
+
+See: https://github.com/raspberrypi/linux/issues/6237
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/mmc/host/sdhci-brcmstb.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/mmc/host/sdhci-brcmstb.c
++++ b/drivers/mmc/host/sdhci-brcmstb.c
+@@ -429,7 +429,6 @@ static const struct brcmstb_match_priv m
+ };
+
+ static const struct brcmstb_match_priv match_priv_2712 = {
+- .flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE,
+ .hs400es = sdhci_brcmstb_hs400es,
+ .cfginit = sdhci_brcmstb_cfginit_2712,
+ .ops = &sdhci_brcmstb_ops_2712,
--- /dev/null
+From 3b42260d2130b5ca110c5340ab2bd055eede5968 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 28 Apr 2021 17:46:01 +0100
+Subject: [PATCH 1144/1145] dmaengine: dw-axi-dmac: Fixes for RP1
+
+Don't assume that DMA addresses of devices are the same as their
+physical addresses - convert correctly.
+
+The CFG2 register layout is used when there are more than 8 channels,
+but also when configured for more than 16 target peripheral devices
+because the index of the handshake signal has to be made wider.
+
+Reset the DMAC on probe
+
+The driver goes to the trouble of tracking when transfers have been
+paused, but then doesn't report that state when queried.
+
+Not having APB registers is not an error - for most use cases it's
+not even of interest, it's expected. Demote the message to debug level,
+which is disabled by default.
+
+Each channel has a descriptor pool, which is shared between transfers.
+It is unsafe to treat the total number of descriptors allocated from a
+pool as the number allocated to a specific transfer; doing so leads
+to releasing buffers that shouldn't be released and walking off the
+ends of descriptor lists. Instead, give each transfer descriptor its
+own count.
+
+Support partial transfers:
+Some use cases involve streaming from a device where the transfer only
+proceeds when the device's FIFO occupancy exceeds a certain threshold.
+In such cases (e.g. when pulling data from a UART) it is important to
+know how much data has been transferred so far, in order that remaining
+bytes can be read from the FIFO directly by software.
+
+Add the necessary code to provide this "residue" value with a finer,
+sub-transfer granularity.
+
+In order to prevent the occasional byte getting stuck in the DMA
+controller's internal buffers, restrict the destination memory width
+to the source register width.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ .../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 136 +++++++++++++++---
+ drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 1 +
+ 2 files changed, 116 insertions(+), 21 deletions(-)
+
+--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+@@ -12,6 +12,7 @@
+ #include <linux/device.h>
+ #include <linux/dmaengine.h>
+ #include <linux/dmapool.h>
++#include <linux/dma-direct.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/err.h>
+ #include <linux/interrupt.h>
+@@ -84,6 +85,17 @@ axi_chan_iowrite64(struct axi_dma_chan *
+ iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4);
+ }
+
++static inline u64
++axi_chan_ioread64(struct axi_dma_chan *chan, u32 reg)
++{
++ /*
++ * We split one 64 bit read into two 32 bit reads as some HW doesn't
++ * support 64 bit access.
++ */
++ return ((u64)ioread32(chan->chan_regs + reg + 4) << 32) +
++ ioread32(chan->chan_regs + reg);
++}
++
+ static inline void axi_chan_config_write(struct axi_dma_chan *chan,
+ struct axi_dma_chan_config *config)
+ {
+@@ -220,7 +232,18 @@ static void axi_dma_hw_init(struct axi_d
+ {
+ int ret;
+ u32 i;
++ int retries = 1000;
+
++ axi_dma_iowrite32(chip, DMAC_RESET, 1);
++ while (axi_dma_ioread32(chip, DMAC_RESET)) {
++ retries--;
++ if (!retries) {
++ dev_err(chip->dev, "%s: DMAC failed to reset\n",
++ __func__);
++ return;
++ }
++ cpu_relax();
++ }
+ for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
+ axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
+ axi_chan_disable(&chip->dw->chan[i]);
+@@ -256,7 +279,6 @@ static struct axi_dma_desc *axi_desc_all
+ kfree(desc);
+ return NULL;
+ }
+- desc->nr_hw_descs = num;
+
+ return desc;
+ }
+@@ -283,7 +305,7 @@ static struct axi_dma_lli *axi_desc_get(
+ static void axi_desc_put(struct axi_dma_desc *desc)
+ {
+ struct axi_dma_chan *chan = desc->chan;
+- int count = desc->nr_hw_descs;
++ u32 count = desc->hw_desc_count;
+ struct axi_dma_hw_desc *hw_desc;
+ int descs_put;
+
+@@ -305,6 +327,48 @@ static void vchan_desc_put(struct virt_d
+ axi_desc_put(vd_to_axi_desc(vdesc));
+ }
+
++static u32 axi_dma_desc_src_pos(struct axi_dma_desc *desc, dma_addr_t addr)
++{
++ unsigned int idx = 0;
++ u32 pos = 0;
++
++ while (pos < desc->length) {
++ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++];
++ u32 len = hw_desc->len;
++ dma_addr_t start = le64_to_cpu(hw_desc->lli->sar);
++
++ if (addr >= start && addr <= (start + len)) {
++ pos += addr - start;
++ break;
++ }
++
++ pos += len;
++ }
++
++ return pos;
++}
++
++static u32 axi_dma_desc_dst_pos(struct axi_dma_desc *desc, dma_addr_t addr)
++{
++ unsigned int idx = 0;
++ u32 pos = 0;
++
++ while (pos < desc->length) {
++ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++];
++ u32 len = hw_desc->len;
++ dma_addr_t start = le64_to_cpu(hw_desc->lli->dar);
++
++ if (addr >= start && addr <= (start + len)) {
++ pos += addr - start;
++ break;
++ }
++
++ pos += len;
++ }
++
++ return pos;
++}
++
+ static enum dma_status
+ dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+@@ -314,10 +378,7 @@ dma_chan_tx_status(struct dma_chan *dcha
+ enum dma_status status;
+ u32 completed_length;
+ unsigned long flags;
+- u32 completed_blocks;
+ size_t bytes = 0;
+- u32 length;
+- u32 len;
+
+ status = dma_cookie_status(dchan, cookie, txstate);
+ if (status == DMA_COMPLETE || !txstate)
+@@ -326,16 +387,31 @@ dma_chan_tx_status(struct dma_chan *dcha
+ spin_lock_irqsave(&chan->vc.lock, flags);
+
+ vdesc = vchan_find_desc(&chan->vc, cookie);
+- if (vdesc) {
+- length = vd_to_axi_desc(vdesc)->length;
+- completed_blocks = vd_to_axi_desc(vdesc)->completed_blocks;
+- len = vd_to_axi_desc(vdesc)->hw_desc[0].len;
+- completed_length = completed_blocks * len;
+- bytes = length - completed_length;
++ if (vdesc && vdesc == vchan_next_desc(&chan->vc)) {
++ /* This descriptor is in-progress */
++ struct axi_dma_desc *desc = vd_to_axi_desc(vdesc);
++ dma_addr_t addr;
++
++ if (chan->direction == DMA_MEM_TO_DEV) {
++ addr = axi_chan_ioread64(chan, CH_SAR);
++ completed_length = axi_dma_desc_src_pos(desc, addr);
++ } else if (chan->direction == DMA_DEV_TO_MEM) {
++ addr = axi_chan_ioread64(chan, CH_DAR);
++ completed_length = axi_dma_desc_dst_pos(desc, addr);
++ } else {
++ completed_length = 0;
++ }
++ bytes = desc->length - completed_length;
++ } else if (vdesc) {
++ /* Still in the queue so not started */
++ bytes = vd_to_axi_desc(vdesc)->length;
+ }
+
+- spin_unlock_irqrestore(&chan->vc.lock, flags);
++ if (chan->is_paused && status == DMA_IN_PROGRESS)
++ status = DMA_PAUSED;
++
+ dma_set_residue(txstate, bytes);
++ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ return status;
+ }
+@@ -521,7 +597,7 @@ static void dw_axi_dma_set_hw_channel(st
+ unsigned long reg_value, val;
+
+ if (!chip->apb_regs) {
+- dev_err(chip->dev, "apb_regs not initialized\n");
++ dev_dbg(chip->dev, "apb_regs not initialized\n");
+ return;
+ }
+
+@@ -625,18 +701,25 @@ static int dw_axi_dma_set_hw_desc(struct
+ switch (chan->direction) {
+ case DMA_MEM_TO_DEV:
+ reg_width = __ffs(chan->config.dst_addr_width);
+- device_addr = chan->config.dst_addr;
++ device_addr = phys_to_dma(chan->chip->dev, chan->config.dst_addr);
+ ctllo = reg_width << CH_CTL_L_DST_WIDTH_POS |
+ mem_width << CH_CTL_L_SRC_WIDTH_POS |
++ DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_DST_MSIZE_POS |
++ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS |
+ DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS |
+ DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS;
+ block_ts = len >> mem_width;
+ break;
+ case DMA_DEV_TO_MEM:
+ reg_width = __ffs(chan->config.src_addr_width);
+- device_addr = chan->config.src_addr;
++ /* Prevent partial access units getting lost */
++ if (mem_width > reg_width)
++ mem_width = reg_width;
++ device_addr = phys_to_dma(chan->chip->dev, chan->config.src_addr);
+ ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS |
+ mem_width << CH_CTL_L_DST_WIDTH_POS |
++ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
++ DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_SRC_MSIZE_POS |
+ DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS |
+ DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS;
+ block_ts = len >> reg_width;
+@@ -672,9 +755,6 @@ static int dw_axi_dma_set_hw_desc(struct
+ }
+
+ hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
+-
+- ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
+- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
+ hw_desc->lli->ctl_lo = cpu_to_le32(ctllo);
+
+ set_desc_src_master(hw_desc);
+@@ -769,6 +849,8 @@ dw_axi_dma_chan_prep_cyclic(struct dma_c
+ src_addr += segment_len;
+ }
+
++ desc->hw_desc_count = total_segments;
++
+ llp = desc->hw_desc[0].llp;
+
+ /* Managed transfer list */
+@@ -851,6 +933,8 @@ dw_axi_dma_chan_prep_slave_sg(struct dma
+ } while (len >= segment_len);
+ }
+
++ desc->hw_desc_count = loop;
++
+ /* Set end-of-link to the last link descriptor of list */
+ set_desc_last(&desc->hw_desc[num_sgs - 1]);
+
+@@ -958,6 +1042,8 @@ dma_chan_prep_dma_memcpy(struct dma_chan
+ num++;
+ }
+
++ desc->hw_desc_count = num;
++
+ /* Set end-of-link to the last link descriptor of list */
+ set_desc_last(&desc->hw_desc[num - 1]);
+ /* Managed transfer list */
+@@ -1006,7 +1092,7 @@ static void axi_chan_dump_lli(struct axi
+ static void axi_chan_list_dump_lli(struct axi_dma_chan *chan,
+ struct axi_dma_desc *desc_head)
+ {
+- int count = atomic_read(&chan->descs_allocated);
++ u32 count = desc_head->hw_desc_count;
+ int i;
+
+ for (i = 0; i < count; i++)
+@@ -1049,11 +1135,11 @@ out:
+
+ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
+ {
+- int count = atomic_read(&chan->descs_allocated);
+ struct axi_dma_hw_desc *hw_desc;
+ struct axi_dma_desc *desc;
+ struct virt_dma_desc *vd;
+ unsigned long flags;
++ u32 count;
+ u64 llp;
+ int i;
+
+@@ -1075,6 +1161,7 @@ static void axi_chan_block_xfer_complete
+ if (chan->cyclic) {
+ desc = vd_to_axi_desc(vd);
+ if (desc) {
++ count = desc->hw_desc_count;
+ llp = lo_hi_readq(chan->chan_regs + CH_LLP);
+ for (i = 0; i < count; i++) {
+ hw_desc = &desc->hw_desc[i];
+@@ -1095,6 +1182,9 @@ static void axi_chan_block_xfer_complete
+ /* Remove the completed descriptor from issued list before completing */
+ list_del(&vd->node);
+ vchan_cookie_complete(vd);
++
++ /* Submit queued descriptors after processing the completed ones */
++ axi_chan_start_first_queued(chan);
+ }
+
+ out:
+@@ -1324,6 +1414,10 @@ static int parse_device_properties(struc
+
+ chip->dw->hdata->nr_masters = tmp;
+
++ ret = device_property_read_u32(dev, "snps,dma-targets", &tmp);
++ if (!ret && tmp > 16)
++ chip->dw->hdata->use_cfg2 = true;
++
+ ret = device_property_read_u32(dev, "snps,data-width", &tmp);
+ if (ret)
+ return ret;
+--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+@@ -101,6 +101,7 @@ struct axi_dma_desc {
+
+ struct virt_dma_desc vd;
+ struct axi_dma_chan *chan;
++ u32 hw_desc_count;
+ u32 completed_blocks;
+ u32 length;
+ u32 period_len;
--- /dev/null
+From 769634f344626ed73bcda14c91b567067974d7b2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Sat, 29 Jun 2024 09:30:23 +0100
+Subject: [PATCH 1145/1145] fixup! dmaengine: dw-axi-dmac: Fixes for RP1
+
+nr_hw_descs is the upstream version of what count_hw_descs, so make
+(more) use of it instead.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 14 +++++++-------
+ drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 1 -
+ 2 files changed, 7 insertions(+), 8 deletions(-)
+
+--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+@@ -305,7 +305,7 @@ static struct axi_dma_lli *axi_desc_get(
+ static void axi_desc_put(struct axi_dma_desc *desc)
+ {
+ struct axi_dma_chan *chan = desc->chan;
+- u32 count = desc->hw_desc_count;
++ int count = desc->nr_hw_descs;
+ struct axi_dma_hw_desc *hw_desc;
+ int descs_put;
+
+@@ -849,7 +849,7 @@ dw_axi_dma_chan_prep_cyclic(struct dma_c
+ src_addr += segment_len;
+ }
+
+- desc->hw_desc_count = total_segments;
++ desc->nr_hw_descs = total_segments;
+
+ llp = desc->hw_desc[0].llp;
+
+@@ -933,7 +933,7 @@ dw_axi_dma_chan_prep_slave_sg(struct dma
+ } while (len >= segment_len);
+ }
+
+- desc->hw_desc_count = loop;
++ desc->nr_hw_descs = loop;
+
+ /* Set end-of-link to the last link descriptor of list */
+ set_desc_last(&desc->hw_desc[num_sgs - 1]);
+@@ -1042,7 +1042,7 @@ dma_chan_prep_dma_memcpy(struct dma_chan
+ num++;
+ }
+
+- desc->hw_desc_count = num;
++ desc->nr_hw_descs = num;
+
+ /* Set end-of-link to the last link descriptor of list */
+ set_desc_last(&desc->hw_desc[num - 1]);
+@@ -1092,7 +1092,7 @@ static void axi_chan_dump_lli(struct axi
+ static void axi_chan_list_dump_lli(struct axi_dma_chan *chan,
+ struct axi_dma_desc *desc_head)
+ {
+- u32 count = desc_head->hw_desc_count;
++ int count = desc_head->nr_hw_descs;
+ int i;
+
+ for (i = 0; i < count; i++)
+@@ -1139,7 +1139,7 @@ static void axi_chan_block_xfer_complete
+ struct axi_dma_desc *desc;
+ struct virt_dma_desc *vd;
+ unsigned long flags;
+- u32 count;
++ int count;
+ u64 llp;
+ int i;
+
+@@ -1161,7 +1161,7 @@ static void axi_chan_block_xfer_complete
+ if (chan->cyclic) {
+ desc = vd_to_axi_desc(vd);
+ if (desc) {
+- count = desc->hw_desc_count;
++ count = desc->nr_hw_descs;
+ llp = lo_hi_readq(chan->chan_regs + CH_LLP);
+ for (i = 0; i < count; i++) {
+ hw_desc = &desc->hw_desc[i];
+--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+@@ -101,7 +101,6 @@ struct axi_dma_desc {
+
+ struct virt_dma_desc vd;
+ struct axi_dma_chan *chan;
+- u32 hw_desc_count;
+ u32 completed_blocks;
+ u32 length;
+ u32 period_len;