aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/dt-bindings/clock/rp1.h60
-rw-r--r--include/dt-bindings/mfd/rp1.h235
-rw-r--r--include/linux/brcmphy.h1
-rw-r--r--include/linux/broadcom/bcm2835_smi.h391
-rw-r--r--include/linux/broadcom/vc_mem.h39
-rw-r--r--include/linux/gpio/generic.h1
-rw-r--r--include/linux/irqchip/irq-bcm2836.h50
-rw-r--r--include/linux/leds.h3
-rw-r--r--include/linux/microchipphy.h8
-rw-r--r--include/linux/mmc/card.h9
-rw-r--r--include/linux/mmc/host.h1
-rw-r--r--include/linux/mmc/sd.h12
-rw-r--r--include/linux/pio_instructions.h481
-rw-r--r--include/linux/pio_rp1.h1019
-rw-r--r--include/linux/platform_data/dma-bcm2708.h143
-rw-r--r--include/linux/rp1-firmware.h53
-rw-r--r--include/linux/rp1_platform.h20
-rw-r--r--include/linux/usb.h755
-rw-r--r--include/linux/usb/hcd.h7
-rw-r--r--include/linux/usb/otg-fsm.h2
-rw-r--r--include/soc/bcm2835/raspberrypi-firmware.h30
-rw-r--r--include/uapi/linux/fb.h12
-rw-r--r--include/uapi/linux/serial_core.h3
-rw-r--r--include/uapi/misc/rp1_pio_if.h227
24 files changed, 3150 insertions, 412 deletions
diff --git a/include/dt-bindings/clock/rp1.h b/include/dt-bindings/clock/rp1.h
new file mode 100644
index 000000000000..1ebb25f16923
--- /dev/null
+++ b/include/dt-bindings/clock/rp1.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2021 Raspberry Pi Ltd.
+ */
+
+#define RP1_PLL_SYS_CORE 0
+#define RP1_PLL_AUDIO_CORE 1
+#define RP1_PLL_VIDEO_CORE 2
+
+#define RP1_PLL_SYS 3
+#define RP1_PLL_AUDIO 4
+#define RP1_PLL_VIDEO 5
+
+#define RP1_PLL_SYS_PRI_PH 6
+#define RP1_PLL_SYS_SEC_PH 7
+#define RP1_PLL_AUDIO_PRI_PH 8
+
+#define RP1_PLL_SYS_SEC 9
+#define RP1_PLL_AUDIO_SEC 10
+#define RP1_PLL_VIDEO_SEC 11
+
+#define RP1_CLK_SYS 12
+#define RP1_CLK_SLOW_SYS 13
+#define RP1_CLK_DMA 14
+#define RP1_CLK_UART 15
+#define RP1_CLK_ETH 16
+#define RP1_CLK_PWM0 17
+#define RP1_CLK_PWM1 18
+#define RP1_CLK_AUDIO_IN 19
+#define RP1_CLK_AUDIO_OUT 20
+#define RP1_CLK_I2S 21
+#define RP1_CLK_MIPI0_CFG 22
+#define RP1_CLK_MIPI1_CFG 23
+#define RP1_CLK_PCIE_AUX 24
+#define RP1_CLK_USBH0_MICROFRAME 25
+#define RP1_CLK_USBH1_MICROFRAME 26
+#define RP1_CLK_USBH0_SUSPEND 27
+#define RP1_CLK_USBH1_SUSPEND 28
+#define RP1_CLK_ETH_TSU 29
+#define RP1_CLK_ADC 30
+#define RP1_CLK_SDIO_TIMER 31
+#define RP1_CLK_SDIO_ALT_SRC 32
+#define RP1_CLK_GP0 33
+#define RP1_CLK_GP1 34
+#define RP1_CLK_GP2 35
+#define RP1_CLK_GP3 36
+#define RP1_CLK_GP4 37
+#define RP1_CLK_GP5 38
+#define RP1_CLK_VEC 39
+#define RP1_CLK_DPI 40
+#define RP1_CLK_MIPI0_DPI 41
+#define RP1_CLK_MIPI1_DPI 42
+
+/* Extra PLL output channels - RP1B0 only */
+#define RP1_PLL_VIDEO_PRI_PH 43
+#define RP1_PLL_AUDIO_TERN 44
+
+/* MIPI clocks managed by the DSI driver */
+#define RP1_CLK_MIPI0_DSI_BYTECLOCK 45
+#define RP1_CLK_MIPI1_DSI_BYTECLOCK 46
diff --git a/include/dt-bindings/mfd/rp1.h b/include/dt-bindings/mfd/rp1.h
new file mode 100644
index 000000000000..80bbfd61b270
--- /dev/null
+++ b/include/dt-bindings/mfd/rp1.h
@@ -0,0 +1,235 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for the PY MFD.
+ */
+
+#ifndef _RP1_H
+#define _RP1_H
+
+/* Address map */
+#define RP1_SYSINFO_BASE 0x000000
+#define RP1_TBMAN_BASE 0x004000
+#define RP1_SYSCFG_BASE 0x008000
+#define RP1_OTP_BASE 0x00c000
+#define RP1_POWER_BASE 0x010000
+#define RP1_RESETS_BASE 0x014000
+#define RP1_CLOCKS_BANK_DEFAULT_BASE 0x018000
+#define RP1_CLOCKS_BANK_VIDEO_BASE 0x01c000
+#define RP1_PLL_SYS_BASE 0x020000
+#define RP1_PLL_AUDIO_BASE 0x024000
+#define RP1_PLL_VIDEO_BASE 0x028000
+#define RP1_UART0_BASE 0x030000
+#define RP1_UART1_BASE 0x034000
+#define RP1_UART2_BASE 0x038000
+#define RP1_UART3_BASE 0x03c000
+#define RP1_UART4_BASE 0x040000
+#define RP1_UART5_BASE 0x044000
+#define RP1_SPI8_BASE 0x04c000
+#define RP1_SPI0_BASE 0x050000
+#define RP1_SPI1_BASE 0x054000
+#define RP1_SPI2_BASE 0x058000
+#define RP1_SPI3_BASE 0x05c000
+#define RP1_SPI4_BASE 0x060000
+#define RP1_SPI5_BASE 0x064000
+#define RP1_SPI6_BASE 0x068000
+#define RP1_SPI7_BASE 0x06c000
+#define RP1_I2C0_BASE 0x070000
+#define RP1_I2C1_BASE 0x074000
+#define RP1_I2C2_BASE 0x078000
+#define RP1_I2C3_BASE 0x07c000
+#define RP1_I2C4_BASE 0x080000
+#define RP1_I2C5_BASE 0x084000
+#define RP1_I2C6_BASE 0x088000
+#define RP1_AUDIO_IN_BASE 0x090000
+#define RP1_AUDIO_OUT_BASE 0x094000
+#define RP1_PWM0_BASE 0x098000
+#define RP1_PWM1_BASE 0x09c000
+#define RP1_I2S0_BASE 0x0a0000
+#define RP1_I2S1_BASE 0x0a4000
+#define RP1_I2S2_BASE 0x0a8000
+#define RP1_TIMER_BASE 0x0ac000
+#define RP1_SDIO0_APBS_BASE 0x0b0000
+#define RP1_SDIO1_APBS_BASE 0x0b4000
+#define RP1_BUSFABRIC_MONITOR_BASE 0x0c0000
+#define RP1_BUSFABRIC_AXISHIM_BASE 0x0c4000
+#define RP1_ADC_BASE 0x0c8000
+#define RP1_IO_BANK0_BASE 0x0d0000
+#define RP1_IO_BANK1_BASE 0x0d4000
+#define RP1_IO_BANK2_BASE 0x0d8000
+#define RP1_SYS_RIO0_BASE 0x0e0000
+#define RP1_SYS_RIO1_BASE 0x0e4000
+#define RP1_SYS_RIO2_BASE 0x0e8000
+#define RP1_PADS_BANK0_BASE 0x0f0000
+#define RP1_PADS_BANK1_BASE 0x0f4000
+#define RP1_PADS_BANK2_BASE 0x0f8000
+#define RP1_PADS_ETH_BASE 0x0fc000
+#define RP1_ETH_IP_BASE 0x100000
+#define RP1_ETH_CFG_BASE 0x104000
+#define RP1_PCIE_APBS_BASE 0x108000
+#define RP1_MIPI0_CSIDMA_BASE 0x110000
+#define RP1_MIPI0_CSIHOST_BASE 0x114000
+#define RP1_MIPI0_DSIDMA_BASE 0x118000
+#define RP1_MIPI0_DSIHOST_BASE 0x11c000
+#define RP1_MIPI0_MIPICFG_BASE 0x120000
+#define RP1_MIPI0_ISP_BASE 0x124000
+#define RP1_MIPI1_CSIDMA_BASE 0x128000
+#define RP1_MIPI1_CSIHOST_BASE 0x12c000
+#define RP1_MIPI1_DSIDMA_BASE 0x130000
+#define RP1_MIPI1_DSIHOST_BASE 0x134000
+#define RP1_MIPI1_MIPICFG_BASE 0x138000
+#define RP1_MIPI1_ISP_BASE 0x13c000
+#define RP1_VIDEO_OUT_CFG_BASE 0x140000
+#define RP1_VIDEO_OUT_VEC_BASE 0x144000
+#define RP1_VIDEO_OUT_DPI_BASE 0x148000
+#define RP1_XOSC_BASE 0x150000
+#define RP1_WATCHDOG_BASE 0x154000
+#define RP1_DMA_TICK_BASE 0x158000
+#define RP1_SDIO_CLOCKS_BASE 0x15c000
+#define RP1_USBHOST0_APBS_BASE 0x160000
+#define RP1_USBHOST1_APBS_BASE 0x164000
+#define RP1_ROSC0_BASE 0x168000
+#define RP1_ROSC1_BASE 0x16c000
+#define RP1_VBUSCTRL_BASE 0x170000
+#define RP1_TICKS_BASE 0x174000
+#define RP1_PIO_APBS_BASE 0x178000
+#define RP1_SDIO0_AHBLS_BASE 0x180000
+#define RP1_SDIO1_AHBLS_BASE 0x184000
+#define RP1_DMA_BASE 0x188000
+#define RP1_RAM_BASE 0x1c0000
+#define RP1_RAM_SIZE 0x020000
+#define RP1_USBHOST0_AXIS_BASE 0x200000
+#define RP1_USBHOST1_AXIS_BASE 0x300000
+#define RP1_EXAC_BASE 0x400000
+
+/* Interrupts */
+
+#define RP1_INT_IO_BANK0 0
+#define RP1_INT_IO_BANK1 1
+#define RP1_INT_IO_BANK2 2
+#define RP1_INT_AUDIO_IN 3
+#define RP1_INT_AUDIO_OUT 4
+#define RP1_INT_PWM0 5
+#define RP1_INT_ETH 6
+#define RP1_INT_I2C0 7
+#define RP1_INT_I2C1 8
+#define RP1_INT_I2C2 9
+#define RP1_INT_I2C3 10
+#define RP1_INT_I2C4 11
+#define RP1_INT_I2C5 12
+#define RP1_INT_I2C6 13
+#define RP1_INT_I2S0 14
+#define RP1_INT_I2S1 15
+#define RP1_INT_I2S2 16
+#define RP1_INT_SDIO0 17
+#define RP1_INT_SDIO1 18
+#define RP1_INT_SPI0 19
+#define RP1_INT_SPI1 20
+#define RP1_INT_SPI2 21
+#define RP1_INT_SPI3 22
+#define RP1_INT_SPI4 23
+#define RP1_INT_SPI5 24
+#define RP1_INT_UART0 25
+#define RP1_INT_TIMER_0 26
+#define RP1_INT_TIMER_1 27
+#define RP1_INT_TIMER_2 28
+#define RP1_INT_TIMER_3 29
+#define RP1_INT_USBHOST0 30
+#define RP1_INT_USBHOST0_0 31
+#define RP1_INT_USBHOST0_1 32
+#define RP1_INT_USBHOST0_2 33
+#define RP1_INT_USBHOST0_3 34
+#define RP1_INT_USBHOST1 35
+#define RP1_INT_USBHOST1_0 36
+#define RP1_INT_USBHOST1_1 37
+#define RP1_INT_USBHOST1_2 38
+#define RP1_INT_USBHOST1_3 39
+#define RP1_INT_DMA 40
+#define RP1_INT_PWM1 41
+#define RP1_INT_UART1 42
+#define RP1_INT_UART2 43
+#define RP1_INT_UART3 44
+#define RP1_INT_UART4 45
+#define RP1_INT_UART5 46
+#define RP1_INT_MIPI0 47
+#define RP1_INT_MIPI1 48
+#define RP1_INT_VIDEO_OUT 49
+#define RP1_INT_PIO_0 50
+#define RP1_INT_PIO_1 51
+#define RP1_INT_ADC_FIFO 52
+#define RP1_INT_PCIE_OUT 53
+#define RP1_INT_SPI6 54
+#define RP1_INT_SPI7 55
+#define RP1_INT_SPI8 56
+#define RP1_INT_SYSCFG 58
+#define RP1_INT_CLOCKS_DEFAULT 59
+#define RP1_INT_VBUSCTRL 60
+#define RP1_INT_PROC_MISC 57
+#define RP1_INT_END 61
+
+/* DMA peripherals (for pacing) */
+#define RP1_DMA_I2C0_RX 0x0
+#define RP1_DMA_I2C0_TX 0x1
+#define RP1_DMA_I2C1_RX 0x2
+#define RP1_DMA_I2C1_TX 0x3
+#define RP1_DMA_I2C2_RX 0x4
+#define RP1_DMA_I2C2_TX 0x5
+#define RP1_DMA_I2C3_RX 0x6
+#define RP1_DMA_I2C3_TX 0x7
+#define RP1_DMA_I2C4_RX 0x8
+#define RP1_DMA_I2C4_TX 0x9
+#define RP1_DMA_I2C5_RX 0xa
+#define RP1_DMA_I2C5_TX 0xb
+#define RP1_DMA_SPI0_RX 0xc
+#define RP1_DMA_SPI0_TX 0xd
+#define RP1_DMA_SPI1_RX 0xe
+#define RP1_DMA_SPI1_TX 0xf
+#define RP1_DMA_SPI2_RX 0x10
+#define RP1_DMA_SPI2_TX 0x11
+#define RP1_DMA_SPI3_RX 0x12
+#define RP1_DMA_SPI3_TX 0x13
+#define RP1_DMA_SPI4_RX 0x14
+#define RP1_DMA_SPI4_TX 0x15
+#define RP1_DMA_SPI5_RX 0x16
+#define RP1_DMA_SPI5_TX 0x17
+#define RP1_DMA_PWM0 0x18
+#define RP1_DMA_UART0_RX 0x19
+#define RP1_DMA_UART0_TX 0x1a
+#define RP1_DMA_AUDIO_IN_CH0 0x1b
+#define RP1_DMA_AUDIO_IN_CH1 0x1c
+#define RP1_DMA_AUDIO_OUT 0x1d
+#define RP1_DMA_PWM1 0x1e
+#define RP1_DMA_I2S0_RX 0x1f
+#define RP1_DMA_I2S0_TX 0x20
+#define RP1_DMA_I2S1_RX 0x21
+#define RP1_DMA_I2S1_TX 0x22
+#define RP1_DMA_I2S2_RX 0x23
+#define RP1_DMA_I2S2_TX 0x24
+#define RP1_DMA_UART1_RX 0x25
+#define RP1_DMA_UART1_TX 0x26
+#define RP1_DMA_UART2_RX 0x27
+#define RP1_DMA_UART2_TX 0x28
+#define RP1_DMA_UART3_RX 0x29
+#define RP1_DMA_UART3_TX 0x2a
+#define RP1_DMA_UART4_RX 0x2b
+#define RP1_DMA_UART4_TX 0x2c
+#define RP1_DMA_UART5_RX 0x2d
+#define RP1_DMA_UART5_TX 0x2e
+#define RP1_DMA_ADC 0x2f
+#define RP1_DMA_DMA_TICK_TICK0 0x30
+#define RP1_DMA_DMA_TICK_TICK1 0x31
+#define RP1_DMA_SPI6_RX 0x32
+#define RP1_DMA_SPI6_TX 0x33
+#define RP1_DMA_SPI7_RX 0x34
+#define RP1_DMA_SPI7_TX 0x35
+#define RP1_DMA_SPI8_RX 0x36
+#define RP1_DMA_SPI8_TX 0x37
+#define RP1_DMA_PIO_CH0_TX 0x38
+#define RP1_DMA_PIO_CH0_RX 0x39
+#define RP1_DMA_PIO_CH1_TX 0x3a
+#define RP1_DMA_PIO_CH1_RX 0x3b
+#define RP1_DMA_PIO_CH2_TX 0x3c
+#define RP1_DMA_PIO_CH2_RX 0x3d
+#define RP1_DMA_PIO_CH3_TX 0x3e
+#define RP1_DMA_PIO_CH3_RX 0x3f
+
+#endif
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 115a964f3006..97e6a716740b 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -24,6 +24,7 @@
#define PHY_ID_BCM5411 0x00206070
#define PHY_ID_BCM5421 0x002060e0
#define PHY_ID_BCM54210E 0x600d84a0
+#define PHY_ID_BCM54213PE 0x600d84a2
#define PHY_ID_BCM5464 0x002060b0
#define PHY_ID_BCM5461 0x002060c0
#define PHY_ID_BCM54612E 0x03625e60
diff --git a/include/linux/broadcom/bcm2835_smi.h b/include/linux/broadcom/bcm2835_smi.h
new file mode 100644
index 000000000000..ee3a75edfc03
--- /dev/null
+++ b/include/linux/broadcom/bcm2835_smi.h
@@ -0,0 +1,391 @@
+/**
+ * Declarations and definitions for Broadcom's Secondary Memory Interface
+ *
+ * Written by Luke Wren <[email protected]>
+ * Copyright (c) 2015, Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the above-listed copyright holders may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2, as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BCM2835_SMI_H
+#define BCM2835_SMI_H
+
+#include <linux/ioctl.h>
+
+#ifndef __KERNEL__
+#include <stdint.h>
+#include <stdbool.h>
+#endif
+
+#define BCM2835_SMI_IOC_MAGIC 0x1
+#define BCM2835_SMI_INVALID_HANDLE (~0)
+
+/* IOCTLs 0x100...0x1ff are not device-specific - we can use them */
+#define BCM2835_SMI_IOC_GET_SETTINGS _IO(BCM2835_SMI_IOC_MAGIC, 0)
+#define BCM2835_SMI_IOC_WRITE_SETTINGS _IO(BCM2835_SMI_IOC_MAGIC, 1)
+#define BCM2835_SMI_IOC_ADDRESS _IO(BCM2835_SMI_IOC_MAGIC, 2)
+#define BCM2835_SMI_IOC_MAX 2
+
+#define SMI_WIDTH_8BIT 0
+#define SMI_WIDTH_16BIT 1
+#define SMI_WIDTH_9BIT 2
+#define SMI_WIDTH_18BIT 3
+
+/* max number of bytes where DMA will not be used */
+#define DMA_THRESHOLD_BYTES 128
+#define DMA_BOUNCE_BUFFER_SIZE (1024 * 1024 / 2)
+#define DMA_BOUNCE_BUFFER_COUNT 3
+
+
+struct smi_settings {
+ int data_width;
+ /* Whether or not to pack multiple SMI transfers into a
+ single 32 bit FIFO word */
+ bool pack_data;
+
+ /* Timing for reads (writes the same but for WE)
+ *
+ * OE ----------+ +--------------------
+ * | |
+ * +----------+
+ * SD -<==============================>-----------
+ * SA -<=========================================>-
+ * <-setup-> <-strobe -> <-hold -> <- pace ->
+ */
+
+ int read_setup_time;
+ int read_hold_time;
+ int read_pace_time;
+ int read_strobe_time;
+
+ int write_setup_time;
+ int write_hold_time;
+ int write_pace_time;
+ int write_strobe_time;
+
+ bool dma_enable; /* DREQs */
+ bool dma_passthrough_enable; /* External DREQs */
+ int dma_read_thresh;
+ int dma_write_thresh;
+ int dma_panic_read_thresh;
+ int dma_panic_write_thresh;
+};
+
+/****************************************************************************
+*
+* Declare exported SMI functions
+*
+***************************************************************************/
+
+#ifdef __KERNEL__
+
+#include <linux/dmaengine.h> /* for enum dma_transfer_direction */
+#include <linux/of.h>
+#include <linux/semaphore.h>
+
+struct bcm2835_smi_instance;
+
+struct bcm2835_smi_bounce_info {
+ struct semaphore callback_sem;
+ void *buffer[DMA_BOUNCE_BUFFER_COUNT];
+ dma_addr_t phys[DMA_BOUNCE_BUFFER_COUNT];
+ struct scatterlist sgl[DMA_BOUNCE_BUFFER_COUNT];
+};
+
+
+void bcm2835_smi_set_regs_from_settings(struct bcm2835_smi_instance *);
+
+struct smi_settings *bcm2835_smi_get_settings_from_regs(
+ struct bcm2835_smi_instance *inst);
+
+void bcm2835_smi_write_buf(
+ struct bcm2835_smi_instance *inst,
+ const void *buf,
+ size_t n_bytes);
+
+void bcm2835_smi_read_buf(
+ struct bcm2835_smi_instance *inst,
+ void *buf,
+ size_t n_bytes);
+
+void bcm2835_smi_set_address(struct bcm2835_smi_instance *inst,
+ unsigned int address);
+
+ssize_t bcm2835_smi_user_dma(
+ struct bcm2835_smi_instance *inst,
+ enum dma_transfer_direction dma_dir,
+ char __user *user_ptr,
+ size_t count,
+ struct bcm2835_smi_bounce_info **bounce);
+
+struct bcm2835_smi_instance *bcm2835_smi_get(struct device_node *node);
+
+#endif /* __KERNEL__ */
+
+/****************************************************************
+*
+* Implementation-only declarations
+*
+****************************************************************/
+
+#ifdef BCM2835_SMI_IMPLEMENTATION
+
+/* Clock manager registers for SMI clock: */
+#define CM_SMI_BASE_ADDRESS ((BCM2708_PERI_BASE) + 0x1010b0)
+/* Clock manager "password" to protect registers from spurious writes */
+#define CM_PWD (0x5a << 24)
+
+#define CM_SMI_CTL 0x00
+#define CM_SMI_DIV 0x04
+
+#define CM_SMI_CTL_FLIP (1 << 8)
+#define CM_SMI_CTL_BUSY (1 << 7)
+#define CM_SMI_CTL_KILL (1 << 5)
+#define CM_SMI_CTL_ENAB (1 << 4)
+#define CM_SMI_CTL_SRC_MASK (0xf)
+#define CM_SMI_CTL_SRC_OFFS (0)
+
+#define CM_SMI_DIV_DIVI_MASK (0xf << 12)
+#define CM_SMI_DIV_DIVI_OFFS (12)
+#define CM_SMI_DIV_DIVF_MASK (0xff << 4)
+#define CM_SMI_DIV_DIVF_OFFS (4)
+
+/* SMI register mapping:*/
+#define SMI_BASE_ADDRESS ((BCM2708_PERI_BASE) + 0x600000)
+
+#define SMICS 0x00 /* control + status register */
+#define SMIL 0x04 /* length/count (n external txfers) */
+#define SMIA 0x08 /* address register */
+#define SMID 0x0c /* data register */
+#define SMIDSR0 0x10 /* device 0 read settings */
+#define SMIDSW0 0x14 /* device 0 write settings */
+#define SMIDSR1 0x18 /* device 1 read settings */
+#define SMIDSW1 0x1c /* device 1 write settings */
+#define SMIDSR2 0x20 /* device 2 read settings */
+#define SMIDSW2 0x24 /* device 2 write settings */
+#define SMIDSR3 0x28 /* device 3 read settings */
+#define SMIDSW3 0x2c /* device 3 write settings */
+#define SMIDC 0x30 /* DMA control registers */
+#define SMIDCS 0x34 /* direct control/status register */
+#define SMIDA 0x38 /* direct address register */
+#define SMIDD 0x3c /* direct data registers */
+#define SMIFD 0x40 /* FIFO debug register */
+
+
+
+/* Control and Status register bits:
+ * SMICS_RXF : RX fifo full: 1 when RX fifo is full
+ * SMICS_TXE : TX fifo empty: 1 when empty.
+ * SMICS_RXD : RX fifo contains data: 1 when there is data.
+ * SMICS_TXD : TX fifo can accept data: 1 when true.
+ * SMICS_RXR : RX fifo needs reading: 1 when fifo more than 3/4 full, or
+ * when "DONE" and fifo not emptied.
+ * SMICS_TXW : TX fifo needs writing: 1 when less than 1/4 full.
+ * SMICS_AFERR : AXI FIFO error: 1 when fifo read when empty or written
+ * when full. Write 1 to clear.
+ * SMICS_EDREQ : 1 when external DREQ received.
+ * SMICS_PXLDAT : Pixel data: write 1 to enable pixel transfer modes.
+ * SMICS_SETERR : 1 if there was an error writing to setup regs (e.g.
+ * tx was in progress). Write 1 to clear.
+ * SMICS_PVMODE : Set to 1 to enable pixel valve mode.
+ * SMICS_INTR : Set to 1 to enable interrupt on RX.
+ * SMICS_INTT : Set to 1 to enable interrupt on TX.
+ * SMICS_INTD : Set to 1 to enable interrupt on DONE condition.
+ * SMICS_TEEN : Tear effect mode enabled: Programmed transfers will wait
+ * for a TE trigger before writing.
+ * SMICS_PAD1 : Padding settings for external transfers. For writes: the
+ * number of bytes initially written to the TX fifo that
+ * SMICS_PAD0 : should be ignored. For reads: the number of bytes that will
+ * be read before the data, and should be dropped.
+ * SMICS_WRITE : Transfer direction: 1 = write to external device, 0 = read
+ * SMICS_CLEAR : Write 1 to clear the FIFOs.
+ * SMICS_START : Write 1 to start the programmed transfer.
+ * SMICS_ACTIVE : Reads as 1 when a programmed transfer is underway.
+ * SMICS_DONE : Reads as 1 when transfer finished. For RX, not set until
+ * FIFO emptied.
+ * SMICS_ENABLE : Set to 1 to enable the SMI peripheral, 0 to disable.
+ */
+
+#define SMICS_RXF (1 << 31)
+#define SMICS_TXE (1 << 30)
+#define SMICS_RXD (1 << 29)
+#define SMICS_TXD (1 << 28)
+#define SMICS_RXR (1 << 27)
+#define SMICS_TXW (1 << 26)
+#define SMICS_AFERR (1 << 25)
+#define SMICS_EDREQ (1 << 15)
+#define SMICS_PXLDAT (1 << 14)
+#define SMICS_SETERR (1 << 13)
+#define SMICS_PVMODE (1 << 12)
+#define SMICS_INTR (1 << 11)
+#define SMICS_INTT (1 << 10)
+#define SMICS_INTD (1 << 9)
+#define SMICS_TEEN (1 << 8)
+#define SMICS_PAD1 (1 << 7)
+#define SMICS_PAD0 (1 << 6)
+#define SMICS_WRITE (1 << 5)
+#define SMICS_CLEAR (1 << 4)
+#define SMICS_START (1 << 3)
+#define SMICS_ACTIVE (1 << 2)
+#define SMICS_DONE (1 << 1)
+#define SMICS_ENABLE (1 << 0)
+
+/* Address register bits: */
+
+#define SMIA_DEVICE_MASK ((1 << 9) | (1 << 8))
+#define SMIA_DEVICE_OFFS (8)
+#define SMIA_ADDR_MASK (0x3f) /* bits 5 -> 0 */
+#define SMIA_ADDR_OFFS (0)
+
+/* DMA control register bits:
+ * SMIDC_DMAEN : DMA enable: set 1: DMA requests will be issued.
+ * SMIDC_DMAP : DMA passthrough: when set to 0, top two data pins are used by
+ * SMI as usual. When set to 1, the top two pins are used for
+ * external DREQs: pin 16 read request, 17 write.
+ * SMIDC_PANIC* : Threshold at which DMA will panic during read/write.
+ * SMIDC_REQ* : Threshold at which DMA will generate a DREQ.
+ */
+
+#define SMIDC_DMAEN (1 << 28)
+#define SMIDC_DMAP (1 << 24)
+#define SMIDC_PANICR_MASK (0x3f << 18)
+#define SMIDC_PANICR_OFFS (18)
+#define SMIDC_PANICW_MASK (0x3f << 12)
+#define SMIDC_PANICW_OFFS (12)
+#define SMIDC_REQR_MASK (0x3f << 6)
+#define SMIDC_REQR_OFFS (6)
+#define SMIDC_REQW_MASK (0x3f)
+#define SMIDC_REQW_OFFS (0)
+
+/* Device settings register bits: same for all 4 (or 3?) device register sets.
+ * Device read settings:
+ * SMIDSR_RWIDTH : Read transfer width. 00 = 8bit, 01 = 16bit,
+ * 10 = 18bit, 11 = 9bit.
+ * SMIDSR_RSETUP : Read setup time: number of core cycles between chip
+ * select/address and read strobe. Min 1, max 64.
+ * SMIDSR_MODE68 : 1 for System 68 mode (i.e. enable + direction pins,
+ * rather than OE + WE pin)
+ * SMIDSR_FSETUP : If set to 1, setup time only applies to first
+ * transfer after address change.
+ * SMIDSR_RHOLD : Number of core cycles between read strobe going
+ * inactive and CS/address going inactive. Min 1, max 64
+ * SMIDSR_RPACEALL : When set to 1, this device's RPACE value will always
+ * be used for the next transaction, even if it is not
+ * to this device.
+ * SMIDSR_RPACE : Number of core cycles spent waiting between CS
+ * deassert and start of next transfer. Min 1, max 128
+ * SMIDSR_RDREQ : 1 = use external DMA request on SD16 to pace reads
+ * from device. Must also set DMAP in SMICS.
+ * SMIDSR_RSTROBE : Number of cycles to assert the read strobe.
+ * min 1, max 128.
+ */
+#define SMIDSR_RWIDTH_MASK ((1<<31)|(1<<30))
+#define SMIDSR_RWIDTH_OFFS (30)
+#define SMIDSR_RSETUP_MASK (0x3f << 24)
+#define SMIDSR_RSETUP_OFFS (24)
+#define SMIDSR_MODE68 (1 << 23)
+#define SMIDSR_FSETUP (1 << 22)
+#define SMIDSR_RHOLD_MASK (0x3f << 16)
+#define SMIDSR_RHOLD_OFFS (16)
+#define SMIDSR_RPACEALL (1 << 15)
+#define SMIDSR_RPACE_MASK (0x7f << 8)
+#define SMIDSR_RPACE_OFFS (8)
+#define SMIDSR_RDREQ (1 << 7)
+#define SMIDSR_RSTROBE_MASK (0x7f)
+#define SMIDSR_RSTROBE_OFFS (0)
+
+/* Device write settings:
+ * SMIDSW_WWIDTH : Write transfer width. 00 = 8bit, 01 = 16bit,
+ * 10= 18bit, 11 = 9bit.
+ * SMIDSW_WSETUP : Number of cycles between CS assert and write strobe.
+ * Min 1, max 64.
+ * SMIDSW_WFORMAT : Pixel format of input. 0 = 16bit RGB 565,
+ * 1 = 32bit RGBA 8888
+ * SMIDSW_WSWAP : 1 = swap pixel data bits. (Use with SMICS_PXLDAT)
+ * SMIDSW_WHOLD : Time between WE deassert and CS deassert. 1 to 64
+ * SMIDSW_WPACEALL : 1: this device's WPACE will be used for the next
+ * transfer, regardless of that transfer's device.
+ * SMIDSW_WPACE : Cycles between CS deassert and next CS assert.
+ * Min 1, max 128
+ * SMIDSW_WDREQ : Use external DREQ on pin 17 to pace writes. DMAP must
+ * be set in SMICS.
+ * SMIDSW_WSTROBE : Number of cycles to assert the write strobe.
+ * Min 1, max 128
+ */
+#define SMIDSW_WWIDTH_MASK ((1<<31)|(1<<30))
+#define SMIDSW_WWIDTH_OFFS (30)
+#define SMIDSW_WSETUP_MASK (0x3f << 24)
+#define SMIDSW_WSETUP_OFFS (24)
+#define SMIDSW_WFORMAT (1 << 23)
+#define SMIDSW_WSWAP (1 << 22)
+#define SMIDSW_WHOLD_MASK (0x3f << 16)
+#define SMIDSW_WHOLD_OFFS (16)
+#define SMIDSW_WPACEALL (1 << 15)
+#define SMIDSW_WPACE_MASK (0x7f << 8)
+#define SMIDSW_WPACE_OFFS (8)
+#define SMIDSW_WDREQ (1 << 7)
+#define SMIDSW_WSTROBE_MASK (0x7f)
+#define SMIDSW_WSTROBE_OFFS (0)
+
+/* Direct transfer control + status register
+ * SMIDCS_WRITE : Direction of transfer: 1 -> write, 0 -> read
+ * SMIDCS_DONE : 1 when a transfer has finished. Write 1 to clear.
+ * SMIDCS_START : Write 1 to start a transfer, if one is not already underway.
+ * SMIDCE_ENABLE: Write 1 to enable SMI in direct mode.
+ */
+
+#define SMIDCS_WRITE (1 << 3)
+#define SMIDCS_DONE (1 << 2)
+#define SMIDCS_START (1 << 1)
+#define SMIDCS_ENABLE (1 << 0)
+
+/* Direct transfer address register
+ * SMIDA_DEVICE : Indicates which of the device settings banks should be used.
+ * SMIDA_ADDR : The value to be asserted on the address pins.
+ */
+
+#define SMIDA_DEVICE_MASK ((1<<9)|(1<<8))
+#define SMIDA_DEVICE_OFFS (8)
+#define SMIDA_ADDR_MASK (0x3f)
+#define SMIDA_ADDR_OFFS (0)
+
+/* FIFO debug register
+ * SMIFD_FLVL : The high-tide mark of FIFO count during the most recent txfer
+ * SMIFD_FCNT : The current FIFO count.
+ */
+#define SMIFD_FLVL_MASK (0x3f << 8)
+#define SMIFD_FLVL_OFFS (8)
+#define SMIFD_FCNT_MASK (0x3f)
+#define SMIFD_FCNT_OFFS (0)
+
+#endif /* BCM2835_SMI_IMPLEMENTATION */
+
+#endif /* BCM2835_SMI_H */
diff --git a/include/linux/broadcom/vc_mem.h b/include/linux/broadcom/vc_mem.h
new file mode 100644
index 000000000000..3c7079237496
--- /dev/null
+++ b/include/linux/broadcom/vc_mem.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2, available at
+ * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a
+ * license other than the GPL, without Broadcom's express prior written
+ * consent.
+ */
+
+#ifndef _VC_MEM_H
+#define _VC_MEM_H
+
+#include <linux/ioctl.h>
+
+#define VC_MEM_IOC_MAGIC 'v'
+
+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR(VC_MEM_IOC_MAGIC, 0, unsigned long)
+#define VC_MEM_IOC_MEM_SIZE _IOR(VC_MEM_IOC_MAGIC, 1, unsigned int)
+#define VC_MEM_IOC_MEM_BASE _IOR(VC_MEM_IOC_MAGIC, 2, unsigned int)
+#define VC_MEM_IOC_MEM_LOAD _IOR(VC_MEM_IOC_MAGIC, 3, unsigned int)
+
+#ifdef __KERNEL__
+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
+
+extern unsigned long mm_vc_mem_phys_addr;
+extern unsigned int mm_vc_mem_size;
+extern int vc_mem_get_current_size(void);
+#endif
+
+#ifdef CONFIG_COMPAT
+#define VC_MEM_IOC_MEM_PHYS_ADDR32 _IOR(VC_MEM_IOC_MAGIC, 0, compat_ulong_t)
+#endif
+
+#endif /* _VC_MEM_H */
diff --git a/include/linux/gpio/generic.h b/include/linux/gpio/generic.h
index ff566dc9c3cb..e3625f4cb933 100644
--- a/include/linux/gpio/generic.h
+++ b/include/linux/gpio/generic.h
@@ -18,6 +18,7 @@ struct device;
#define GPIO_GENERIC_NO_SET_ON_INPUT BIT(6)
#define GPIO_GENERIC_PINCTRL_BACKEND BIT(7) /* Call pinctrl direction setters */
#define GPIO_GENERIC_NO_INPUT BIT(8) /* only output */
+#define GPIO_GENERIC_REG_DIRECT BIT(15) /* ignore shadow registers */
/**
* struct gpio_generic_chip_config - Generic GPIO chip configuration data
diff --git a/include/linux/irqchip/irq-bcm2836.h b/include/linux/irqchip/irq-bcm2836.h
index ac5719d8f56b..0d105aee10fa 100644
--- a/include/linux/irqchip/irq-bcm2836.h
+++ b/include/linux/irqchip/irq-bcm2836.h
@@ -5,57 +5,59 @@
* Copyright 2015 Broadcom
*/
-#define LOCAL_CONTROL 0x000
-#define LOCAL_PRESCALER 0x008
+#define LOCAL_CONTROL 0x000
+#define LOCAL_PRESCALER 0x008
/*
* The low 2 bits identify the CPU that the GPU IRQ goes to, and the
* next 2 bits identify the CPU that the GPU FIQ goes to.
*/
-#define LOCAL_GPU_ROUTING 0x00c
+#define LOCAL_GPU_ROUTING 0x00c
/* When setting bits 0-3, enables PMU interrupts on that CPU. */
-#define LOCAL_PM_ROUTING_SET 0x010
+#define LOCAL_PM_ROUTING_SET 0x010
/* When setting bits 0-3, disables PMU interrupts on that CPU. */
-#define LOCAL_PM_ROUTING_CLR 0x014
+#define LOCAL_PM_ROUTING_CLR 0x014
/*
* The low 4 bits of this are the CPU's timer IRQ enables, and the
* next 4 bits are the CPU's timer FIQ enables (which override the IRQ
* bits).
*/
-#define LOCAL_TIMER_INT_CONTROL0 0x040
+#define LOCAL_TIMER_INT_CONTROL0 0x040
/*
* The low 4 bits of this are the CPU's per-mailbox IRQ enables, and
* the next 4 bits are the CPU's per-mailbox FIQ enables (which
* override the IRQ bits).
*/
-#define LOCAL_MAILBOX_INT_CONTROL0 0x050
+#define LOCAL_MAILBOX_INT_CONTROL0 0x050
/*
* The CPU's interrupt status register. Bits are defined by the
* LOCAL_IRQ_* bits below.
*/
-#define LOCAL_IRQ_PENDING0 0x060
+#define LOCAL_IRQ_PENDING0 0x060
/* Same status bits as above, but for FIQ. */
-#define LOCAL_FIQ_PENDING0 0x070
+#define LOCAL_FIQ_PENDING0 0x070
/*
* Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and
* these bits are organized by mailbox number and then CPU number. We
* use mailbox 0 for IPIs. The mailbox's interrupt is raised while
* any bit is set.
*/
-#define LOCAL_MAILBOX0_SET0 0x080
-#define LOCAL_MAILBOX3_SET0 0x08c
+#define LOCAL_MAILBOX0_SET0 0x080
+#define LOCAL_MAILBOX3_SET0 0x08c
/* Mailbox write-to-clear bits. */
-#define LOCAL_MAILBOX0_CLR0 0x0c0
-#define LOCAL_MAILBOX3_CLR0 0x0cc
+#define LOCAL_MAILBOX0_CLR0 0x0c0
+#define LOCAL_MAILBOX3_CLR0 0x0cc
-#define LOCAL_IRQ_CNTPSIRQ 0
-#define LOCAL_IRQ_CNTPNSIRQ 1
-#define LOCAL_IRQ_CNTHPIRQ 2
-#define LOCAL_IRQ_CNTVIRQ 3
-#define LOCAL_IRQ_MAILBOX0 4
-#define LOCAL_IRQ_MAILBOX1 5
-#define LOCAL_IRQ_MAILBOX2 6
-#define LOCAL_IRQ_MAILBOX3 7
-#define LOCAL_IRQ_GPU_FAST 8
-#define LOCAL_IRQ_PMU_FAST 9
-#define LAST_IRQ LOCAL_IRQ_PMU_FAST
+#define LOCAL_IRQ_CNTPSIRQ 0
+#define LOCAL_IRQ_CNTPNSIRQ 1
+#define LOCAL_IRQ_CNTHPIRQ 2
+#define LOCAL_IRQ_CNTVIRQ 3
+#define LOCAL_IRQ_MAILBOX0 4
+#define LOCAL_IRQ_MAILBOX1 5
+#define LOCAL_IRQ_MAILBOX2 6
+#define LOCAL_IRQ_MAILBOX3 7
+#define LOCAL_IRQ_GPU_FAST 8
+#define LOCAL_IRQ_PMU_FAST 9
+#define LAST_IRQ LOCAL_IRQ_PMU_FAST
+
+void bcm2836_arm_irqchip_spin_gpu_irq(void); \ No newline at end of file
diff --git a/include/linux/leds.h b/include/linux/leds.h
index b16b803cc1ac..4dff7add72ce 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -109,6 +109,9 @@ struct led_classdev {
#define LED_INIT_DEFAULT_TRIGGER BIT(23)
#define LED_REJECT_NAME_CONFLICT BIT(24)
#define LED_MULTI_COLOR BIT(25)
+ /* Additions for Raspberry Pi PWR LED */
+#define SET_GPIO_INPUT BIT(30)
+#define SET_GPIO_OUTPUT BIT(31)
/* set_brightness_work / blink_timer flags, atomic, private. */
unsigned long work_flags;
diff --git a/include/linux/microchipphy.h b/include/linux/microchipphy.h
index 517288da19fd..626c450d71f4 100644
--- a/include/linux/microchipphy.h
+++ b/include/linux/microchipphy.h
@@ -61,6 +61,14 @@
/* Registers specific to the LAN7800/LAN7850 embedded phy */
#define LAN78XX_PHY_LED_MODE_SELECT (0x1D)
+#define LAN78XX_PHY_CTRL3 (0x14)
+#define LAN78XX_PHY_CTRL3_AUTO_DOWNSHIFT (0x0010)
+#define LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_MASK (0x000c)
+#define LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_2 (0x0000)
+#define LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_3 (0x0004)
+#define LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_4 (0x0008)
+#define LAN78XX_PHY_CTRL3_DOWNSHIFT_CTRL_5 (0x000c)
+
/* DSP registers */
#define PHY_ARDENNES_MMD_DEV_3_PHY_CFG (0x806A)
#define PHY_ARDENNES_MMD_DEV_3_PHY_CFG_ZD_DLY_EN_ (0x2000)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index ddcdf23d731c..221fef5c9715 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -329,9 +329,11 @@ struct mmc_card {
#define MMC_QUIRK_BROKEN_SD_CACHE (1<<15) /* Disable broken SD cache support */
#define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */
#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */
-#define MMC_QUIRK_NO_UHS_DDR50_TUNING (1<<18) /* Disable DDR50 tuning */
+#define MMC_QUIRK_NO_UHS_DDR50_TUNING (1 << 18) /* Disable DDR50 tuning */
+#define MMC_QUIRK_WORKING_SD_CQ (1<<30) /* SD card has known-good CQ implementation */
+#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */
- bool written_flag; /* Indicates eMMC has been written since power on */
+ bool written_flag; /* Indicates eMMC has been written since power on */
bool reenable_cmdq; /* Re-enable Command Queue */
unsigned int erase_size; /* erase size in sectors */
@@ -354,6 +356,7 @@ struct mmc_card {
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
struct sd_ext_reg ext_power; /* SD extension reg for PM */
struct sd_ext_reg ext_perf; /* SD extension reg for PERF */
+ u8 *ext_reg_buf; /* 512 byte block for extension register R/W */
struct sd_uhs2_config uhs2_config; /* SD UHS-II config */
@@ -378,6 +381,8 @@ struct mmc_card {
unsigned int nr_parts;
struct workqueue_struct *complete_wq; /* Private workqueue */
+
+ unsigned int max_posted_writes; /* command queue posted write limit */
};
static inline bool mmc_large_sector(struct mmc_card *card)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index e0e2c265e5d1..37b33ea3b037 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -463,6 +463,7 @@ struct mmc_host {
#define MMC_CAP2_CRYPTO 0
#endif
#define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */
+#define MMC_CAP2_SD_CQE_PERMISSIVE (1 << 31) /* Ignore allow-list for CQ capable SD card detection */
bool uhs2_sd_tran; /* UHS-II flag for SD_TRAN state */
bool uhs2_app_cmd; /* UHS-II flag for APP command */
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
index af5fc70e09a2..c13b565c6f01 100644
--- a/include/linux/mmc/sd.h
+++ b/include/linux/mmc/sd.h
@@ -32,6 +32,9 @@
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SEND_SCR 51 /* adtc R1 */
+ /* class 1 */
+#define SD_CMDQ_TASK_MGMT 43 /* ac See below R1b */
+
/* class 11 */
#define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */
#define SD_WRITE_EXTR_SINGLE 49 /* adtc [31:0] R1 */
@@ -65,6 +68,15 @@
*/
/*
+ * SD_CMDQ_TASK_MGMT argument format:
+ *
+ * [31:21] Reserved (0)
+ * [20:16] Task ID
+ * [15:4] Reserved (0)
+ * [3:0] Operation - 0x1 = abort all tasks, 0x2 = abort Task ID
+ */
+
+/*
* SCR field definitions
*/
diff --git a/include/linux/pio_instructions.h b/include/linux/pio_instructions.h
new file mode 100644
index 000000000000..a72934b1ed60
--- /dev/null
+++ b/include/linux/pio_instructions.h
@@ -0,0 +1,481 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ */
+
+#ifndef _HARDWARE_PIO_INSTRUCTIONS_H
+#define _HARDWARE_PIO_INSTRUCTIONS_H
+
+/** \brief PIO instruction encoding
+ * \defgroup pio_instructions pio_instructions
+ * \ingroup hardware_pio
+ *
+ * Functions for generating PIO instruction encodings programmatically. In debug builds
+ *`PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS` can be set to 1 to enable validation of encoding function
+ * parameters.
+ *
+ * For fuller descriptions of the instructions in question see the "RP2040 Datasheet"
+ */
+
+// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS, Enable/disable assertions in the PIO instructions, type=bool, default=0, group=pio_instructions
+#ifndef PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS
+#define PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum pio_instr_bits {
+ pio_instr_bits_jmp = 0x0000,
+ pio_instr_bits_wait = 0x2000,
+ pio_instr_bits_in = 0x4000,
+ pio_instr_bits_out = 0x6000,
+ pio_instr_bits_push = 0x8000,
+ pio_instr_bits_pull = 0x8080,
+ pio_instr_bits_mov = 0xa000,
+ pio_instr_bits_irq = 0xc000,
+ pio_instr_bits_set = 0xe000,
+};
+
+#ifndef NDEBUG
+#define _PIO_INVALID_IN_SRC 0x08u
+#define _PIO_INVALID_OUT_DEST 0x10u
+#define _PIO_INVALID_SET_DEST 0x20u
+#define _PIO_INVALID_MOV_SRC 0x40u
+#define _PIO_INVALID_MOV_DEST 0x80u
+#else
+#define _PIO_INVALID_IN_SRC 0u
+#define _PIO_INVALID_OUT_DEST 0u
+#define _PIO_INVALID_SET_DEST 0u
+#define _PIO_INVALID_MOV_SRC 0u
+#define _PIO_INVALID_MOV_DEST 0u
+#endif
+
+/*! \brief Enumeration of values to pass for source/destination args for instruction encoding functions
+ * \ingroup pio_instructions
+ *
+ * \note Not all values are suitable for all functions. Validity is only checked in debug mode when
+ * `PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS` is 1
+ */
+enum pio_src_dest {
+ pio_pins = 0u,
+ pio_x = 1u,
+ pio_y = 2u,
+ pio_null = 3u | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
+ pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
+ pio_exec_mov = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
+ pio_status = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
+ pio_pc = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
+ pio_isr = 6u | _PIO_INVALID_SET_DEST,
+ pio_osr = 7u | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST,
+ pio_exec_out = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
+};
+
+static inline uint _pio_major_instr_bits(uint instr) {
+ return instr & 0xe000u;
+}
+
+static inline uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) {
+ valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7);
+#if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS)
+ uint32_t major = _pio_major_instr_bits(instr_bits);
+ if (major == pio_instr_bits_in || major == pio_instr_bits_out) {
+ assert(arg2 && arg2 <= 32);
+ } else {
+ assert(arg2 <= 31);
+ }
+#endif
+ return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu);
+}
+
+static inline uint _pio_encode_instr_and_src_dest(enum pio_instr_bits instr_bits, enum pio_src_dest dest, uint value) {
+ return _pio_encode_instr_and_args(instr_bits, dest & 7u, value);
+}
+
+/*! \brief Encode just the delay slot bits of an instruction
+ * \ingroup pio_instructions
+ *
+ * \note This function does not return a valid instruction encoding; instead it returns an encoding of the delay
+ * slot suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
+ * combining the results of this function with the results of \ref pio_encode_sideset and \ref pio_encode_sideset_opt
+ * as they share the same bits within the instruction encoding.
+ *
+ * \param cycles the number of cycles 0-31 (or less if side set is being used)
+ * \return the delay slot bits to be ORed with an instruction encoding
+ */
+static inline uint pio_encode_delay(uint cycles) {
+ // note that the maximum cycles will be smaller if sideset_bit_count > 0
+ valid_params_if(PIO_INSTRUCTIONS, cycles <= 0x1f);
+ return cycles << 8u;
+}
+
+/*! \brief Encode just the side set bits of an instruction (in non optional side set mode)
+ * \ingroup pio_instructions
+ *
+ * \note This function does not return a valid instruction encoding; instead it returns an encoding of the side set bits
+ * suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
+ * combining the results of this function with the results of \ref pio_encode_delay as they share the same bits
+ * within the instruction encoding.
+ *
+ * \param sideset_bit_count number of side set bits as would be specified via `.sideset` in pioasm
+ * \param value the value to sideset on the pins
+ * \return the side set bits to be ORed with an instruction encoding
+ */
+static inline uint pio_encode_sideset(uint sideset_bit_count, uint value) {
+ valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 5);
+ valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
+ return value << (13u - sideset_bit_count);
+}
+
+/*! \brief Encode just the side set bits of an instruction (in optional -`opt` side set mode)
+ * \ingroup pio_instructions
+ *
+ * \note This function does not return a valid instruction encoding; instead it returns an encoding of the side set bits
+ * suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
+ * combining the results of this function with the results of \ref pio_encode_delay as they share the same bits
+ * within the instruction encoding.
+ *
+ * \param sideset_bit_count number of side set bits as would be specified via `.sideset <n> opt` in pioasm
+ * \param value the value to sideset on the pins
+ * \return the side set bits to be ORed with an instruction encoding
+ */
+static inline uint pio_encode_sideset_opt(uint sideset_bit_count, uint value) {
+ valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 4);
+ valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
+ return 0x1000u | value << (12u - sideset_bit_count);
+}
+
+/*! \brief Encode an unconditional JMP instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr);
+}
+
+/*! \brief Encode a conditional JMP if scratch X zero instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP !X <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp_not_x(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 1, addr);
+}
+
+/*! \brief Encode a conditional JMP if scratch X non-zero (and post-decrement X) instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP X-- <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp_x_dec(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 2, addr);
+}
+
+/*! \brief Encode a conditional JMP if scratch Y zero instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP !Y <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp_not_y(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 3, addr);
+}
+
+/*! \brief Encode a conditional JMP if scratch Y non-zero (and post-decrement Y) instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP Y-- <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp_y_dec(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 4, addr);
+}
+
+/*! \brief Encode a conditional JMP if scratch X not equal scratch Y instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP X!=Y <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp_x_ne_y(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 5, addr);
+}
+
+/*! \brief Encode a conditional JMP if input pin high instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP PIN <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp_pin(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 6, addr);
+}
+
+/*! \brief Encode a conditional JMP if output shift register not empty instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `JMP !OSRE <addr>`
+ *
+ * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_jmp_not_osre(uint addr) {
+ return _pio_encode_instr_and_args(pio_instr_bits_jmp, 7, addr);
+}
+
+static inline uint _pio_encode_irq(bool relative, uint irq) {
+ valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
+ return (relative ? 0x10u : 0x0u) | irq;
+}
+
+/*! \brief Encode a WAIT for GPIO pin instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `WAIT <polarity> GPIO <gpio>`
+ *
+ * \param polarity true for `WAIT 1`, false for `WAIT 0`
+ * \param gpio The real GPIO number 0-31
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_wait_gpio(bool polarity, uint gpio) {
+ return _pio_encode_instr_and_args(pio_instr_bits_wait, 0u | (polarity ? 4u : 0u), gpio);
+}
+
+/*! \brief Encode a WAIT for pin instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `WAIT <polarity> PIN <pin>`
+ *
+ * \param polarity true for `WAIT 1`, false for `WAIT 0`
+ * \param pin The pin number 0-31 relative to the executing SM's input pin mapping
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_wait_pin(bool polarity, uint pin) {
+ return _pio_encode_instr_and_args(pio_instr_bits_wait, 1u | (polarity ? 4u : 0u), pin);
+}
+
+/*! \brief Encode a WAIT for IRQ instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `WAIT <polarity> IRQ <irq> <relative>`
+ *
+ * \param polarity true for `WAIT 1`, false for `WAIT 0`
+ * \param relative true for a `WAIT IRQ <irq> REL`, false for regular `WAIT IRQ <irq>`
+ * \param irq the irq number 0-7
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_wait_irq(bool polarity, bool relative, uint irq) {
+ valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
+ return _pio_encode_instr_and_args(pio_instr_bits_wait, 2u | (polarity ? 4u : 0u), _pio_encode_irq(relative, irq));
+}
+
+/*! \brief Encode an IN instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `IN <src>, <count>`
+ *
+ * \param src The source to take data from
+ * \param count The number of bits 1-32
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_in(enum pio_src_dest src, uint count) {
+ valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_IN_SRC));
+ return _pio_encode_instr_and_src_dest(pio_instr_bits_in, src, count);
+}
+
+/*! \brief Encode an OUT instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `OUT <src>, <count>`
+ *
+ * \param dest The destination to write data to
+ * \param count The number of bits 1-32
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_out(enum pio_src_dest dest, uint count) {
+ valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_OUT_DEST));
+ return _pio_encode_instr_and_src_dest(pio_instr_bits_out, dest, count);
+}
+
+/*! \brief Encode a PUSH instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `PUSH <if_full>, <block>`
+ *
+ * \param if_full true for `PUSH IF_FULL ...`, false for `PUSH ...`
+ * \param block true for `PUSH ... BLOCK`, false for `PUSH ...`
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_push(bool if_full, bool block) {
+ return _pio_encode_instr_and_args(pio_instr_bits_push, (if_full ? 2u : 0u) | (block ? 1u : 0u), 0);
+}
+
+/*! \brief Encode a PULL instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `PULL <if_empty>, <block>`
+ *
+ * \param if_empty true for `PULL IF_EMPTY ...`, false for `PULL ...`
+ * \param block true for `PULL ... BLOCK`, false for `PULL ...`
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_pull(bool if_empty, bool block) {
+ return _pio_encode_instr_and_args(pio_instr_bits_pull, (if_empty ? 2u : 0u) | (block ? 1u : 0u), 0);
+}
+
+/*! \brief Encode a MOV instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `MOV <dest>, <src>`
+ *
+ * \param dest The destination to write data to
+ * \param src The source to take data from
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src) {
+ valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
+ valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
+ return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, src & 7u);
+}
+
+/*! \brief Encode a MOV instruction with bit invert
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `MOV <dest>, ~<src>`
+ *
+ * \param dest The destination to write inverted data to
+ * \param src The source to take data from
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_mov_not(enum pio_src_dest dest, enum pio_src_dest src) {
+ valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
+ valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
+ return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (1u << 3u) | (src & 7u));
+}
+
+/*! \brief Encode a MOV instruction with bit reverse
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `MOV <dest>, ::<src>`
+ *
+ * \param dest The destination to write bit reversed data to
+ * \param src The source to take data from
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_mov_reverse(enum pio_src_dest dest, enum pio_src_dest src) {
+ valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
+ valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
+ return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (2u << 3u) | (src & 7u));
+}
+
+/*! \brief Encode a IRQ SET instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `IRQ SET <irq> <relative>`
+ *
+ * \param relative true for a `IRQ SET <irq> REL`, false for regular `IRQ SET <irq>`
+ * \param irq the irq number 0-7
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_irq_set(bool relative, uint irq) {
+ return _pio_encode_instr_and_args(pio_instr_bits_irq, 0, _pio_encode_irq(relative, irq));
+}
+
+/*! \brief Encode a IRQ WAIT instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `IRQ WAIT <irq> <relative>`
+ *
+ * \param relative true for a `IRQ WAIT <irq> REL`, false for regular `IRQ WAIT <irq>`
+ * \param irq the irq number 0-7
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_irq_wait(bool relative, uint irq) {
+ return _pio_encode_instr_and_args(pio_instr_bits_irq, 1, _pio_encode_irq(relative, irq));
+}
+
+/*! \brief Encode a IRQ CLEAR instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `IRQ CLEAR <irq> <relative>`
+ *
+ * \param relative true for a `IRQ CLEAR <irq> REL`, false for regular `IRQ CLEAR <irq>`
+ * \param irq the irq number 0-7
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_irq_clear(bool relative, uint irq) {
+ return _pio_encode_instr_and_args(pio_instr_bits_irq, 2, _pio_encode_irq(relative, irq));
+}
+
+/*! \brief Encode a SET instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `SET <dest>, <value>`
+ *
+ * \param dest The destination to apply the value to
+ * \param value The value 0-31
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_set(enum pio_src_dest dest, uint value) {
+ valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_SET_DEST));
+ return _pio_encode_instr_and_src_dest(pio_instr_bits_set, dest, value);
+}
+
+/*! \brief Encode a NOP instruction
+ * \ingroup pio_instructions
+ *
+ * This is the equivalent of `NOP` which is itself encoded as `MOV y, y`
+ *
+ * \return The instruction encoding with 0 delay and no side set value
+ * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
+ */
+static inline uint pio_encode_nop(void) {
+ return pio_encode_mov(pio_y, pio_y);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/linux/pio_rp1.h b/include/linux/pio_rp1.h
new file mode 100644
index 000000000000..f262fdd9c8f1
--- /dev/null
+++ b/include/linux/pio_rp1.h
@@ -0,0 +1,1019 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Raspberry Pi Ltd.
+ * All rights reserved.
+ */
+
+#ifndef _PIO_RP1_H
+#define _PIO_RP1_H
+
+#include <uapi/misc/rp1_pio_if.h>
+
+#define PARAM_WARNINGS_ENABLED 1
+
+#ifdef DEBUG
+#define PARAM_WARNINGS_ENABLED 1
+#endif
+
+#ifndef PARAM_WARNINGS_ENABLED
+#define PARAM_WARNINGS_ENABLED 0
+#endif
+
+#define bad_params_if(client, test) \
+ ({ bool f = (test); if (f && client) pio_set_error(client, -EINVAL); \
+ if (f && PARAM_WARNINGS_ENABLED) WARN_ON((test)); \
+ f; })
+
+#ifndef PARAM_ASSERTIONS_ENABLE_ALL
+#define PARAM_ASSERTIONS_ENABLE_ALL 0
+#endif
+
+#ifndef PARAM_ASSERTIONS_DISABLE_ALL
+#define PARAM_ASSERTIONS_DISABLE_ALL 0
+#endif
+
+#define PARAM_ASSERTIONS_ENABLED(x) \
+ ((PARAM_ASSERTIONS_ENABLED_ ## x || PARAM_ASSERTIONS_ENABLE_ALL) && \
+ !PARAM_ASSERTIONS_DISABLE_ALL)
+#define valid_params_if(x, test) ({if (PARAM_ASSERTIONS_ENABLED(x)) WARN_ON(test); })
+
+#include <linux/pio_instructions.h>
+
+#define NUM_PIO_STATE_MACHINES 4
+#define PIO_INSTRUCTION_COUNT 32
+#define PIO_ORIGIN_ANY ((uint)(~0))
+#define GPIOS_MASK ((1 << RP1_PIO_GPIO_COUNT) - 1)
+
+#define PICO_NO_HARDWARE 0
+
+#define pio0 pio_open_helper(0)
+
+#define PROC_PIO_SM0_PINCTRL_OUT_BASE_BITS 0x0000001f
+#define PROC_PIO_SM0_PINCTRL_OUT_BASE_LSB 0
+#define PROC_PIO_SM0_PINCTRL_OUT_COUNT_BITS 0x03f00000
+#define PROC_PIO_SM0_PINCTRL_OUT_COUNT_LSB 20
+#define PROC_PIO_SM0_PINCTRL_SET_BASE_BITS 0x000003e0
+#define PROC_PIO_SM0_PINCTRL_SET_BASE_LSB 5
+#define PROC_PIO_SM0_PINCTRL_SET_COUNT_BITS 0x1c000000
+#define PROC_PIO_SM0_PINCTRL_SET_COUNT_LSB 26
+#define PROC_PIO_SM0_PINCTRL_IN_BASE_BITS 0x000f8000
+#define PROC_PIO_SM0_PINCTRL_IN_BASE_LSB 15
+#define PROC_PIO_SM0_PINCTRL_SIDESET_BASE_BITS 0x00007c00
+#define PROC_PIO_SM0_PINCTRL_SIDESET_BASE_LSB 10
+#define PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_BITS 0xe0000000
+#define PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_LSB 29
+#define PROC_PIO_SM0_EXECCTRL_SIDE_EN_BITS 0x40000000
+#define PROC_PIO_SM0_EXECCTRL_SIDE_EN_LSB 30
+#define PROC_PIO_SM0_EXECCTRL_SIDE_PINDIR_BITS 0x20000000
+#define PROC_PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB 29
+#define PROC_PIO_SM0_CLKDIV_INT_LSB 16
+#define PROC_PIO_SM0_CLKDIV_FRAC_LSB 8
+#define PROC_PIO_SM0_EXECCTRL_WRAP_TOP_BITS 0x0001f000
+#define PROC_PIO_SM0_EXECCTRL_WRAP_TOP_LSB 12
+#define PROC_PIO_SM0_EXECCTRL_WRAP_BOTTOM_BITS 0x00000f80
+#define PROC_PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB 7
+#define PROC_PIO_SM0_EXECCTRL_JMP_PIN_BITS 0x1f000000
+#define PROC_PIO_SM0_EXECCTRL_JMP_PIN_LSB 24
+#define PROC_PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_BITS 0x00040000
+#define PROC_PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_LSB 18
+#define PROC_PIO_SM0_SHIFTCTRL_AUTOPULL_BITS 0x00020000
+#define PROC_PIO_SM0_SHIFTCTRL_AUTOPULL_LSB 17
+#define PROC_PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS 0x00010000
+#define PROC_PIO_SM0_SHIFTCTRL_AUTOPUSH_LSB 16
+#define PROC_PIO_SM0_SHIFTCTRL_PUSH_THRESH_BITS 0x01f00000
+#define PROC_PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB 20
+#define PROC_PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_BITS 0x00080000
+#define PROC_PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_LSB 19
+#define PROC_PIO_SM0_SHIFTCTRL_PULL_THRESH_BITS 0x3e000000
+#define PROC_PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB 25
+#define PROC_PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS 0x40000000
+#define PROC_PIO_SM0_SHIFTCTRL_FJOIN_TX_LSB 30
+#define PROC_PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS 0x80000000
+#define PROC_PIO_SM0_SHIFTCTRL_FJOIN_RX_LSB 31
+#define PROC_PIO_SM0_EXECCTRL_OUT_STICKY_BITS 0x00020000
+#define PROC_PIO_SM0_EXECCTRL_OUT_STICKY_LSB 17
+#define PROC_PIO_SM0_EXECCTRL_INLINE_OUT_EN_BITS 0x00040000
+#define PROC_PIO_SM0_EXECCTRL_INLINE_OUT_EN_LSB 18
+#define PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS 0x00f80000
+#define PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB 19
+#define PROC_PIO_SM0_EXECCTRL_STATUS_SEL_BITS 0x00000020
+#define PROC_PIO_SM0_EXECCTRL_STATUS_SEL_LSB 5
+#define PROC_PIO_SM0_EXECCTRL_STATUS_N_BITS 0x0000001f
+#define PROC_PIO_SM0_EXECCTRL_STATUS_N_LSB 0
+
+enum pio_fifo_join {
+ PIO_FIFO_JOIN_NONE = 0,
+ PIO_FIFO_JOIN_TX = 1,
+ PIO_FIFO_JOIN_RX = 2,
+};
+
+enum pio_mov_status_type {
+ STATUS_TX_LESSTHAN = 0,
+ STATUS_RX_LESSTHAN = 1
+};
+
+enum pio_xfer_dir {
+ PIO_DIR_TO_SM,
+ PIO_DIR_FROM_SM,
+ PIO_DIR_COUNT
+};
+
+enum clock_index {
+ clk_sys = 5
+};
+
+typedef struct pio_program {
+ const uint16_t *instructions;
+ uint8_t length;
+ int8_t origin; // required instruction memory origin or -1
+} pio_program_t;
+
+enum gpio_function {
+ GPIO_FUNC_FSEL0 = 0,
+ GPIO_FUNC_FSEL1 = 1,
+ GPIO_FUNC_FSEL2 = 2,
+ GPIO_FUNC_FSEL3 = 3,
+ GPIO_FUNC_FSEL4 = 4,
+ GPIO_FUNC_FSEL5 = 5,
+ GPIO_FUNC_FSEL6 = 6,
+ GPIO_FUNC_FSEL7 = 7,
+ GPIO_FUNC_FSEL8 = 8,
+ GPIO_FUNC_NULL = 0x1f,
+
+ // Name a few
+ GPIO_FUNC_SYS_RIO = 5,
+ GPIO_FUNC_PROC_RIO = 6,
+ GPIO_FUNC_PIO = 7,
+};
+
+enum gpio_irq_level {
+ GPIO_IRQ_LEVEL_LOW = 0x1u,
+ GPIO_IRQ_LEVEL_HIGH = 0x2u,
+ GPIO_IRQ_EDGE_FALL = 0x4u,
+ GPIO_IRQ_EDGE_RISE = 0x8u,
+};
+
+enum gpio_override {
+ GPIO_OVERRIDE_NORMAL = 0,
+ GPIO_OVERRIDE_INVERT = 1,
+ GPIO_OVERRIDE_LOW = 2,
+ GPIO_OVERRIDE_HIGH = 3,
+};
+enum gpio_slew_rate {
+ GPIO_SLEW_RATE_SLOW = 0,
+ GPIO_SLEW_RATE_FAST = 1
+};
+
+enum gpio_drive_strength {
+ GPIO_DRIVE_STRENGTH_2MA = 0,
+ GPIO_DRIVE_STRENGTH_4MA = 1,
+ GPIO_DRIVE_STRENGTH_8MA = 2,
+ GPIO_DRIVE_STRENGTH_12MA = 3
+};
+
+struct fp24_8 {
+ uint32_t val;
+};
+
+typedef rp1_pio_sm_config pio_sm_config;
+
+typedef struct rp1_pio_client *PIO;
+
+int rp1_pio_init(void);
+PIO rp1_pio_open(void);
+void rp1_pio_close(struct rp1_pio_client *client);
+void rp1_pio_set_error(struct rp1_pio_client *client, int err);
+int rp1_pio_get_error(const struct rp1_pio_client *client);
+void rp1_pio_clear_error(struct rp1_pio_client *client);
+int rp1_pio_sm_config_xfer(struct rp1_pio_client *client, uint sm, uint dir,
+ uint buf_size, uint buf_count);
+int rp1_pio_sm_xfer_data(struct rp1_pio_client *client, uint sm, uint dir,
+ uint data_bytes, void *data, dma_addr_t dma_addr,
+ void (*callback)(void *param), void *param);
+
+int rp1_pio_can_add_program(struct rp1_pio_client *client, void *param);
+int rp1_pio_add_program(struct rp1_pio_client *client, void *param);
+int rp1_pio_remove_program(struct rp1_pio_client *client, void *param);
+int rp1_pio_clear_instr_mem(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_claim(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_unclaim(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_is_claimed(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_init(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_set_config(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_exec(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_clear_fifos(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_set_clkdiv(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_set_pins(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_set_pindirs(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_set_enabled(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_restart(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_clkdiv_restart(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_enable_sync(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_put(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_get(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_set_dmactrl(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_fifo_state(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_drain_tx(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_init(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_set_function(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_set_pulls(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_set_outover(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_set_inover(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_set_oeover(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_set_input_enabled(struct rp1_pio_client *client, void *param);
+int rp1_pio_gpio_set_drive_strength(struct rp1_pio_client *client, void *param);
+
+static inline int pio_init(void)
+{
+ return rp1_pio_init();
+}
+
+static inline struct rp1_pio_client *pio_open(void)
+{
+ return rp1_pio_open();
+}
+
+static inline void pio_close(struct rp1_pio_client *client)
+{
+ rp1_pio_close(client);
+}
+
+static inline void pio_set_error(struct rp1_pio_client *client, int err)
+{
+ rp1_pio_set_error(client, err);
+}
+
+static inline int pio_get_error(const struct rp1_pio_client *client)
+{
+ return rp1_pio_get_error(client);
+}
+
+static inline void pio_clear_error(struct rp1_pio_client *client)
+{
+ rp1_pio_clear_error(client);
+}
+
+static inline int pio_sm_config_xfer(struct rp1_pio_client *client, uint sm, uint dir,
+ uint buf_size, uint buf_count)
+{
+ return rp1_pio_sm_config_xfer(client, sm, dir, buf_size, buf_count);
+}
+
+static inline int pio_sm_xfer_data(struct rp1_pio_client *client, uint sm, uint dir,
+ uint data_bytes, void *data, dma_addr_t dma_addr,
+ void (*callback)(void *param), void *param)
+{
+ return rp1_pio_sm_xfer_data(client, sm, dir, data_bytes, data, dma_addr, callback, param);
+}
+
+static inline struct fp24_8 make_fp24_8(uint mul, uint div)
+{
+ struct fp24_8 res = { .val = ((unsigned long long)mul << 8) / div };
+
+ return res;
+}
+
+static inline bool pio_can_add_program(struct rp1_pio_client *client,
+ const pio_program_t *program)
+{
+ struct rp1_pio_add_program_args args;
+
+ if (bad_params_if(client, program->length > PIO_INSTRUCTION_COUNT))
+ return false;
+ args.origin = (program->origin == -1) ? PIO_ORIGIN_ANY : program->origin;
+ args.num_instrs = program->length;
+
+ memcpy(args.instrs, program->instructions, args.num_instrs * sizeof(args.instrs[0]));
+ return rp1_pio_can_add_program(client, &args);
+}
+
+static inline bool pio_can_add_program_at_offset(struct rp1_pio_client *client,
+ const pio_program_t *program, uint offset)
+{
+ struct rp1_pio_add_program_args args;
+
+ if (bad_params_if(client, program->length > PIO_INSTRUCTION_COUNT ||
+ offset >= PIO_INSTRUCTION_COUNT))
+ return false;
+ args.origin = offset;
+ args.num_instrs = program->length;
+
+ memcpy(args.instrs, program->instructions, args.num_instrs * sizeof(args.instrs[0]));
+ return !rp1_pio_can_add_program(client, &args);
+}
+
+static inline uint pio_add_program(struct rp1_pio_client *client, const pio_program_t *program)
+{
+ struct rp1_pio_add_program_args args;
+ int offset;
+
+ if (bad_params_if(client, program->length > PIO_INSTRUCTION_COUNT))
+ return PIO_ORIGIN_ANY;
+ args.origin = (program->origin == -1) ? PIO_ORIGIN_ANY : program->origin;
+ args.num_instrs = program->length;
+
+ memcpy(args.instrs, program->instructions, args.num_instrs * sizeof(args.instrs[0]));
+ offset = rp1_pio_add_program(client, &args);
+ return (offset >= 0) ? offset : PIO_ORIGIN_ANY;
+}
+
+static inline int pio_add_program_at_offset(struct rp1_pio_client *client,
+ const pio_program_t *program, uint offset)
+{
+ struct rp1_pio_add_program_args args;
+
+ if (bad_params_if(client, program->length > PIO_INSTRUCTION_COUNT ||
+ offset >= PIO_INSTRUCTION_COUNT))
+ return -EINVAL;
+ args.origin = offset;
+ args.num_instrs = program->length;
+
+ memcpy(args.instrs, program->instructions, args.num_instrs * sizeof(args.instrs[0]));
+ return rp1_pio_add_program(client, &args);
+}
+
+static inline int pio_remove_program(struct rp1_pio_client *client, const pio_program_t *program,
+ uint loaded_offset)
+{
+ struct rp1_pio_remove_program_args args;
+
+ args.origin = loaded_offset;
+ args.num_instrs = program->length;
+
+ return rp1_pio_remove_program(client, &args);
+}
+
+static inline int pio_clear_instruction_memory(struct rp1_pio_client *client)
+{
+ return rp1_pio_clear_instr_mem(client, NULL);
+}
+
+static inline int pio_sm_claim(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_claim_args args = { .mask = 1 << sm };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+
+ return rp1_pio_sm_claim(client, &args);
+}
+
+static inline int pio_claim_sm_mask(struct rp1_pio_client *client, uint mask)
+{
+ struct rp1_pio_sm_claim_args args = { .mask = mask };
+
+ if (bad_params_if(client, mask >= (1 << NUM_PIO_STATE_MACHINES)))
+ return -EINVAL;
+
+ return rp1_pio_sm_claim(client, &args);
+}
+
+static inline int pio_sm_unclaim(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_claim_args args = { .mask = 1 << sm };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+
+ return rp1_pio_sm_unclaim(client, &args);
+}
+
+static inline int pio_claim_unused_sm(struct rp1_pio_client *client, bool required)
+{
+ struct rp1_pio_sm_claim_args args = { .mask = 0 };
+ int sm;
+
+ sm = rp1_pio_sm_claim(client, &args);
+ if (sm < 0 && required)
+ WARN_ON("No PIO state machines are available");
+ return sm;
+}
+
+static inline bool pio_sm_is_claimed(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_claim_args args = { .mask = (1 << sm) };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return true;
+ return rp1_pio_sm_is_claimed(client, &args);
+}
+
+static inline int pio_sm_init(struct rp1_pio_client *client, uint sm, uint initial_pc,
+ const pio_sm_config *config)
+{
+ struct rp1_pio_sm_init_args args = { .sm = sm, .initial_pc = initial_pc,
+ .config = *config };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES ||
+ initial_pc >= PIO_INSTRUCTION_COUNT))
+ return -EINVAL;
+
+ return rp1_pio_sm_init(client, &args);
+}
+
+static inline int pio_sm_set_config(struct rp1_pio_client *client, uint sm,
+ const pio_sm_config *config)
+{
+ struct rp1_pio_sm_init_args args = { .sm = sm, .config = *config };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+
+ return rp1_pio_sm_set_config(client, &args);
+}
+
+static inline int pio_sm_exec(struct rp1_pio_client *client, uint sm, uint instr)
+{
+ struct rp1_pio_sm_exec_args args = { .sm = sm, .instr = instr, .blocking = false };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES || instr > (uint16_t)~0))
+ return -EINVAL;
+
+ return rp1_pio_sm_exec(client, &args);
+}
+
+static inline int pio_sm_exec_wait_blocking(struct rp1_pio_client *client, uint sm, uint instr)
+{
+ struct rp1_pio_sm_exec_args args = { .sm = sm, .instr = instr, .blocking = true };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES || instr > (uint16_t)~0))
+ return -EINVAL;
+
+ return rp1_pio_sm_exec(client, &args);
+}
+
+static inline int pio_sm_clear_fifos(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_clear_fifos_args args = { .sm = sm };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_clear_fifos(client, &args);
+}
+
+static inline bool pio_calculate_clkdiv_from_fp24_8(struct fp24_8 div, uint16_t *div_int,
+ uint8_t *div_frac)
+{
+ uint inum = (div.val >> 8);
+
+ if (bad_params_if(NULL, inum < 1 || inum > 65536))
+ return false;
+ *div_int = (uint16_t)inum;
+ if (*div_int == 0)
+ *div_frac = 0;
+ else
+ *div_frac = div.val & 0xff;
+ return true;
+}
+
+static inline int pio_sm_set_clkdiv_int_frac(struct rp1_pio_client *client, uint sm,
+ uint16_t div_int, uint8_t div_frac)
+{
+ struct rp1_pio_sm_set_clkdiv_args args = { .sm = sm, .div_int = div_int,
+ .div_frac = div_frac };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES ||
+ (div_int == 0 && div_frac != 0)))
+ return -EINVAL;
+ return rp1_pio_sm_set_clkdiv(client, &args);
+}
+
+static inline int pio_sm_set_clkdiv(struct rp1_pio_client *client, uint sm, struct fp24_8 div)
+{
+ struct rp1_pio_sm_set_clkdiv_args args = { .sm = sm };
+
+ if (!pio_calculate_clkdiv_from_fp24_8(div, &args.div_int, &args.div_frac))
+ return -EINVAL;
+ return rp1_pio_sm_set_clkdiv(client, &args);
+}
+
+static inline int pio_sm_set_pins(struct rp1_pio_client *client, uint sm, uint32_t pin_values)
+{
+ struct rp1_pio_sm_set_pins_args args = { .sm = sm, .values = pin_values,
+ .mask = GPIOS_MASK };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_set_pins(client, &args);
+}
+
+static inline int pio_sm_set_pins_with_mask(struct rp1_pio_client *client, uint sm,
+ uint32_t pin_values, uint32_t pin_mask)
+{
+ struct rp1_pio_sm_set_pins_args args = { .sm = sm, .values = pin_values,
+ .mask = pin_mask };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_set_pins(client, &args);
+}
+
+static inline int pio_sm_set_pindirs_with_mask(struct rp1_pio_client *client, uint sm,
+ uint32_t pin_dirs, uint32_t pin_mask)
+{
+ struct rp1_pio_sm_set_pindirs_args args = { .sm = sm, .dirs = pin_dirs,
+ .mask = pin_mask };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES ||
+ (pin_dirs & GPIOS_MASK) != pin_dirs ||
+ (pin_mask & pin_mask) != pin_mask))
+ return -EINVAL;
+ return rp1_pio_sm_set_pindirs(client, &args);
+}
+
+static inline int pio_sm_set_consecutive_pindirs(struct rp1_pio_client *client, uint sm,
+ uint pin_base, uint pin_count, bool is_out)
+{
+ uint32_t mask = ((1 << pin_count) - 1) << pin_base;
+ struct rp1_pio_sm_set_pindirs_args args = { .sm = sm, .dirs = is_out ? mask : 0,
+ .mask = mask };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES ||
+ pin_base >= RP1_PIO_GPIO_COUNT ||
+ pin_count > RP1_PIO_GPIO_COUNT ||
+ (pin_base + pin_count) > RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_sm_set_pindirs(client, &args);
+}
+
+static inline int pio_sm_set_enabled(struct rp1_pio_client *client, uint sm, bool enabled)
+{
+ struct rp1_pio_sm_set_enabled_args args = { .mask = (1 << sm), .enable = enabled };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_set_enabled(client, &args);
+}
+
+static inline int pio_set_sm_mask_enabled(struct rp1_pio_client *client, uint32_t mask,
+ bool enabled)
+{
+ struct rp1_pio_sm_set_enabled_args args = { .mask = mask, .enable = enabled };
+
+ if (bad_params_if(client, mask >= (1 << NUM_PIO_STATE_MACHINES)))
+ return -EINVAL;
+ return rp1_pio_sm_set_enabled(client, &args);
+}
+
+static inline int pio_sm_restart(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_restart_args args = { .mask = (1 << sm) };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_restart(client, &args);
+}
+
+static inline int pio_restart_sm_mask(struct rp1_pio_client *client, uint32_t mask)
+{
+ struct rp1_pio_sm_restart_args args = { .mask = (uint16_t)mask };
+
+ if (bad_params_if(client, mask >= (1 << NUM_PIO_STATE_MACHINES)))
+ return -EINVAL;
+ return rp1_pio_sm_restart(client, &args);
+}
+
+static inline int pio_sm_clkdiv_restart(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_restart_args args = { .mask = (1 << sm) };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_clkdiv_restart(client, &args);
+}
+
+static inline int pio_clkdiv_restart_sm_mask(struct rp1_pio_client *client, uint32_t mask)
+{
+ struct rp1_pio_sm_restart_args args = { .mask = (uint16_t)mask };
+
+ if (bad_params_if(client, mask >= (1 << NUM_PIO_STATE_MACHINES)))
+ return -EINVAL;
+ return rp1_pio_sm_clkdiv_restart(client, &args);
+}
+
+static inline int pio_enable_sm_in_sync_mask(struct rp1_pio_client *client, uint32_t mask)
+{
+ struct rp1_pio_sm_enable_sync_args args = { .mask = (uint16_t)mask };
+
+ if (bad_params_if(client, mask >= (1 << NUM_PIO_STATE_MACHINES)))
+ return -EINVAL;
+ return rp1_pio_sm_enable_sync(client, &args);
+}
+
+static inline int pio_sm_set_dmactrl(struct rp1_pio_client *client, uint sm, bool is_tx,
+ uint32_t ctrl)
+{
+ struct rp1_pio_sm_set_dmactrl_args args = { .sm = sm, .is_tx = is_tx, .ctrl = ctrl };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_set_dmactrl(client, &args);
+};
+
+static inline int pio_sm_drain_tx_fifo(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_clear_fifos_args args = { .sm = sm };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_drain_tx(client, &args);
+};
+
+static inline int pio_sm_put(struct rp1_pio_client *client, uint sm, uint32_t data)
+{
+ struct rp1_pio_sm_put_args args = { .sm = (uint16_t)sm, .blocking = false, .data = data };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_put(client, &args);
+}
+
+static inline int pio_sm_put_blocking(struct rp1_pio_client *client, uint sm, uint32_t data)
+{
+ struct rp1_pio_sm_put_args args = { .sm = (uint16_t)sm, .blocking = true, .data = data };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_put(client, &args);
+}
+
+static inline uint32_t pio_sm_get(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_get_args args = { .sm = (uint16_t)sm, .blocking = false };
+
+ if (!bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ rp1_pio_sm_get(client, &args);
+ return args.data;
+}
+
+static inline uint32_t pio_sm_get_blocking(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_get_args args = { .sm = (uint16_t)sm, .blocking = true };
+
+ if (!bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ rp1_pio_sm_get(client, &args);
+ return args.data;
+}
+
+static inline int pio_sm_is_rx_fifo_empty(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = false };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.empty;
+ return ret;
+};
+
+static inline int pio_sm_is_rx_fifo_full(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = false };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.full;
+ return ret;
+};
+
+static inline int pio_sm_rx_fifo_level(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = false };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.level;
+ return ret;
+};
+
+static inline int pio_sm_is_tx_fifo_empty(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = true };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.empty;
+ return ret;
+};
+
+static inline int pio_sm_is_tx_fifo_full(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = true };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.full;
+ return ret;
+};
+
+static inline int pio_sm_tx_fifo_level(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = true };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.level;
+ return ret;
+};
+
+static inline void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint out_count)
+{
+ if (bad_params_if(NULL, out_base >= RP1_PIO_GPIO_COUNT ||
+ out_count > RP1_PIO_GPIO_COUNT))
+ return;
+
+ c->pinctrl = (c->pinctrl & ~(PROC_PIO_SM0_PINCTRL_OUT_BASE_BITS |
+ PROC_PIO_SM0_PINCTRL_OUT_COUNT_BITS)) |
+ (out_base << PROC_PIO_SM0_PINCTRL_OUT_BASE_LSB) |
+ (out_count << PROC_PIO_SM0_PINCTRL_OUT_COUNT_LSB);
+}
+
+static inline void sm_config_set_set_pins(pio_sm_config *c, uint set_base, uint set_count)
+{
+ if (bad_params_if(NULL, set_base >= RP1_PIO_GPIO_COUNT ||
+ set_count > 5))
+ return;
+
+ c->pinctrl = (c->pinctrl & ~(PROC_PIO_SM0_PINCTRL_SET_BASE_BITS |
+ PROC_PIO_SM0_PINCTRL_SET_COUNT_BITS)) |
+ (set_base << PROC_PIO_SM0_PINCTRL_SET_BASE_LSB) |
+ (set_count << PROC_PIO_SM0_PINCTRL_SET_COUNT_LSB);
+}
+
+
+static inline void sm_config_set_in_pins(pio_sm_config *c, uint in_base)
+{
+ if (bad_params_if(NULL, in_base >= RP1_PIO_GPIO_COUNT))
+ return;
+
+ c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_IN_BASE_BITS) |
+ (in_base << PROC_PIO_SM0_PINCTRL_IN_BASE_LSB);
+}
+
+static inline void sm_config_set_sideset_pins(pio_sm_config *c, uint sideset_base)
+{
+ if (bad_params_if(NULL, sideset_base >= RP1_PIO_GPIO_COUNT))
+ return;
+
+ c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SIDESET_BASE_BITS) |
+ (sideset_base << PROC_PIO_SM0_PINCTRL_SIDESET_BASE_LSB);
+}
+
+static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool optional,
+ bool pindirs)
+{
+ if (bad_params_if(NULL, bit_count > 5 ||
+ (optional && (bit_count == 0))))
+ return;
+ c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_BITS) |
+ (bit_count << PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_LSB);
+
+ c->execctrl = (c->execctrl & ~(PROC_PIO_SM0_EXECCTRL_SIDE_EN_BITS |
+ PROC_PIO_SM0_EXECCTRL_SIDE_PINDIR_BITS)) |
+ (optional << PROC_PIO_SM0_EXECCTRL_SIDE_EN_LSB) |
+ (pindirs << PROC_PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB);
+}
+
+static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_int,
+ uint8_t div_frac)
+{
+ if (bad_params_if(NULL, div_int == 0 && div_frac != 0))
+ return;
+
+ c->clkdiv =
+ (((uint)div_frac) << PROC_PIO_SM0_CLKDIV_FRAC_LSB) |
+ (((uint)div_int) << PROC_PIO_SM0_CLKDIV_INT_LSB);
+}
+
+static inline void sm_config_set_clkdiv(pio_sm_config *c, struct fp24_8 div)
+{
+ uint16_t div_int;
+ uint8_t div_frac;
+
+ pio_calculate_clkdiv_from_fp24_8(div, &div_int, &div_frac);
+ sm_config_set_clkdiv_int_frac(c, div_int, div_frac);
+}
+
+static inline void sm_config_set_wrap(pio_sm_config *c, uint wrap_target, uint wrap)
+{
+ if (bad_params_if(NULL, wrap >= PIO_INSTRUCTION_COUNT ||
+ wrap_target >= PIO_INSTRUCTION_COUNT))
+ return;
+
+ c->execctrl = (c->execctrl & ~(PROC_PIO_SM0_EXECCTRL_WRAP_TOP_BITS |
+ PROC_PIO_SM0_EXECCTRL_WRAP_BOTTOM_BITS)) |
+ (wrap_target << PROC_PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB) |
+ (wrap << PROC_PIO_SM0_EXECCTRL_WRAP_TOP_LSB);
+}
+
+static inline void sm_config_set_jmp_pin(pio_sm_config *c, uint pin)
+{
+ if (bad_params_if(NULL, pin >= RP1_PIO_GPIO_COUNT))
+ return;
+
+ c->execctrl = (c->execctrl & ~PROC_PIO_SM0_EXECCTRL_JMP_PIN_BITS) |
+ (pin << PROC_PIO_SM0_EXECCTRL_JMP_PIN_LSB);
+}
+
+static inline void sm_config_set_in_shift(pio_sm_config *c, bool shift_right, bool autopush,
+ uint push_threshold)
+{
+ if (bad_params_if(NULL, push_threshold > 32))
+ return;
+
+ c->shiftctrl = (c->shiftctrl &
+ ~(PROC_PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_BITS |
+ PROC_PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS |
+ PROC_PIO_SM0_SHIFTCTRL_PUSH_THRESH_BITS)) |
+ (shift_right << PROC_PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_LSB) |
+ (autopush << PROC_PIO_SM0_SHIFTCTRL_AUTOPUSH_LSB) |
+ ((push_threshold & 0x1fu) << PROC_PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB);
+}
+
+static inline void sm_config_set_out_shift(pio_sm_config *c, bool shift_right, bool autopull,
+ uint pull_threshold)
+{
+ if (bad_params_if(NULL, pull_threshold > 32))
+ return;
+
+ c->shiftctrl = (c->shiftctrl &
+ ~(PROC_PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_BITS |
+ PROC_PIO_SM0_SHIFTCTRL_AUTOPULL_BITS |
+ PROC_PIO_SM0_SHIFTCTRL_PULL_THRESH_BITS)) |
+ (shift_right << PROC_PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_LSB) |
+ (autopull << PROC_PIO_SM0_SHIFTCTRL_AUTOPULL_LSB) |
+ ((pull_threshold & 0x1fu) << PROC_PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB);
+}
+
+static inline void sm_config_set_fifo_join(pio_sm_config *c, enum pio_fifo_join join)
+{
+ if (bad_params_if(NULL, join != PIO_FIFO_JOIN_NONE &&
+ join != PIO_FIFO_JOIN_TX &&
+ join != PIO_FIFO_JOIN_RX))
+ return;
+
+ c->shiftctrl = (c->shiftctrl & (uint)~(PROC_PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS |
+ PROC_PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS)) |
+ (((uint)join) << PROC_PIO_SM0_SHIFTCTRL_FJOIN_TX_LSB);
+}
+
+static inline void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool has_enable_pin,
+ uint enable_pin_index)
+{
+ c->execctrl = (c->execctrl &
+ (uint)~(PROC_PIO_SM0_EXECCTRL_OUT_STICKY_BITS |
+ PROC_PIO_SM0_EXECCTRL_INLINE_OUT_EN_BITS |
+ PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS)) |
+ (sticky << PROC_PIO_SM0_EXECCTRL_OUT_STICKY_LSB) |
+ (has_enable_pin << PROC_PIO_SM0_EXECCTRL_INLINE_OUT_EN_LSB) |
+ ((enable_pin_index << PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB) &
+ PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS);
+}
+
+static inline void sm_config_set_mov_status(pio_sm_config *c, enum pio_mov_status_type status_sel,
+ uint status_n)
+{
+ if (bad_params_if(NULL, status_sel != STATUS_TX_LESSTHAN &&
+ status_sel != STATUS_RX_LESSTHAN))
+ return;
+
+ c->execctrl = (c->execctrl
+ & ~(PROC_PIO_SM0_EXECCTRL_STATUS_SEL_BITS | PROC_PIO_SM0_EXECCTRL_STATUS_N_BITS))
+ | ((((uint)status_sel) << PROC_PIO_SM0_EXECCTRL_STATUS_SEL_LSB) &
+ PROC_PIO_SM0_EXECCTRL_STATUS_SEL_BITS)
+ | ((status_n << PROC_PIO_SM0_EXECCTRL_STATUS_N_LSB) &
+ PROC_PIO_SM0_EXECCTRL_STATUS_N_BITS);
+}
+
+static inline pio_sm_config pio_get_default_sm_config(void)
+{
+ pio_sm_config c = { 0 };
+
+ sm_config_set_clkdiv_int_frac(&c, 1, 0);
+ sm_config_set_wrap(&c, 0, 31);
+ sm_config_set_in_shift(&c, true, false, 32);
+ sm_config_set_out_shift(&c, true, false, 32);
+ return c;
+}
+
+static inline uint32_t clock_get_hz(enum clock_index clk_index)
+{
+ const uint32_t MHZ = 1000000;
+
+ if (bad_params_if(NULL, clk_index != clk_sys))
+ return 0;
+ return 200 * MHZ;
+}
+
+static inline int pio_gpio_set_function(struct rp1_pio_client *client, uint gpio,
+ enum gpio_function fn)
+{
+ struct rp1_gpio_set_function_args args = { .gpio = gpio, .fn = fn };
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_gpio_set_function(client, &args);
+}
+
+static inline int pio_gpio_init(struct rp1_pio_client *client, uint gpio)
+{
+ struct rp1_gpio_init_args args = { .gpio = gpio };
+ int ret;
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ ret = rp1_pio_gpio_init(client, &args);
+ if (ret)
+ return ret;
+ return pio_gpio_set_function(client, gpio, RP1_GPIO_FUNC_PIO);
+}
+
+static inline int pio_gpio_set_pulls(struct rp1_pio_client *client, uint gpio, bool up, bool down)
+{
+ struct rp1_gpio_set_pulls_args args = { .gpio = gpio, .up = up, .down = down };
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_gpio_set_pulls(client, &args);
+}
+
+static inline int pio_gpio_set_outover(struct rp1_pio_client *client, uint gpio, uint value)
+{
+ struct rp1_gpio_set_args args = { .gpio = gpio, .value = value };
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_gpio_set_outover(client, &args);
+}
+
+static inline int pio_gpio_set_inover(struct rp1_pio_client *client, uint gpio, uint value)
+{
+ struct rp1_gpio_set_args args = { .gpio = gpio, .value = value };
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_gpio_set_inover(client, &args);
+}
+
+static inline int pio_gpio_set_oeover(struct rp1_pio_client *client, uint gpio, uint value)
+{
+ struct rp1_gpio_set_args args = { .gpio = gpio, .value = value };
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_gpio_set_oeover(client, &args);
+}
+
+static inline int pio_gpio_set_input_enabled(struct rp1_pio_client *client, uint gpio,
+ bool enabled)
+{
+ struct rp1_gpio_set_args args = { .gpio = gpio, .value = enabled };
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_gpio_set_input_enabled(client, &args);
+}
+
+static inline int pio_gpio_set_drive_strength(struct rp1_pio_client *client, uint gpio,
+ enum gpio_drive_strength drive)
+{
+ struct rp1_gpio_set_args args = { .gpio = gpio, .value = drive };
+
+ if (bad_params_if(client, gpio >= RP1_PIO_GPIO_COUNT))
+ return -EINVAL;
+ return rp1_pio_gpio_set_drive_strength(client, &args);
+}
+
+static inline int pio_gpio_pull_up(struct rp1_pio_client *client, uint gpio)
+{
+ return pio_gpio_set_pulls(client, gpio, true, false);
+}
+
+static inline int pio_gpio_pull_down(struct rp1_pio_client *client, uint gpio)
+{
+ return pio_gpio_set_pulls(client, gpio, false, true);
+}
+
+static inline int pio_gpio_disable_pulls(struct rp1_pio_client *client, uint gpio)
+{
+ return pio_gpio_set_pulls(client, gpio, false, false);
+}
+
+#endif
diff --git a/include/linux/platform_data/dma-bcm2708.h b/include/linux/platform_data/dma-bcm2708.h
new file mode 100644
index 000000000000..6ca874d332a8
--- /dev/null
+++ b/include/linux/platform_data/dma-bcm2708.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PLAT_BCM2708_DMA_H
+#define _PLAT_BCM2708_DMA_H
+
+/* DMA CS Control and Status bits */
+#define BCM2708_DMA_ACTIVE BIT(0)
+#define BCM2708_DMA_INT BIT(2)
+#define BCM2708_DMA_ISPAUSED BIT(4) /* Pause requested or not active */
+#define BCM2708_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */
+#define BCM2708_DMA_ERR BIT(8)
+#define BCM2708_DMA_ABORT BIT(30) /* stop current CB, go to next, WO */
+#define BCM2708_DMA_RESET BIT(31) /* WO, self clearing */
+
+/* DMA control block "info" field bits */
+#define BCM2708_DMA_INT_EN BIT(0)
+#define BCM2708_DMA_TDMODE BIT(1)
+#define BCM2708_DMA_WAIT_RESP BIT(3)
+#define BCM2708_DMA_D_INC BIT(4)
+#define BCM2708_DMA_D_WIDTH BIT(5)
+#define BCM2708_DMA_D_DREQ BIT(6)
+#define BCM2708_DMA_S_INC BIT(8)
+#define BCM2708_DMA_S_WIDTH BIT(9)
+#define BCM2708_DMA_S_DREQ BIT(10)
+
+#define BCM2708_DMA_BURST(x) (((x) & 0xf) << 12)
+#define BCM2708_DMA_PER_MAP(x) ((x) << 16)
+#define BCM2708_DMA_WAITS(x) (((x) & 0x1f) << 21)
+
+#define BCM2708_DMA_DREQ_EMMC 11
+#define BCM2708_DMA_DREQ_SDHOST 13
+
+#define BCM2708_DMA_CS 0x00 /* Control and Status */
+#define BCM2708_DMA_ADDR 0x04
+/* the current control block appears in the following registers - read only */
+#define BCM2708_DMA_INFO 0x08
+#define BCM2708_DMA_SOURCE_AD 0x0c
+#define BCM2708_DMA_DEST_AD 0x10
+#define BCM2708_DMA_NEXTCB 0x1C
+#define BCM2708_DMA_DEBUG 0x20
+
+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4) + BCM2708_DMA_CS)
+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4) + BCM2708_DMA_ADDR)
+
+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w))
+
+/* When listing features we can ask for when allocating DMA channels give
+ those with higher priority smaller ordinal numbers */
+#define BCM_DMA_FEATURE_FAST_ORD 0
+#define BCM_DMA_FEATURE_BULK_ORD 1
+#define BCM_DMA_FEATURE_NORMAL_ORD 2
+#define BCM_DMA_FEATURE_LITE_ORD 3
+#define BCM_DMA_FEATURE_FAST BIT(BCM_DMA_FEATURE_FAST_ORD)
+#define BCM_DMA_FEATURE_BULK BIT(BCM_DMA_FEATURE_BULK_ORD)
+#define BCM_DMA_FEATURE_NORMAL BIT(BCM_DMA_FEATURE_NORMAL_ORD)
+#define BCM_DMA_FEATURE_LITE BIT(BCM_DMA_FEATURE_LITE_ORD)
+#define BCM_DMA_FEATURE_COUNT 4
+
+struct bcm2708_dma_cb {
+ u32 info;
+ u32 src;
+ u32 dst;
+ u32 length;
+ u32 stride;
+ u32 next;
+ u32 pad[2];
+};
+
+struct scatterlist;
+struct platform_device;
+
+#if defined(CONFIG_DMA_BCM2708) || defined(CONFIG_DMA_BCM2708_MODULE)
+
+int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len);
+void bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block);
+void bcm_dma_wait_idle(void __iomem *dma_chan_base);
+bool bcm_dma_is_busy(void __iomem *dma_chan_base);
+int bcm_dma_abort(void __iomem *dma_chan_base);
+
+/* return channel no or -ve error */
+int bcm_dma_chan_alloc(unsigned preferred_feature_set,
+ void __iomem **out_dma_base, int *out_dma_irq);
+int bcm_dma_chan_free(int channel);
+
+int bcm_dmaman_probe(struct platform_device *pdev, void __iomem *base,
+ u32 chans_available);
+int bcm_dmaman_remove(struct platform_device *pdev);
+
+#else /* CONFIG_DMA_BCM2708 */
+
+static inline int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr,
+ int sg_len)
+{
+ return 0;
+}
+
+static inline void bcm_dma_start(void __iomem *dma_chan_base,
+ dma_addr_t control_block) { }
+
+static inline void bcm_dma_wait_idle(void __iomem *dma_chan_base) { }
+
+static inline bool bcm_dma_is_busy(void __iomem *dma_chan_base)
+{
+ return false;
+}
+
+static inline int bcm_dma_abort(void __iomem *dma_chan_base)
+{
+ return -EINVAL;
+}
+
+static inline int bcm_dma_chan_alloc(unsigned preferred_feature_set,
+ void __iomem **out_dma_base,
+ int *out_dma_irq)
+{
+ return -EINVAL;
+}
+
+static inline int bcm_dma_chan_free(int channel)
+{
+ return -EINVAL;
+}
+
+static inline int bcm_dmaman_probe(struct platform_device *pdev,
+ void __iomem *base, u32 chans_available)
+{
+ return 0;
+}
+
+static inline int bcm_dmaman_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+#endif /* CONFIG_DMA_BCM2708 || CONFIG_DMA_BCM2708_MODULE */
+
+#endif /* _PLAT_BCM2708_DMA_H */
diff --git a/include/linux/rp1-firmware.h b/include/linux/rp1-firmware.h
new file mode 100644
index 000000000000..19f11d6d79b1
--- /dev/null
+++ b/include/linux/rp1-firmware.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 2023-2024 Raspberry Pi Ltd.
+ */
+
+#ifndef __SOC_RP1_FIRMWARE_H__
+#define __SOC_RP1_FIRMWARE_H__
+
+#include <linux/types.h>
+#include <linux/of_device.h>
+
+#define RP1_FOURCC(s) ((uint32_t)((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | (s[3] << 0)))
+
+struct rp1_firmware;
+
+#if IS_ENABLED(CONFIG_FIRMWARE_RP1)
+int rp1_firmware_message(struct rp1_firmware *fw, uint16_t op,
+ const void *data, unsigned int data_len,
+ void *resp, unsigned int resp_space);
+void rp1_firmware_put(struct rp1_firmware *fw);
+struct rp1_firmware *rp1_firmware_get(struct device_node *fwnode);
+struct rp1_firmware *devm_rp1_firmware_get(struct device *dev, struct device_node *fwnode);
+int rp1_firmware_get_feature(struct rp1_firmware *fw, uint32_t fourcc,
+ uint32_t *op_base, uint32_t *op_count);
+#else
+static inline int rp1_firmware_message(struct rp1_firmware *fw, uint16_t op,
+ const void *data, unsigned int data_len,
+ void *resp, unsigned int resp_space)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void rp1_firmware_put(struct rp1_firmware *fw) { }
+
+static inline struct rp1_firmware *rp1_firmware_get(struct device_node *fwnode)
+{
+ return NULL;
+}
+
+static inline struct rp1_firmware *devm_rp1_firmware_get(struct device *dev,
+ struct device_node *fwnode)
+{
+ return NULL;
+}
+
+static inline int rp1_firmware_get_feature(struct rp1_firmware *fw, uint32_t fourcc,
+ uint32_t *op_base, uint32_t *op_count)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
+#endif /* __SOC_RP1_FIRMWARE_H__ */
diff --git a/include/linux/rp1_platform.h b/include/linux/rp1_platform.h
new file mode 100644
index 000000000000..f805dbe1ed9b
--- /dev/null
+++ b/include/linux/rp1_platform.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021-2022 Raspberry Pi Ltd.
+ * All rights reserved.
+ */
+
+#ifndef _RP1_PLATFORM_H
+#define _RP1_PLATFORM_H
+
+#include <vdso/bits.h>
+
+#define RP1_B0_CHIP_ID 0x10001927
+#define RP1_C0_CHIP_ID 0x20001927
+
+#define RP1_PLATFORM_ASIC BIT(1)
+#define RP1_PLATFORM_FPGA BIT(0)
+
+void rp1_get_platform(u32 *chip_id, u32 *platform);
+
+#endif
diff --git a/include/linux/usb.h b/include/linux/usb.h
index e85105939af8..d5e2010c47ea 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -5,23 +5,22 @@
#include <linux/mod_devicetable.h>
#include <linux/usb/ch9.h>
-#define USB_MAJOR 180
-#define USB_DEVICE_MAJOR 189
-
+#define USB_MAJOR 180
+#define USB_DEVICE_MAJOR 189
#ifdef __KERNEL__
-#include <linux/errno.h> /* for -ENODEV */
-#include <linux/delay.h> /* for mdelay() */
-#include <linux/interrupt.h> /* for in_interrupt() */
-#include <linux/list.h> /* for struct list_head */
-#include <linux/kref.h> /* for struct kref */
-#include <linux/device.h> /* for struct device */
-#include <linux/fs.h> /* for struct file_operations */
-#include <linux/completion.h> /* for struct completion */
-#include <linux/sched.h> /* for current && schedule_timeout */
-#include <linux/mutex.h> /* for struct mutex */
-#include <linux/pm_runtime.h> /* for runtime PM */
+#include <linux/errno.h> /* for -ENODEV */
+#include <linux/delay.h> /* for mdelay() */
+#include <linux/interrupt.h> /* for in_interrupt() */
+#include <linux/list.h> /* for struct list_head */
+#include <linux/kref.h> /* for struct kref */
+#include <linux/device.h> /* for struct device */
+#include <linux/fs.h> /* for struct file_operations */
+#include <linux/completion.h> /* for struct completion */
+#include <linux/sched.h> /* for current && schedule_timeout */
+#include <linux/mutex.h> /* for struct mutex */
+#include <linux/pm_runtime.h> /* for runtime PM */
struct usb_device;
struct usb_driver;
@@ -73,7 +72,7 @@ struct usb_host_endpoint {
void *hcpriv;
struct ep_device *ep_dev; /* For sysfs info */
- unsigned char *extra; /* Extra descriptors */
+ unsigned char *extra; /* Extra descriptors */
int extralen;
int enabled;
int streams;
@@ -81,17 +80,17 @@ struct usb_host_endpoint {
/* host-side wrapper for one interface setting's parsed descriptors */
struct usb_host_interface {
- struct usb_interface_descriptor desc;
+ struct usb_interface_descriptor desc;
int extralen;
- unsigned char *extra; /* Extra descriptors */
+ unsigned char *extra; /* Extra descriptors */
/* array of desc.bNumEndpoints endpoints associated with this
* interface setting. these will be in no particular order.
*/
struct usb_host_endpoint *endpoint;
- char *string; /* iInterface string, if present */
+ char *string; /* iInterface string, if present */
};
enum usb_interface_condition {
@@ -103,72 +102,73 @@ enum usb_interface_condition {
int __must_check
usb_find_common_endpoints(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **bulk_in,
- struct usb_endpoint_descriptor **bulk_out,
- struct usb_endpoint_descriptor **int_in,
- struct usb_endpoint_descriptor **int_out);
+ struct usb_endpoint_descriptor **bulk_in,
+ struct usb_endpoint_descriptor **bulk_out,
+ struct usb_endpoint_descriptor **int_in,
+ struct usb_endpoint_descriptor **int_out);
int __must_check
usb_find_common_endpoints_reverse(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **bulk_in,
- struct usb_endpoint_descriptor **bulk_out,
- struct usb_endpoint_descriptor **int_in,
- struct usb_endpoint_descriptor **int_out);
+ struct usb_endpoint_descriptor **bulk_in,
+ struct usb_endpoint_descriptor **bulk_out,
+ struct usb_endpoint_descriptor **int_in,
+ struct usb_endpoint_descriptor **int_out);
static inline int __must_check
usb_find_bulk_in_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **bulk_in)
+ struct usb_endpoint_descriptor **bulk_in)
{
return usb_find_common_endpoints(alt, bulk_in, NULL, NULL, NULL);
}
static inline int __must_check
usb_find_bulk_out_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **bulk_out)
+ struct usb_endpoint_descriptor **bulk_out)
{
return usb_find_common_endpoints(alt, NULL, bulk_out, NULL, NULL);
}
-static inline int __must_check
-usb_find_int_in_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **int_in)
+static inline int __must_check usb_find_int_in_endpoint(
+ struct usb_host_interface *alt, struct usb_endpoint_descriptor **int_in)
{
return usb_find_common_endpoints(alt, NULL, NULL, int_in, NULL);
}
static inline int __must_check
usb_find_int_out_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **int_out)
+ struct usb_endpoint_descriptor **int_out)
{
return usb_find_common_endpoints(alt, NULL, NULL, NULL, int_out);
}
static inline int __must_check
usb_find_last_bulk_in_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **bulk_in)
+ struct usb_endpoint_descriptor **bulk_in)
{
- return usb_find_common_endpoints_reverse(alt, bulk_in, NULL, NULL, NULL);
+ return usb_find_common_endpoints_reverse(alt, bulk_in, NULL, NULL,
+ NULL);
}
static inline int __must_check
usb_find_last_bulk_out_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **bulk_out)
+ struct usb_endpoint_descriptor **bulk_out)
{
- return usb_find_common_endpoints_reverse(alt, NULL, bulk_out, NULL, NULL);
+ return usb_find_common_endpoints_reverse(alt, NULL, bulk_out, NULL,
+ NULL);
}
-static inline int __must_check
-usb_find_last_int_in_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **int_in)
+static inline int __must_check usb_find_last_int_in_endpoint(
+ struct usb_host_interface *alt, struct usb_endpoint_descriptor **int_in)
{
return usb_find_common_endpoints_reverse(alt, NULL, NULL, int_in, NULL);
}
static inline int __must_check
usb_find_last_int_out_endpoint(struct usb_host_interface *alt,
- struct usb_endpoint_descriptor **int_out)
+ struct usb_endpoint_descriptor **int_out)
{
- return usb_find_common_endpoints_reverse(alt, NULL, NULL, NULL, int_out);
+ return usb_find_common_endpoints_reverse(alt, NULL, NULL, NULL,
+ int_out);
}
enum usb_wireless_status {
@@ -245,34 +245,35 @@ struct usb_interface {
* stored in no particular order */
struct usb_host_interface *altsetting;
- struct usb_host_interface *cur_altsetting; /* the currently
+ struct usb_host_interface *cur_altsetting; /* the currently
* active alternate setting */
- unsigned num_altsetting; /* number of alternate settings */
+ unsigned num_altsetting; /* number of alternate settings */
/* If there is an interface association descriptor then it will list
* the associated interfaces */
struct usb_interface_assoc_descriptor *intf_assoc;
- int minor; /* minor number this interface is
+ int minor; /* minor number this interface is
* bound to */
- enum usb_interface_condition condition; /* state of binding */
- unsigned sysfs_files_created:1; /* the sysfs attributes exist */
- unsigned ep_devs_created:1; /* endpoint "devices" exist */
- unsigned unregistering:1; /* unregistration is in progress */
- unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
- unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
- unsigned needs_binding:1; /* needs delayed unbind/rebind */
- unsigned resetting_device:1; /* true: bandwidth alloc after reset */
- unsigned authorized:1; /* used for interface authorization */
+ enum usb_interface_condition condition; /* state of binding */
+ unsigned sysfs_files_created : 1; /* the sysfs attributes exist */
+ unsigned ep_devs_created : 1; /* endpoint "devices" exist */
+ unsigned unregistering : 1; /* unregistration is in progress */
+ unsigned needs_remote_wakeup : 1; /* driver requires remote wakeup */
+ unsigned needs_altsetting0 : 1; /* switch to altsetting 0 is pending */
+ unsigned needs_binding : 1; /* needs delayed unbind/rebind */
+ unsigned resetting_device : 1; /* true: bandwidth alloc after reset */
+ unsigned authorized : 1; /* used for interface authorization */
enum usb_wireless_status wireless_status;
struct work_struct wireless_status_work;
- struct device dev; /* interface specific device info */
+ struct device dev; /* interface specific device info */
struct device *usb_dev;
- struct work_struct reset_ws; /* for resets in atomic context */
+ struct work_struct reset_ws; /* for resets in atomic context */
};
-#define to_usb_interface(__dev) container_of_const(__dev, struct usb_interface, dev)
+#define to_usb_interface(__dev) \
+ container_of_const(__dev, struct usb_interface, dev)
static inline void *usb_get_intfdata(struct usb_interface *intf)
{
@@ -299,15 +300,15 @@ struct usb_interface *usb_get_intf(struct usb_interface *intf);
void usb_put_intf(struct usb_interface *intf);
/* Hard limit */
-#define USB_MAXENDPOINTS 30
+#define USB_MAXENDPOINTS 30
/* this maximum is arbitrary */
-#define USB_MAXINTERFACES 32
-#define USB_MAXIADS (USB_MAXINTERFACES/2)
+#define USB_MAXINTERFACES 32
+#define USB_MAXIADS (USB_MAXINTERFACES / 2)
-bool usb_check_bulk_endpoints(
- const struct usb_interface *intf, const u8 *ep_addrs);
-bool usb_check_int_endpoints(
- const struct usb_interface *intf, const u8 *ep_addrs);
+bool usb_check_bulk_endpoints(const struct usb_interface *intf,
+ const u8 *ep_addrs);
+bool usb_check_int_endpoints(const struct usb_interface *intf,
+ const u8 *ep_addrs);
/*
* USB Resume Timer: Every Host controller driver should drive the resume
@@ -333,7 +334,7 @@ bool usb_check_int_endpoints(
* should cope with both LPJ calibration errors and devices not following every
* detail of the USB Specification.
*/
-#define USB_RESUME_TIMEOUT 40 /* ms */
+#define USB_RESUME_TIMEOUT 40 /* ms */
/**
* struct usb_interface_cache - long-term representation of a device interface
@@ -350,17 +351,17 @@ bool usb_check_int_endpoints(
* providing support for the /sys/kernel/debug/usb/devices pseudo-file.
*/
struct usb_interface_cache {
- unsigned num_altsetting; /* number of alternate settings */
- struct kref ref; /* reference counter */
+ unsigned num_altsetting; /* number of alternate settings */
+ struct kref ref; /* reference counter */
/* variable-length array of alternate settings for this interface,
* stored in no particular order */
struct usb_host_interface altsetting[];
};
-#define ref_to_usb_interface_cache(r) \
- container_of(r, struct usb_interface_cache, ref)
-#define altsetting_to_usb_interface_cache(a) \
- container_of(a, struct usb_interface_cache, altsetting[0])
+#define ref_to_usb_interface_cache(r) \
+ container_of(r, struct usb_interface_cache, ref)
+#define altsetting_to_usb_interface_cache(a) \
+ container_of(a, struct usb_interface_cache, altsetting[0])
/**
* struct usb_host_config - representation of a device's configuration
@@ -402,9 +403,9 @@ struct usb_interface_cache {
* all its interfaces.
*/
struct usb_host_config {
- struct usb_config_descriptor desc;
+ struct usb_config_descriptor desc;
- char *string; /* iConfiguration string, if present */
+ char *string; /* iConfiguration string, if present */
/* List of any Interface Association Descriptors in this
* configuration. */
@@ -418,27 +419,26 @@ struct usb_host_config {
* active configuration */
struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
- unsigned char *extra; /* Extra descriptors */
+ unsigned char *extra; /* Extra descriptors */
int extralen;
};
/* USB2.0 and USB3.0 device BOS descriptor set */
struct usb_host_bos {
- struct usb_bos_descriptor *desc;
+ struct usb_bos_descriptor *desc;
- struct usb_ext_cap_descriptor *ext_cap;
- struct usb_ss_cap_descriptor *ss_cap;
- struct usb_ssp_cap_descriptor *ssp_cap;
- struct usb_ss_container_id_descriptor *ss_id;
- struct usb_ptm_cap_descriptor *ptm_cap;
+ struct usb_ext_cap_descriptor *ext_cap;
+ struct usb_ss_cap_descriptor *ss_cap;
+ struct usb_ssp_cap_descriptor *ssp_cap;
+ struct usb_ss_container_id_descriptor *ss_id;
+ struct usb_ptm_cap_descriptor *ptm_cap;
};
-int __usb_get_extra_descriptor(char *buffer, unsigned size,
- unsigned char type, void **ptr, size_t min);
-#define usb_get_extra_descriptor(ifpoint, type, ptr) \
- __usb_get_extra_descriptor((ifpoint)->extra, \
- (ifpoint)->extralen, \
- type, (void **)ptr, sizeof(**(ptr)))
+int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type,
+ void **ptr, size_t min);
+#define usb_get_extra_descriptor(ifpoint, type, ptr) \
+ __usb_get_extra_descriptor((ifpoint)->extra, (ifpoint)->extralen, \
+ type, (void **)ptr, sizeof(**(ptr)))
/* ----------------------------------------------------------------------- */
@@ -446,48 +446,48 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
* Allocated per bus (tree of devices) we have:
*/
struct usb_bus {
- struct device *controller; /* host side hardware */
- struct device *sysdev; /* as seen from firmware or bus */
- int busnum; /* Bus number (in order of reg) */
- const char *bus_name; /* stable id (PCI slot_name etc) */
- u8 uses_pio_for_control; /*
+ struct device *controller; /* host side hardware */
+ struct device *sysdev; /* as seen from firmware or bus */
+ int busnum; /* Bus number (in order of reg) */
+ const char *bus_name; /* stable id (PCI slot_name etc) */
+ u8 uses_pio_for_control; /*
* Does the host controller use PIO
* for control transfers?
*/
- u8 otg_port; /* 0, or number of OTG/HNP port */
- unsigned is_b_host:1; /* true during some HNP roleswitches */
- unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
- unsigned no_stop_on_short:1; /*
+ u8 otg_port; /* 0, or number of OTG/HNP port */
+ unsigned is_b_host : 1; /* true during some HNP roleswitches */
+ unsigned b_hnp_enable : 1; /* OTG: did A-Host enable HNP? */
+ unsigned no_stop_on_short : 1; /*
* Quirk: some controllers don't stop
* the ep queue on a short transfer
* with the URB_SHORT_NOT_OK flag set.
*/
- unsigned no_sg_constraint:1; /* no sg constraint */
- unsigned sg_tablesize; /* 0 or largest number of sg list entries */
+ unsigned no_sg_constraint : 1; /* no sg constraint */
+ unsigned sg_tablesize; /* 0 or largest number of sg list entries */
- int devnum_next; /* Next open device number in
+ int devnum_next; /* Next open device number in
* round-robin allocation */
struct mutex devnum_next_mutex; /* devnum_next mutex */
- DECLARE_BITMAP(devmap, 128); /* USB device number allocation bitmap */
- struct usb_device *root_hub; /* Root hub */
- struct usb_bus *hs_companion; /* Companion EHCI bus, if any */
+ DECLARE_BITMAP(devmap, 128); /* USB device number allocation bitmap */
+ struct usb_device *root_hub; /* Root hub */
+ struct usb_bus *hs_companion; /* Companion EHCI bus, if any */
- int bandwidth_allocated; /* on this bus: how much of the time
+ int bandwidth_allocated; /* on this bus: how much of the time
* reserved for periodic (intr/iso)
* requests is used, on average?
* Units: microseconds/frame.
* Limits: Full/low speed reserve 90%,
* while high speed reserves 80%.
*/
- int bandwidth_int_reqs; /* number of Interrupt requests */
- int bandwidth_isoc_reqs; /* number of Isoc. requests */
+ int bandwidth_int_reqs; /* number of Interrupt requests */
+ int bandwidth_isoc_reqs; /* number of Isoc. requests */
- unsigned resuming_ports; /* bit array: resuming root-hub ports */
+ unsigned resuming_ports; /* bit array: resuming root-hub ports */
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
- struct mon_bus *mon_bus; /* non-null when associated */
- int monitored; /* non-zero when monitored */
+ struct mon_bus *mon_bus; /* non-null when associated */
+ int monitored; /* non-zero when monitored */
#endif
};
@@ -515,10 +515,10 @@ enum usb_port_connect_type {
*/
/* For the given port, prefer the old (faster) enumeration scheme. */
-#define USB_PORT_QUIRK_OLD_SCHEME BIT(0)
+#define USB_PORT_QUIRK_OLD_SCHEME BIT(0)
/* Decrease TRSTRCY to 10ms during device enumeration. */
-#define USB_PORT_QUIRK_FAST_ENUM BIT(1)
+#define USB_PORT_QUIRK_FAST_ENUM BIT(1)
/*
* USB 2.0 Link Power Management (LPM) parameters.
@@ -656,17 +656,17 @@ struct usb3_lpm_parameters {
* usb_set_device_state().
*/
struct usb_device {
- int devnum;
- char devpath[16];
- u32 route;
- enum usb_device_state state;
- enum usb_device_speed speed;
- unsigned int rx_lanes;
- unsigned int tx_lanes;
- enum usb_ssp_rate ssp_rate;
+ int devnum;
+ char devpath[16];
+ u32 route;
+ enum usb_device_state state;
+ enum usb_device_speed speed;
+ unsigned int rx_lanes;
+ unsigned int tx_lanes;
+ enum usb_ssp_rate ssp_rate;
- struct usb_tt *tt;
- int ttport;
+ struct usb_tt *tt;
+ int ttport;
unsigned int toggle[2];
@@ -691,20 +691,20 @@ struct usb_device {
u8 level;
u8 devaddr;
- unsigned can_submit:1;
- unsigned persist_enabled:1;
- unsigned reset_in_progress:1;
- unsigned have_langid:1;
- unsigned authorized:1;
- unsigned authenticated:1;
- unsigned lpm_capable:1;
- unsigned lpm_devinit_allow:1;
- unsigned usb2_hw_lpm_capable:1;
- unsigned usb2_hw_lpm_besl_capable:1;
- unsigned usb2_hw_lpm_enabled:1;
- unsigned usb2_hw_lpm_allowed:1;
- unsigned usb3_lpm_u1_enabled:1;
- unsigned usb3_lpm_u2_enabled:1;
+ unsigned can_submit : 1;
+ unsigned persist_enabled : 1;
+ unsigned reset_in_progress : 1;
+ unsigned have_langid : 1;
+ unsigned authorized : 1;
+ unsigned authenticated : 1;
+ unsigned lpm_capable : 1;
+ unsigned lpm_devinit_allow : 1;
+ unsigned usb2_hw_lpm_capable : 1;
+ unsigned usb2_hw_lpm_besl_capable : 1;
+ unsigned usb2_hw_lpm_enabled : 1;
+ unsigned usb2_hw_lpm_allowed : 1;
+ unsigned usb3_lpm_u1_enabled : 1;
+ unsigned usb3_lpm_u2_enabled : 1;
int string_langid;
/* static strings from the device */
@@ -738,21 +738,22 @@ struct usb_device {
unsigned lpm_disable_count;
u16 hub_delay;
- unsigned use_generic_driver:1;
+ unsigned use_generic_driver : 1;
};
-#define to_usb_device(__dev) container_of_const(__dev, struct usb_device, dev)
+#define to_usb_device(__dev) container_of_const(__dev, struct usb_device, dev)
static inline struct usb_device *__intf_to_usbdev(struct usb_interface *intf)
{
return to_usb_device(intf->dev.parent);
}
-static inline const struct usb_device *__intf_to_usbdev_const(const struct usb_interface *intf)
+static inline const struct usb_device *
+__intf_to_usbdev_const(const struct usb_interface *intf)
{
return to_usb_device((const struct device *)intf->dev.parent);
}
-#define interface_to_usbdev(intf) \
+#define interface_to_usbdev(intf) \
_Generic((intf), \
const struct usb_interface *: __intf_to_usbdev_const, \
struct usb_interface *: __intf_to_usbdev)(intf)
@@ -760,7 +761,7 @@ static inline const struct usb_device *__intf_to_usbdev_const(const struct usb_i
extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_dev(struct usb_device *dev);
extern struct usb_device *usb_hub_find_child(struct usb_device *hdev,
- int port1);
+ int port1);
/**
* usb_hub_for_each_child - iterate over all child devices on the hub
@@ -768,17 +769,20 @@ extern struct usb_device *usb_hub_find_child(struct usb_device *hdev,
* @port1: portnum associated with child device
* @child: child device pointer
*/
-#define usb_hub_for_each_child(hdev, port1, child) \
- for (port1 = 1, child = usb_hub_find_child(hdev, port1); \
- port1 <= hdev->maxchild; \
- child = usb_hub_find_child(hdev, ++port1)) \
- if (!child) continue; else
+#define usb_hub_for_each_child(hdev, port1, child) \
+ for (port1 = 1, child = usb_hub_find_child(hdev, port1); \
+ port1 <= hdev->maxchild; \
+ child = usb_hub_find_child(hdev, ++port1)) \
+ if (!child) \
+ continue; \
+ else
/* USB device locking */
-#define usb_lock_device(udev) device_lock(&(udev)->dev)
-#define usb_unlock_device(udev) device_unlock(&(udev)->dev)
-#define usb_lock_device_interruptible(udev) device_lock_interruptible(&(udev)->dev)
-#define usb_trylock_device(udev) device_trylock(&(udev)->dev)
+#define usb_lock_device(udev) device_lock(&(udev)->dev)
+#define usb_unlock_device(udev) device_unlock(&(udev)->dev)
+#define usb_lock_device_interruptible(udev) \
+ device_lock_interruptible(&(udev)->dev)
+#define usb_trylock_device(udev) device_trylock(&(udev)->dev)
extern int usb_lock_device_for_reset(struct usb_device *udev,
const struct usb_interface *iface);
@@ -790,16 +794,24 @@ extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
#ifdef CONFIG_ACPI
extern int usb_acpi_set_power_state(struct usb_device *hdev, int index,
- bool enable);
+ bool enable);
extern bool usb_acpi_power_manageable(struct usb_device *hdev, int index);
extern int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index);
#else
static inline int usb_acpi_set_power_state(struct usb_device *hdev, int index,
- bool enable) { return 0; }
+ bool enable)
+{
+ return 0;
+}
static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
- { return true; }
-static inline int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
- { return 0; }
+{
+ return true;
+}
+static inline int usb_acpi_port_lpm_incapable(struct usb_device *hdev,
+ int index)
+{
+ return 0;
+}
#endif
/* USB autosuspend and autoresume */
@@ -827,22 +839,31 @@ static inline void usb_disable_autosuspend(struct usb_device *udev)
{ }
static inline int usb_autopm_get_interface(struct usb_interface *intf)
-{ return 0; }
+{
+ return 0;
+}
static inline int usb_autopm_get_interface_async(struct usb_interface *intf)
-{ return 0; }
+{
+ return 0;
+}
static inline void usb_autopm_put_interface(struct usb_interface *intf)
-{ }
+{
+}
static inline void usb_autopm_put_interface_async(struct usb_interface *intf)
-{ }
-static inline void usb_autopm_get_interface_no_resume(
- struct usb_interface *intf)
-{ }
-static inline void usb_autopm_put_interface_no_suspend(
- struct usb_interface *intf)
-{ }
+{
+}
+static inline void
+usb_autopm_get_interface_no_resume(struct usb_interface *intf)
+{
+}
+static inline void
+usb_autopm_put_interface_no_suspend(struct usb_interface *intf)
+{
+}
static inline void usb_mark_last_busy(struct usb_device *udev)
-{ }
+{
+}
#endif
#if IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND)
@@ -880,7 +901,6 @@ static inline bool usb_device_no_sg_constraint(struct usb_device *udev)
return udev && udev->bus && udev->bus->no_sg_constraint;
}
-
/*-------------------------------------------------------------------------*/
/* for drivers using iso endpoints */
@@ -888,17 +908,18 @@ extern int usb_get_current_frame_number(struct usb_device *usb_dev);
/* Sets up a group of bulk endpoints to support multiple stream IDs. */
extern int usb_alloc_streams(struct usb_interface *interface,
- struct usb_host_endpoint **eps, unsigned int num_eps,
- unsigned int num_streams, gfp_t mem_flags);
+ struct usb_host_endpoint **eps,
+ unsigned int num_eps, unsigned int num_streams,
+ gfp_t mem_flags);
/* Reverts a group of bulk endpoints back to not using stream IDs. */
extern int usb_free_streams(struct usb_interface *interface,
- struct usb_host_endpoint **eps, unsigned int num_eps,
- gfp_t mem_flags);
+ struct usb_host_endpoint **eps,
+ unsigned int num_eps, gfp_t mem_flags);
/* used these for multi-interface device registration */
extern int usb_driver_claim_interface(struct usb_driver *driver,
- struct usb_interface *iface, void *data);
+ struct usb_interface *iface, void *data);
/**
* usb_interface_claimed - returns true iff an interface is claimed
@@ -919,10 +940,10 @@ static inline int usb_interface_claimed(struct usb_interface *iface)
}
extern void usb_driver_release_interface(struct usb_driver *driver,
- struct usb_interface *iface);
+ struct usb_interface *iface);
int usb_set_wireless_status(struct usb_interface *iface,
- enum usb_wireless_status status);
+ enum usb_wireless_status status);
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
const struct usb_device_id *id);
@@ -931,21 +952,20 @@ extern int usb_match_one_id(struct usb_interface *interface,
extern int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *));
extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
- int minor);
+ int minor);
extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
- unsigned ifnum);
-extern struct usb_host_interface *usb_altnum_to_altsetting(
- const struct usb_interface *intf, unsigned int altnum);
-extern struct usb_host_interface *usb_find_alt_setting(
- struct usb_host_config *config,
- unsigned int iface_num,
- unsigned int alt_num);
+ unsigned ifnum);
+extern struct usb_host_interface *
+usb_altnum_to_altsetting(const struct usb_interface *intf, unsigned int altnum);
+extern struct usb_host_interface *
+usb_find_alt_setting(struct usb_host_config *config, unsigned int iface_num,
+ unsigned int alt_num);
/* port claiming functions */
int usb_hub_claim_port(struct usb_device *hdev, unsigned port1,
- struct usb_dev_state *owner);
+ struct usb_dev_state *owner);
int usb_hub_release_port(struct usb_device *hdev, unsigned port1,
- struct usb_dev_state *owner);
+ struct usb_dev_state *owner);
/**
* usb_make_path - returns stable device path in the usb tree
@@ -983,19 +1003,17 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
/*-------------------------------------------------------------------------*/
#define USB_DEVICE_ID_MATCH_DEVICE \
- (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
+ (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
#define USB_DEVICE_ID_MATCH_DEV_RANGE \
- (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
+ (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
- (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
-#define USB_DEVICE_ID_MATCH_DEV_INFO \
- (USB_DEVICE_ID_MATCH_DEV_CLASS | \
- USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
- USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
-#define USB_DEVICE_ID_MATCH_INT_INFO \
- (USB_DEVICE_ID_MATCH_INT_CLASS | \
- USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
- USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+ (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
+#define USB_DEVICE_ID_MATCH_DEV_INFO \
+ (USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
+ USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+#define USB_DEVICE_ID_MATCH_INT_INFO \
+ (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL)
/**
* USB_DEVICE - macro used to describe a specific usb device
@@ -1005,9 +1023,8 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This macro is used to create a struct usb_device_id that matches a
* specific device.
*/
-#define USB_DEVICE(vend, prod) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
- .idVendor = (vend), \
+#define USB_DEVICE(vend, prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
.idProduct = (prod)
/**
* USB_DEVICE_VER - describe a specific usb device with a version range
@@ -1019,11 +1036,9 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This macro is used to create a struct usb_device_id that matches a
* specific device, with a version range.
*/
-#define USB_DEVICE_VER(vend, prod, lo, hi) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
- .idVendor = (vend), \
- .idProduct = (prod), \
- .bcdDevice_lo = (lo), \
+#define USB_DEVICE_VER(vend, prod, lo, hi) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
+ .idVendor = (vend), .idProduct = (prod), .bcdDevice_lo = (lo), \
.bcdDevice_hi = (hi)
/**
@@ -1035,12 +1050,10 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This macro is used to create a struct usb_device_id that matches a
* specific interface class of devices.
*/
-#define USB_DEVICE_INTERFACE_CLASS(vend, prod, cl) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+#define USB_DEVICE_INTERFACE_CLASS(vend, prod, cl) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS, \
- .idVendor = (vend), \
- .idProduct = (prod), \
- .bInterfaceClass = (cl)
+ .idVendor = (vend), .idProduct = (prod), .bInterfaceClass = (cl)
/**
* USB_DEVICE_INTERFACE_PROTOCOL - describe a usb device with a specific interface protocol
@@ -1051,12 +1064,10 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This macro is used to create a struct usb_device_id that matches a
* specific interface protocol of devices.
*/
-#define USB_DEVICE_INTERFACE_PROTOCOL(vend, prod, pr) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+#define USB_DEVICE_INTERFACE_PROTOCOL(vend, prod, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
- .idVendor = (vend), \
- .idProduct = (prod), \
- .bInterfaceProtocol = (pr)
+ .idVendor = (vend), .idProduct = (prod), .bInterfaceProtocol = (pr)
/**
* USB_DEVICE_INTERFACE_NUMBER - describe a usb device with a specific interface number
@@ -1067,12 +1078,10 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This macro is used to create a struct usb_device_id that matches a
* specific interface number of devices.
*/
-#define USB_DEVICE_INTERFACE_NUMBER(vend, prod, num) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+#define USB_DEVICE_INTERFACE_NUMBER(vend, prod, num) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_NUMBER, \
- .idVendor = (vend), \
- .idProduct = (prod), \
- .bInterfaceNumber = (num)
+ .idVendor = (vend), .idProduct = (prod), .bInterfaceNumber = (num)
/**
* USB_DEVICE_INFO - macro used to describe a class of usb devices
@@ -1083,11 +1092,9 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This macro is used to create a struct usb_device_id that matches a
* specific class of devices.
*/
-#define USB_DEVICE_INFO(cl, sc, pr) \
- .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, \
- .bDeviceClass = (cl), \
- .bDeviceSubClass = (sc), \
- .bDeviceProtocol = (pr)
+#define USB_DEVICE_INFO(cl, sc, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \
+ .bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
/**
* USB_INTERFACE_INFO - macro used to describe a class of usb interfaces
@@ -1098,11 +1105,9 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This macro is used to create a struct usb_device_id that matches a
* specific class of interfaces.
*/
-#define USB_INTERFACE_INFO(cl, sc, pr) \
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \
- .bInterfaceClass = (cl), \
- .bInterfaceSubClass = (sc), \
- .bInterfaceProtocol = (pr)
+#define USB_INTERFACE_INFO(cl, sc, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
/**
* USB_DEVICE_AND_INTERFACE_INFO - describe a specific usb device with a class of usb interfaces
@@ -1118,14 +1123,11 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* This is especially useful when explicitly matching devices that have
* vendor specific bDeviceClass values, but standards-compliant interfaces.
*/
-#define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, cl, sc, pr) \
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
- | USB_DEVICE_ID_MATCH_DEVICE, \
- .idVendor = (vend), \
- .idProduct = (prod), \
- .bInterfaceClass = (cl), \
- .bInterfaceSubClass = (sc), \
- .bInterfaceProtocol = (pr)
+#define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, cl, sc, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | \
+ USB_DEVICE_ID_MATCH_DEVICE, \
+ .idVendor = (vend), .idProduct = (prod), .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
/**
* USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces
@@ -1141,12 +1143,10 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
* vendor specific bDeviceClass values, but standards-compliant interfaces.
*/
#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
- | USB_DEVICE_ID_MATCH_VENDOR, \
- .idVendor = (vend), \
- .bInterfaceClass = (cl), \
- .bInterfaceSubClass = (sc), \
- .bInterfaceProtocol = (pr)
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | \
+ USB_DEVICE_ID_MATCH_VENDOR, \
+ .idVendor = (vend), .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
/* ----------------------------------------------------------------------- */
@@ -1163,8 +1163,8 @@ struct usb_dynid {
extern ssize_t usb_store_new_id(struct usb_dynids *dynids,
const struct usb_device_id *id_table,
- struct device_driver *driver,
- const char *buf, size_t count);
+ struct device_driver *driver, const char *buf,
+ size_t count);
extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);
@@ -1238,16 +1238,16 @@ extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);
struct usb_driver {
const char *name;
- int (*probe) (struct usb_interface *intf,
- const struct usb_device_id *id);
+ int (*probe)(struct usb_interface *intf,
+ const struct usb_device_id *id);
- void (*disconnect) (struct usb_interface *intf);
+ void (*disconnect)(struct usb_interface *intf);
- int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
- void *buf);
+ int (*unlocked_ioctl)(struct usb_interface *intf, unsigned int code,
+ void *buf);
- int (*suspend) (struct usb_interface *intf, pm_message_t message);
- int (*resume) (struct usb_interface *intf);
+ int (*suspend)(struct usb_interface *intf, pm_message_t message);
+ int (*resume)(struct usb_interface *intf);
int (*reset_resume)(struct usb_interface *intf);
int (*pre_reset)(struct usb_interface *intf);
@@ -1260,12 +1260,12 @@ struct usb_driver {
struct usb_dynids dynids;
struct device_driver driver;
- unsigned int no_dynamic_id:1;
- unsigned int supports_autosuspend:1;
- unsigned int disable_hub_initiated_lpm:1;
- unsigned int soft_unbind:1;
+ unsigned int no_dynamic_id : 1;
+ unsigned int supports_autosuspend : 1;
+ unsigned int disable_hub_initiated_lpm : 1;
+ unsigned int soft_unbind : 1;
};
-#define to_usb_driver(d) container_of_const(d, struct usb_driver, driver)
+#define to_usb_driver(d) container_of_const(d, struct usb_driver, driver)
/**
* struct usb_device_driver - identifies USB device driver to usbcore
@@ -1301,22 +1301,23 @@ struct usb_driver {
struct usb_device_driver {
const char *name;
- bool (*match) (struct usb_device *udev);
- int (*probe) (struct usb_device *udev);
- void (*disconnect) (struct usb_device *udev);
+ bool (*match)(struct usb_device *udev);
+ int (*probe)(struct usb_device *udev);
+ void (*disconnect)(struct usb_device *udev);
- int (*suspend) (struct usb_device *udev, pm_message_t message);
- int (*resume) (struct usb_device *udev, pm_message_t message);
+ int (*suspend)(struct usb_device *udev, pm_message_t message);
+ int (*resume)(struct usb_device *udev, pm_message_t message);
- int (*choose_configuration) (struct usb_device *udev);
+ int (*choose_configuration)(struct usb_device *udev);
const struct attribute_group **dev_groups;
struct device_driver driver;
const struct usb_device_id *id_table;
- unsigned int supports_autosuspend:1;
- unsigned int generic_subclass:1;
+ unsigned int supports_autosuspend : 1;
+ unsigned int generic_subclass : 1;
};
-#define to_usb_device_driver(d) container_of_const(d, struct usb_device_driver, driver)
+#define to_usb_device_driver(d) \
+ container_of_const(d, struct usb_device_driver, driver)
/**
* struct usb_class_driver - identifies a USB driver that wants to use the USB major number
@@ -1359,11 +1360,10 @@ extern void usb_deregister(struct usb_driver *);
* use this macro once, and calling it replaces module_init() and module_exit()
*/
#define module_usb_driver(__usb_driver) \
- module_driver(__usb_driver, usb_register, \
- usb_deregister)
+ module_driver(__usb_driver, usb_register, usb_deregister)
extern int usb_register_device_driver(struct usb_device_driver *,
- struct module *);
+ struct module *);
extern void usb_deregister_device_driver(struct usb_device_driver *);
extern int usb_register_dev(struct usb_interface *intf,
@@ -1384,32 +1384,34 @@ extern int usb_disabled(void);
*
* Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
*/
-#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
-#define URB_ISO_ASAP 0x0002 /* iso-only; use the first unexpired
+#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
+#define URB_ISO_ASAP \
+ 0x0002 /* iso-only; use the first unexpired
* slot in the schedule */
-#define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */
-#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
-#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt
+#define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */
+#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
+#define URB_NO_INTERRUPT \
+ 0x0080 /* HINT: no non-error interrupt
* needed */
-#define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */
+#define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */
/* The following flags are used internally by usbcore and HCDs */
-#define URB_DIR_IN 0x0200 /* Transfer from device to host */
-#define URB_DIR_OUT 0
-#define URB_DIR_MASK URB_DIR_IN
+#define URB_DIR_IN 0x0200 /* Transfer from device to host */
+#define URB_DIR_OUT 0
+#define URB_DIR_MASK URB_DIR_IN
-#define URB_DMA_MAP_SINGLE 0x00010000 /* Non-scatter-gather mapping */
-#define URB_DMA_MAP_PAGE 0x00020000 /* HCD-unsupported S-G */
-#define URB_DMA_MAP_SG 0x00040000 /* HCD-supported S-G */
-#define URB_MAP_LOCAL 0x00080000 /* HCD-local-memory mapping */
-#define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */
-#define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */
-#define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */
-#define URB_ALIGNED_TEMP_BUFFER 0x00800000 /* Temp buffer was alloc'd */
+#define URB_DMA_MAP_SINGLE 0x00010000 /* Non-scatter-gather mapping */
+#define URB_DMA_MAP_PAGE 0x00020000 /* HCD-unsupported S-G */
+#define URB_DMA_MAP_SG 0x00040000 /* HCD-supported S-G */
+#define URB_MAP_LOCAL 0x00080000 /* HCD-local-memory mapping */
+#define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */
+#define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */
+#define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */
+#define URB_ALIGNED_TEMP_BUFFER 0x00800000 /* Temp buffer was alloc'd */
struct usb_iso_packet_descriptor {
unsigned int offset;
- unsigned int length; /* expected length */
+ unsigned int length; /* expected length */
unsigned int actual_length;
int status;
};
@@ -1421,7 +1423,7 @@ struct usb_anchor {
wait_queue_head_t wait;
spinlock_t lock;
atomic_t suspend_wakeups;
- unsigned int poisoned:1;
+ unsigned int poisoned : 1;
};
static inline void init_usb_anchor(struct usb_anchor *anchor)
@@ -1623,16 +1625,16 @@ typedef void (*usb_complete_t)(struct urb *);
*/
struct urb {
/* private: usb core and host controller only fields in the urb */
- struct kref kref; /* reference count of the URB */
- int unlinked; /* unlink error code */
- void *hcpriv; /* private data for host controller */
- atomic_t use_count; /* concurrent submissions counter */
- atomic_t reject; /* submissions will fail */
+ struct kref kref; /* reference count of the URB */
+ int unlinked; /* unlink error code */
+ void *hcpriv; /* private data for host controller */
+ atomic_t use_count; /* concurrent submissions counter */
+ atomic_t reject; /* submissions will fail */
/* public: documented fields in the urb that can be used by drivers */
- struct list_head urb_list; /* list head for use by the urb's
+ struct list_head urb_list; /* list head for use by the urb's
* current owner */
- struct list_head anchor_list; /* the URB may be anchored */
+ struct list_head anchor_list; /* the URB may be anchored */
struct usb_anchor *anchor;
struct usb_device *dev; /* (in) pointer to associated device */
struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
@@ -1654,11 +1656,11 @@ struct urb {
int number_of_packets; /* (in) number of ISO packets */
int interval; /* (modify) transfer interval
* (INT/ISO) */
- int error_count; /* (return) number of ISO errors */
- void *context; /* (in) context for completion */
- usb_complete_t complete; /* (in) completion routine */
+ int error_count; /* (return) number of ISO errors */
+ void *context; /* (in) context for completion */
+ usb_complete_t complete; /* (in) completion routine */
struct usb_iso_packet_descriptor iso_frame_desc[];
- /* (in) ISO ONLY */
+ /* (in) ISO ONLY */
};
/* ----------------------------------------------------------------------- */
@@ -1688,14 +1690,11 @@ struct urb {
* cache. For more information, check &struct urb.
*
*/
-static inline void usb_fill_control_urb(struct urb *urb,
- struct usb_device *dev,
- unsigned int pipe,
- unsigned char *setup_packet,
- void *transfer_buffer,
- int buffer_length,
- usb_complete_t complete_fn,
- void *context)
+static inline void
+usb_fill_control_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
+ unsigned char *setup_packet, void *transfer_buffer,
+ int buffer_length, usb_complete_t complete_fn,
+ void *context)
{
urb->dev = dev;
urb->pipe = pipe;
@@ -1723,13 +1722,10 @@ static inline void usb_fill_control_urb(struct urb *urb,
* Refer to usb_fill_control_urb() for a description of the requirements for
* transfer_buffer.
*/
-static inline void usb_fill_bulk_urb(struct urb *urb,
- struct usb_device *dev,
- unsigned int pipe,
- void *transfer_buffer,
+static inline void usb_fill_bulk_urb(struct urb *urb, struct usb_device *dev,
+ unsigned int pipe, void *transfer_buffer,
int buffer_length,
- usb_complete_t complete_fn,
- void *context)
+ usb_complete_t complete_fn, void *context)
{
urb->dev = dev;
urb->pipe = pipe;
@@ -1763,13 +1759,10 @@ static inline void usb_fill_bulk_urb(struct urb *urb,
* microframes (eight per millisecond) rather than in frames (one per
* millisecond).
*/
-static inline void usb_fill_int_urb(struct urb *urb,
- struct usb_device *dev,
- unsigned int pipe,
- void *transfer_buffer,
+static inline void usb_fill_int_urb(struct urb *urb, struct usb_device *dev,
+ unsigned int pipe, void *transfer_buffer,
int buffer_length,
- usb_complete_t complete_fn,
- void *context,
+ usb_complete_t complete_fn, void *context,
int interval)
{
urb->dev = dev;
@@ -1815,7 +1808,7 @@ extern struct urb *usb_get_from_anchor(struct usb_anchor *anchor);
extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor);
extern int usb_anchor_empty(struct usb_anchor *anchor);
-#define usb_unblock_urb usb_unpoison_urb
+#define usb_unblock_urb usb_unpoison_urb
/**
* usb_urb_dir_in - check if an URB describes an IN transfer
@@ -1864,13 +1857,13 @@ void usb_free_noncoherent(struct usb_device *dev, size_t size,
*-------------------------------------------------------------------*/
extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
- __u8 request, __u8 requesttype, __u16 value, __u16 index,
- void *data, __u16 size, int timeout);
+ __u8 request, __u8 requesttype, __u16 value,
+ __u16 index, void *data, __u16 size, int timeout);
extern int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
- void *data, int len, int *actual_length, int timeout);
+ void *data, int len, int *actual_length,
+ int timeout);
extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
- void *data, int len, int *actual_length,
- int timeout);
+ void *data, int len, int *actual_length, int timeout);
/* wrappers around usb_control_msg() for the most common standard requests */
int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request,
@@ -1878,29 +1871,28 @@ int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request,
const void *data, __u16 size, int timeout,
gfp_t memflags);
int usb_control_msg_recv(struct usb_device *dev, __u8 endpoint, __u8 request,
- __u8 requesttype, __u16 value, __u16 index,
- void *data, __u16 size, int timeout,
- gfp_t memflags);
+ __u8 requesttype, __u16 value, __u16 index, void *data,
+ __u16 size, int timeout, gfp_t memflags);
extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
- unsigned char descindex, void *buf, int size);
-extern int usb_get_status(struct usb_device *dev,
- int recip, int type, int target, void *data);
+ unsigned char descindex, void *buf, int size);
+extern int usb_get_status(struct usb_device *dev, int recip, int type,
+ int target, void *data);
-static inline int usb_get_std_status(struct usb_device *dev,
- int recip, int target, void *data)
+static inline int usb_get_std_status(struct usb_device *dev, int recip,
+ int target, void *data)
{
return usb_get_status(dev, recip, USB_STATUS_TYPE_STANDARD, target,
- data);
+ data);
}
static inline int usb_get_ptm_status(struct usb_device *dev, void *data)
{
- return usb_get_status(dev, USB_RECIP_DEVICE, USB_STATUS_TYPE_PTM,
- 0, data);
+ return usb_get_status(dev, USB_RECIP_DEVICE, USB_STATUS_TYPE_PTM, 0,
+ data);
}
-extern int usb_string(struct usb_device *dev, int index,
- char *buf, size_t size);
+extern int usb_string(struct usb_device *dev, int index, char *buf,
+ size_t size);
extern char *usb_cache_string(struct usb_device *udev, int index);
/* wrappers that also update important state inside usbcore */
@@ -1908,6 +1900,8 @@ extern int usb_clear_halt(struct usb_device *dev, int pipe);
extern int usb_reset_configuration(struct usb_device *dev);
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
+extern void usb_fixup_endpoint(struct usb_device *dev, int epaddr,
+ int interval);
/* this request isn't really synchronous, but it belongs with the others */
extern int usb_driver_set_configuration(struct usb_device *udev, int config);
@@ -1922,9 +1916,8 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration);
* USB identifies 5 second timeouts, maybe more in a few cases, and a few
* slow devices (like some MGE Ellipse UPSes) actually push that limit.
*/
-#define USB_CTRL_GET_TIMEOUT 5000
-#define USB_CTRL_SET_TIMEOUT 5000
-
+#define USB_CTRL_GET_TIMEOUT 5000
+#define USB_CTRL_SET_TIMEOUT 5000
/**
* struct usb_sg_request - support for scatter/gather I/O
@@ -1943,39 +1936,31 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration);
* on the endpoint.
*/
struct usb_sg_request {
- int status;
- size_t bytes;
+ int status;
+ size_t bytes;
/* private:
* members below are private to usbcore,
* and are not provided for driver access!
*/
- spinlock_t lock;
+ spinlock_t lock;
- struct usb_device *dev;
- int pipe;
+ struct usb_device *dev;
+ int pipe;
- int entries;
- struct urb **urbs;
+ int entries;
+ struct urb **urbs;
- int count;
- struct completion complete;
+ int count;
+ struct completion complete;
};
-int usb_sg_init(
- struct usb_sg_request *io,
- struct usb_device *dev,
- unsigned pipe,
- unsigned period,
- struct scatterlist *sg,
- int nents,
- size_t length,
- gfp_t mem_flags
-);
+int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ unsigned pipe, unsigned period, struct scatterlist *sg,
+ int nents, size_t length, gfp_t mem_flags);
void usb_sg_cancel(struct usb_sg_request *io);
void usb_sg_wait(struct usb_sg_request *io);
-
/* ----------------------------------------------------------------------- */
/*
@@ -1997,45 +1982,45 @@ void usb_sg_wait(struct usb_sg_request *io);
/* NOTE: these are not the standard USB_ENDPOINT_XFER_* values!! */
/* (yet ... they're the values used by usbfs) */
-#define PIPE_ISOCHRONOUS 0
-#define PIPE_INTERRUPT 1
-#define PIPE_CONTROL 2
-#define PIPE_BULK 3
+#define PIPE_ISOCHRONOUS 0
+#define PIPE_INTERRUPT 1
+#define PIPE_CONTROL 2
+#define PIPE_BULK 3
-#define usb_pipein(pipe) ((pipe) & USB_DIR_IN)
-#define usb_pipeout(pipe) (!usb_pipein(pipe))
+#define usb_pipein(pipe) ((pipe)&USB_DIR_IN)
+#define usb_pipeout(pipe) (!usb_pipein(pipe))
-#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
-#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
+#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
+#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
-#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
-#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
-#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
-#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
-#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
+#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
+#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
+#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
+#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
+#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
static inline unsigned int __create_pipe(struct usb_device *dev,
- unsigned int endpoint)
+ unsigned int endpoint)
{
return (dev->devnum << 8) | (endpoint << 15);
}
/* Create various pipes... */
-#define usb_sndctrlpipe(dev, endpoint) \
+#define usb_sndctrlpipe(dev, endpoint) \
((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint))
-#define usb_rcvctrlpipe(dev, endpoint) \
+#define usb_rcvctrlpipe(dev, endpoint) \
((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
-#define usb_sndisocpipe(dev, endpoint) \
+#define usb_sndisocpipe(dev, endpoint) \
((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint))
-#define usb_rcvisocpipe(dev, endpoint) \
+#define usb_rcvisocpipe(dev, endpoint) \
((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
-#define usb_sndbulkpipe(dev, endpoint) \
+#define usb_sndbulkpipe(dev, endpoint) \
((PIPE_BULK << 30) | __create_pipe(dev, endpoint))
-#define usb_rcvbulkpipe(dev, endpoint) \
+#define usb_rcvbulkpipe(dev, endpoint) \
((PIPE_BULK << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
-#define usb_sndintpipe(dev, endpoint) \
+#define usb_sndintpipe(dev, endpoint) \
((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint))
-#define usb_rcvintpipe(dev, endpoint) \
+#define usb_rcvintpipe(dev, endpoint) \
((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
static inline struct usb_host_endpoint *
@@ -2078,10 +2063,10 @@ static inline int usb_translate_errors(int error_code)
}
/* Events from the usb core */
-#define USB_DEVICE_ADD 0x0001
-#define USB_DEVICE_REMOVE 0x0002
-#define USB_BUS_ADD 0x0003
-#define USB_BUS_REMOVE 0x0004
+#define USB_DEVICE_ADD 0x0001
+#define USB_DEVICE_REMOVE 0x0002
+#define USB_BUS_ADD 0x0003
+#define USB_BUS_REMOVE 0x0004
extern void usb_register_notify(struct notifier_block *nb);
extern void usb_unregister_notify(struct notifier_block *nb);
@@ -2097,9 +2082,11 @@ enum usb_led_event {
#ifdef CONFIG_USB_LED_TRIG
extern void usb_led_activity(enum usb_led_event ev);
#else
-static inline void usb_led_activity(enum usb_led_event ev) {}
+static inline void usb_led_activity(enum usb_led_event ev)
+{
+}
#endif
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index ac95e7c89df5..8fd38368cb31 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -372,6 +372,11 @@ struct hc_driver {
* or bandwidth constraints.
*/
void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
+ /* Override the endpoint-derived interval
+ * (if there is any cached hardware state).
+ */
+ void (*fixup_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep, int interval);
/* Set the hardware-chosen device address */
int (*address_device)(struct usb_hcd *, struct usb_device *udev,
unsigned int timeout_ms);
@@ -437,6 +442,8 @@ extern void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *);
extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
extern void usb_hcd_flush_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
+extern void usb_hcd_fixup_endpoint(struct usb_device *udev,
+ struct usb_host_endpoint *ep, int interval);
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_reset_endpoint(struct usb_device *udev,
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h
index 6135d076c53d..2d9eed47cf91 100644
--- a/include/linux/usb/otg-fsm.h
+++ b/include/linux/usb/otg-fsm.h
@@ -289,7 +289,7 @@ static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer)
{
if (!fsm->ops->del_timer)
return -EOPNOTSUPP;
- fsm->ops->del_timer(fsm, timer);
+ fsm->ops->timer_delete(fsm, timer);
return 0;
}
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index e1f87fbfe554..3e71d45477a4 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -36,6 +36,8 @@ struct rpi_firmware_property_tag_header {
enum rpi_firmware_property_tag {
RPI_FIRMWARE_PROPERTY_END = 0,
RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
+ RPI_FIRMWARE_GET_FIRMWARE_VARIANT = 0x00000002,
+ RPI_FIRMWARE_GET_FIRMWARE_HASH = 0x00000003,
RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
@@ -71,6 +73,7 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
+ RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY = 0x00030023,
RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
@@ -89,9 +92,14 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045,
RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045,
RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,
- RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,
+ RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00038049,
+ RPI_FIRMWARE_SET_POE_HAT_VAL_OLD = 0x00030050,
RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058,
+ RPI_FIRMWARE_GET_REBOOT_FLAGS = 0x00030064,
+ RPI_FIRMWARE_SET_REBOOT_FLAGS = 0x00038064,
RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066,
+ RPI_FIRMWARE_GET_SW_UART = 0x0003008a,
+ RPI_FIRMWARE_SET_SW_UART = 0x0003808a,
/* Dispmanx TAGS */
RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001,
@@ -105,9 +113,16 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER = 0x0004000c,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
@@ -116,22 +131,33 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+
RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER = 0x0004800c,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
+ RPI_FIRMWARE_SET_TIMING = 0x00048017,
+ RPI_FIRMWARE_GET_DISPLAY_CFG = 0x00040018,
+ RPI_FIRMWARE_SET_DISPLAY_POWER = 0x00048019,
RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
};
@@ -156,6 +182,8 @@ enum rpi_firmware_clk_id {
RPI_FIRMWARE_NUM_CLK_ID,
};
+#define GET_DISPLAY_SETTINGS_PAYLOAD_SIZE 64
+
/**
* struct rpi_firmware_clk_rate_request - Firmware Request for a rate
* @id: ID of the clock being queried
diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h
index 22acaaec7b1c..eab4c7f3d833 100644
--- a/include/uapi/linux/fb.h
+++ b/include/uapi/linux/fb.h
@@ -36,6 +36,12 @@
#define FBIOPUT_MODEINFO 0x4617
#define FBIOGET_DISPINFO 0x4618
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+/*
+ * HACK: use 'z' in order not to clash with any other ioctl numbers which might
+ * be concurrently added to the mainline kernel
+ */
+#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea)
+#define FBIODMACOPY _IOW('z', 0x22, struct fb_dmacopy)
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
@@ -342,6 +348,12 @@ struct fb_copyarea {
__u32 sy;
};
+struct fb_dmacopy {
+ void *dst;
+ __u32 src;
+ __u32 length;
+};
+
struct fb_fillrect {
__u32 dx; /* screen-relative */
__u32 dy;
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 9c007a106330..90f05675213e 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -231,6 +231,9 @@
/* Sunplus UART */
#define PORT_SUNPLUS 123
+/* RPi firmware UART */
+#define PORT_RPI_FW 124
+
/* Generic type identifier for ports which type is not important to userspace. */
#define PORT_GENERIC (-1)
diff --git a/include/uapi/misc/rp1_pio_if.h b/include/uapi/misc/rp1_pio_if.h
new file mode 100644
index 000000000000..0a0d4aca11dd
--- /dev/null
+++ b/include/uapi/misc/rp1_pio_if.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0 + WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2023-24 Raspberry Pi Ltd.
+ * All rights reserved.
+ */
+#ifndef _PIO_RP1_IF_H
+#define _PIO_RP1_IF_H
+
+#include <linux/ioctl.h>
+
+#define RP1_PIO_INSTRUCTION_COUNT 32
+#define RP1_PIO_SM_COUNT 4
+#define RP1_PIO_GPIO_COUNT 28
+#define RP1_GPIO_FUNC_PIO 7
+
+#define RP1_PIO_ORIGIN_ANY ((uint16_t)(~0))
+
+#define RP1_PIO_DIR_TO_SM 0
+#define RP1_PIO_DIR_FROM_SM 1
+#define RP1_PIO_DIR_COUNT 2
+
+typedef struct {
+ uint32_t clkdiv;
+ uint32_t execctrl;
+ uint32_t shiftctrl;
+ uint32_t pinctrl;
+} rp1_pio_sm_config;
+
+struct rp1_pio_add_program_args {
+ uint16_t num_instrs;
+ uint16_t origin;
+ uint16_t instrs[RP1_PIO_INSTRUCTION_COUNT];
+};
+
+struct rp1_pio_remove_program_args {
+ uint16_t num_instrs;
+ uint16_t origin;
+};
+
+struct rp1_pio_sm_claim_args {
+ uint16_t mask;
+};
+
+struct rp1_pio_sm_init_args {
+ uint16_t sm;
+ uint16_t initial_pc;
+ rp1_pio_sm_config config;
+};
+
+struct rp1_pio_sm_set_config_args {
+ uint16_t sm;
+ uint16_t rsvd;
+ rp1_pio_sm_config config;
+};
+
+struct rp1_pio_sm_exec_args {
+ uint16_t sm;
+ uint16_t instr;
+ uint8_t blocking;
+ uint8_t rsvd;
+};
+
+struct rp1_pio_sm_clear_fifos_args {
+ uint16_t sm;
+};
+
+struct rp1_pio_sm_set_clkdiv_args {
+ uint16_t sm;
+ uint16_t div_int;
+ uint8_t div_frac;
+ uint8_t rsvd;
+};
+
+struct rp1_pio_sm_set_pins_args {
+ uint16_t sm;
+ uint16_t rsvd;
+ uint32_t values;
+ uint32_t mask;
+};
+
+struct rp1_pio_sm_set_pindirs_args {
+ uint16_t sm;
+ uint16_t rsvd;
+ uint32_t dirs;
+ uint32_t mask;
+};
+
+struct rp1_pio_sm_set_enabled_args {
+ uint16_t mask;
+ uint8_t enable;
+ uint8_t rsvd;
+};
+
+struct rp1_pio_sm_restart_args {
+ uint16_t mask;
+};
+
+struct rp1_pio_sm_clkdiv_restart_args {
+ uint16_t mask;
+};
+
+struct rp1_pio_sm_enable_sync_args {
+ uint16_t mask;
+};
+
+struct rp1_pio_sm_put_args {
+ uint16_t sm;
+ uint8_t blocking;
+ uint8_t rsvd;
+ uint32_t data;
+};
+
+struct rp1_pio_sm_get_args {
+ uint16_t sm;
+ uint8_t blocking;
+ uint8_t rsvd;
+ uint32_t data; /* OUT */
+};
+
+struct rp1_pio_sm_set_dmactrl_args {
+ uint16_t sm;
+ uint8_t is_tx;
+ uint8_t rsvd;
+ uint32_t ctrl;
+};
+
+struct rp1_pio_sm_fifo_state_args {
+ uint16_t sm;
+ uint8_t tx;
+ uint8_t rsvd;
+ uint16_t level; /* OUT */
+ uint8_t empty; /* OUT */
+ uint8_t full; /* OUT */
+};
+
+struct rp1_gpio_init_args {
+ uint16_t gpio;
+};
+
+struct rp1_gpio_set_function_args {
+ uint16_t gpio;
+ uint16_t fn;
+};
+
+struct rp1_gpio_set_pulls_args {
+ uint16_t gpio;
+ uint8_t up;
+ uint8_t down;
+};
+
+struct rp1_gpio_set_args {
+ uint16_t gpio;
+ uint16_t value;
+};
+
+struct rp1_pio_sm_config_xfer_args {
+ uint16_t sm;
+ uint16_t dir;
+ uint16_t buf_size;
+ uint16_t buf_count;
+};
+
+struct rp1_pio_sm_xfer_data_args {
+ uint16_t sm;
+ uint16_t dir;
+ uint16_t data_bytes;
+ void *data;
+};
+
+struct rp1_pio_sm_xfer_data32_args {
+ uint16_t sm;
+ uint16_t dir;
+ uint32_t data_bytes;
+ void *data;
+};
+
+struct rp1_access_hw_args {
+ uint32_t addr;
+ uint32_t len;
+ void *data;
+};
+
+#define PIO_IOC_MAGIC 102
+
+#define PIO_IOC_SM_CONFIG_XFER _IOW(PIO_IOC_MAGIC, 0, struct rp1_pio_sm_config_xfer_args)
+#define PIO_IOC_SM_XFER_DATA _IOW(PIO_IOC_MAGIC, 1, struct rp1_pio_sm_xfer_data_args)
+#define PIO_IOC_SM_XFER_DATA32 _IOW(PIO_IOC_MAGIC, 2, struct rp1_pio_sm_xfer_data32_args)
+
+#define PIO_IOC_READ_HW _IOW(PIO_IOC_MAGIC, 8, struct rp1_access_hw_args)
+#define PIO_IOC_WRITE_HW _IOW(PIO_IOC_MAGIC, 9, struct rp1_access_hw_args)
+
+#define PIO_IOC_CAN_ADD_PROGRAM _IOW(PIO_IOC_MAGIC, 10, struct rp1_pio_add_program_args)
+#define PIO_IOC_ADD_PROGRAM _IOW(PIO_IOC_MAGIC, 11, struct rp1_pio_add_program_args)
+#define PIO_IOC_REMOVE_PROGRAM _IOW(PIO_IOC_MAGIC, 12, struct rp1_pio_remove_program_args)
+#define PIO_IOC_CLEAR_INSTR_MEM _IO(PIO_IOC_MAGIC, 13)
+
+#define PIO_IOC_SM_CLAIM _IOW(PIO_IOC_MAGIC, 20, struct rp1_pio_sm_claim_args)
+#define PIO_IOC_SM_UNCLAIM _IOW(PIO_IOC_MAGIC, 21, struct rp1_pio_sm_claim_args)
+#define PIO_IOC_SM_IS_CLAIMED _IOW(PIO_IOC_MAGIC, 22, struct rp1_pio_sm_claim_args)
+
+#define PIO_IOC_SM_INIT _IOW(PIO_IOC_MAGIC, 30, struct rp1_pio_sm_init_args)
+#define PIO_IOC_SM_SET_CONFIG _IOW(PIO_IOC_MAGIC, 31, struct rp1_pio_sm_set_config_args)
+#define PIO_IOC_SM_EXEC _IOW(PIO_IOC_MAGIC, 32, struct rp1_pio_sm_exec_args)
+#define PIO_IOC_SM_CLEAR_FIFOS _IOW(PIO_IOC_MAGIC, 33, struct rp1_pio_sm_clear_fifos_args)
+#define PIO_IOC_SM_SET_CLKDIV _IOW(PIO_IOC_MAGIC, 34, struct rp1_pio_sm_set_clkdiv_args)
+#define PIO_IOC_SM_SET_PINS _IOW(PIO_IOC_MAGIC, 35, struct rp1_pio_sm_set_pins_args)
+#define PIO_IOC_SM_SET_PINDIRS _IOW(PIO_IOC_MAGIC, 36, struct rp1_pio_sm_set_pindirs_args)
+#define PIO_IOC_SM_SET_ENABLED _IOW(PIO_IOC_MAGIC, 37, struct rp1_pio_sm_set_enabled_args)
+#define PIO_IOC_SM_RESTART _IOW(PIO_IOC_MAGIC, 38, struct rp1_pio_sm_restart_args)
+#define PIO_IOC_SM_CLKDIV_RESTART _IOW(PIO_IOC_MAGIC, 39, struct rp1_pio_sm_restart_args)
+#define PIO_IOC_SM_ENABLE_SYNC _IOW(PIO_IOC_MAGIC, 40, struct rp1_pio_sm_enable_sync_args)
+#define PIO_IOC_SM_PUT _IOW(PIO_IOC_MAGIC, 41, struct rp1_pio_sm_put_args)
+#define PIO_IOC_SM_GET _IOWR(PIO_IOC_MAGIC, 42, struct rp1_pio_sm_get_args)
+#define PIO_IOC_SM_SET_DMACTRL _IOW(PIO_IOC_MAGIC, 43, struct rp1_pio_sm_set_dmactrl_args)
+#define PIO_IOC_SM_FIFO_STATE _IOW(PIO_IOC_MAGIC, 44, struct rp1_pio_sm_fifo_state_args)
+#define PIO_IOC_SM_DRAIN_TX _IOW(PIO_IOC_MAGIC, 45, struct rp1_pio_sm_clear_fifos_args)
+
+#define PIO_IOC_GPIO_INIT _IOW(PIO_IOC_MAGIC, 50, struct rp1_gpio_init_args)
+#define PIO_IOC_GPIO_SET_FUNCTION _IOW(PIO_IOC_MAGIC, 51, struct rp1_gpio_set_function_args)
+#define PIO_IOC_GPIO_SET_PULLS _IOW(PIO_IOC_MAGIC, 52, struct rp1_gpio_set_pulls_args)
+#define PIO_IOC_GPIO_SET_OUTOVER _IOW(PIO_IOC_MAGIC, 53, struct rp1_gpio_set_args)
+#define PIO_IOC_GPIO_SET_INOVER _IOW(PIO_IOC_MAGIC, 54, struct rp1_gpio_set_args)
+#define PIO_IOC_GPIO_SET_OEOVER _IOW(PIO_IOC_MAGIC, 55, struct rp1_gpio_set_args)
+#define PIO_IOC_GPIO_SET_INPUT_ENABLED _IOW(PIO_IOC_MAGIC, 56, struct rp1_gpio_set_args)
+#define PIO_IOC_GPIO_SET_DRIVE_STRENGTH _IOW(PIO_IOC_MAGIC, 57, struct rp1_gpio_set_args)
+
+#endif