--- /dev/null
+# CONFIG_AIO is not set
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM2835=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+CONFIG_ARCH_MULTI_V6=y
+CONFIG_ARCH_MULTI_V6_V7=y
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
+# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARM=y
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_BCM2835_CPUFREQ=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARM_ERRATA_411920=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_TIMER_SP804=y
+CONFIG_ARM_UNWIND=y
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BCM2708_VCMEM=y
+# CONFIG_BCM2835_DEVGPIOMEM is not set
+CONFIG_BCM2835_FAST_MEMCPY=y
+CONFIG_BCM2835_MBOX=y
+# CONFIG_BCM2835_SMI is not set
+CONFIG_BCM2835_THERMAL=y
+CONFIG_BCM2835_TIMER=y
+CONFIG_BCM2835_VCHIQ=y
+# CONFIG_BCM2835_VCHIQ_SUPPORT_MEMDUMP is not set
+CONFIG_BCM2835_WDT=y
+CONFIG_BCM_VCIO=y
+CONFIG_BCM_VC_SM=y
+CONFIG_BCM_VIDEOCORE=y
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BRCM_CHAR_DRIVERS=y
+CONFIG_BUILD_BIN2C=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CMA=y
+CONFIG_CMA_ALIGNMENT=8
+CONFIG_CMA_AREAS=7
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_SIZE_MBYTES=16
+# CONFIG_CMA_SIZE_SEL_MAX is not set
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+# CONFIG_CMA_SIZE_SEL_MIN is not set
+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
+CONFIG_COMMON_CLK=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+# CONFIG_CPUFREQ_DT is not set
+CONFIG_CPU_32v6=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_ABRT_EV6=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_PM=y
+# CONFIG_CPU_THERMAL is not set
+CONFIG_CPU_THUMB_CAPABLE=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_V6K=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DMADEVICES=y
+CONFIG_DMA_BCM2708=y
+CONFIG_DMA_BCM2835=y
+CONFIG_DMA_CMA=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_SHARED_BUFFER=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DNOTIFY=y
+CONFIG_DTC=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_F2FS_CHECK_FS is not set
+CONFIG_F2FS_FS=y
+# CONFIG_F2FS_FS_SECURITY is not set
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_STAT_FS=y
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CMDLINE=y
+# CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA is not set
+# CONFIG_FB_RPISENSE is not set
+CONFIG_FIQ=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_FIX_EARLYCON_MEM=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_SUPPORT=y
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_FPE_NWFPE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FREEZER=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_GPIO_BCM_EXP is not set
+# CONFIG_GPIO_BCM_VIRT is not set
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GRO_CELLS is not set
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_EBPF_JIT=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HW_CONSOLE=y
+CONFIG_HZ_FIXED=0
+CONFIG_I2C=y
+# CONFIG_I2C_BCM2708 is not set
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INPUT=y
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_IOMMU_HELPER=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_JBD2=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_INPUT=y
+CONFIG_LIBFDT=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAILBOX=y
+# CONFIG_MAILBOX_TEST is not set
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_MDIO_BUS is not set
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_MFD_RPISENSE_CORE is not set
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+# CONFIG_MMC_BCM2835 is not set
+CONFIG_MMC_BCM2835_DMA=y
+CONFIG_MMC_BCM2835_MMC=y
+CONFIG_MMC_BCM2835_PIO_DMA_BARRIER=2
+CONFIG_MMC_BCM2835_SDHOST=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MODULES_USE_ELF_REL=y
+# CONFIG_MTD is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_NLS=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NO_BOOTMEM=y
+CONFIG_NO_HZ=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_OABI_COMPAT=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_OF_DYNAMIC=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OF_RESOLVE=y
+CONFIG_OLD_SIGACTION=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_BCM2835=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_PM_GENERIC_DOMAINS_OF=y
+CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
+CONFIG_PM_SLEEP=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PWM=y
+CONFIG_PWM_BCM2835=y
+CONFIG_PWM_SYSFS=y
+CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_RASPBERRYPI_POWER=y
+CONFIG_RATIONAL=y
+CONFIG_RAW_DRIVER=y
+# CONFIG_RCU_NEED_SEGCBLIST is not set
+# CONFIG_RCU_STALL_COMMON is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_SCHED_INFO is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_SERIAL_8250_BCM2835AUX=y
+# CONFIG_SERIAL_8250_DMA is not set
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_FSL=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=0
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
+# CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SG_POOL=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SRCU=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_SWIOTLB=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_TEXTSEARCH is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_OF=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TINY_SRCU=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_UID16 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_DWCOTG=y
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_NET_DRIVERS=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_UAS=y
+CONFIG_USB_USBNET=y
+CONFIG_USE_OF=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ZBOOT_ROM_TEXT=0x0
--- /dev/null
+# CONFIG_AIO is not set
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM2835=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_ARCH_MMAP_RND_BITS_MAX=15
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+CONFIG_ARCH_MULTI_V6_V7=y
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARM=y
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+CONFIG_ARM_BCM2835_CPUFREQ=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+# CONFIG_ARM_LPAE is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_TIMER_SP804=y
+CONFIG_ARM_UNWIND=y
+CONFIG_ARM_VIRT_EXT=y
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BCM2708_VCMEM=y
+# CONFIG_BCM2835_DEVGPIOMEM is not set
+CONFIG_BCM2835_MBOX=y
+# CONFIG_BCM2835_SMI is not set
+CONFIG_BCM2835_THERMAL=y
+CONFIG_BCM2835_TIMER=y
+CONFIG_BCM2835_VCHIQ=y
+# CONFIG_BCM2835_VCHIQ_SUPPORT_MEMDUMP is not set
+CONFIG_BCM2835_WDT=y
+CONFIG_BCM_VCIO=y
+CONFIG_BCM_VC_SM=y
+CONFIG_BCM_VIDEOCORE=y
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BRCM_CHAR_DRIVERS=y
+CONFIG_BUILD_BIN2C=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CMA=y
+CONFIG_CMA_ALIGNMENT=8
+CONFIG_CMA_AREAS=7
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_SIZE_MBYTES=16
+# CONFIG_CMA_SIZE_SEL_MAX is not set
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+# CONFIG_CMA_SIZE_SEL_MIN is not set
+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
+CONFIG_COMMON_CLK=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+# CONFIG_CPUFREQ_DT is not set
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_SPECTRE=y
+# CONFIG_CPU_THERMAL is not set
+CONFIG_CPU_THUMB_CAPABLE=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DMADEVICES=y
+CONFIG_DMA_BCM2708=y
+CONFIG_DMA_BCM2835=y
+CONFIG_DMA_CMA=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_SHARED_BUFFER=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DNOTIFY=y
+CONFIG_DTC=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_F2FS_CHECK_FS is not set
+CONFIG_F2FS_FS=y
+# CONFIG_F2FS_FS_SECURITY is not set
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_STAT_FS=y
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CMDLINE=y
+# CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA is not set
+# CONFIG_FB_RPISENSE is not set
+CONFIG_FIQ=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_SUPPORT=y
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_FPE_NWFPE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FREEZER=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ARCH_TOPOLOGY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_BCM_EXP=y
+CONFIG_GPIO_BCM_VIRT=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GRO_CELLS is not set
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_HAVE_ARM_SMCCC=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_EBPF_JIT=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SMP=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_HW_CONSOLE=y
+CONFIG_HZ_FIXED=0
+CONFIG_I2C=y
+# CONFIG_I2C_BCM2708 is not set
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INPUT=y
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_IOMMU_HELPER=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_JBD2=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_INPUT=y
+CONFIG_LIBFDT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAILBOX=y
+# CONFIG_MAILBOX_TEST is not set
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_MFD_RPISENSE_CORE is not set
+CONFIG_MFD_SYSCON=y
+CONFIG_MICROCHIP_PHY=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+# CONFIG_MMC_BCM2835 is not set
+CONFIG_MMC_BCM2835_DMA=y
+CONFIG_MMC_BCM2835_MMC=y
+CONFIG_MMC_BCM2835_PIO_DMA_BARRIER=2
+CONFIG_MMC_BCM2835_SDHOST=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MODULES_USE_ELF_REL=y
+# CONFIG_MTD is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEON=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NLS=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NO_BOOTMEM=y
+CONFIG_NO_HZ=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NR_CPUS=4
+CONFIG_OABI_COMPAT=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_OF_DYNAMIC=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OF_RESOLVE=y
+CONFIG_OLD_SIGACTION=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_PADATA=y
+CONFIG_PAGE_OFFSET=0x80000000
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_BCM2835=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_PM_GENERIC_DOMAINS_OF=y
+CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PWM=y
+CONFIG_PWM_BCM2835=y
+CONFIG_PWM_SYSFS=y
+CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_RASPBERRYPI_POWER=y
+CONFIG_RATIONAL=y
+CONFIG_RAW_DRIVER=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_SCHED_INFO is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_SERIAL_8250_BCM2835AUX=y
+# CONFIG_SERIAL_8250_DMA is not set
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_FSL=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=0
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
+# CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SG_POOL=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SRCU=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SWP_EMULATE=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_TEXTSEARCH is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_OF=y
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_UID16 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_DWCOTG=y
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_LAN78XX=y
+CONFIG_USB_NET_DRIVERS=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_UAS=y
+CONFIG_USB_USBNET=y
+CONFIG_USE_OF=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_XPS=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ZBOOT_ROM_TEXT=0x0
--- /dev/null
+CONFIG_64BIT=y
+# CONFIG_AIO is not set
+CONFIG_ARCH_BCM2835=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+CONFIG_ARCH_HAS_KCOV=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MMAP_RND_BITS=18
+CONFIG_ARCH_MMAP_RND_BITS_MAX=24
+CONFIG_ARCH_MMAP_RND_BITS_MIN=18
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
+# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set
+# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARM64=y
+# CONFIG_ARM64_16K_PAGES is not set
+CONFIG_ARM64_4K_PAGES=y
+# CONFIG_ARM64_64K_PAGES is not set
+CONFIG_ARM64_CONT_SHIFT=4
+# CONFIG_ARM64_CRYPTO is not set
+CONFIG_ARM64_ERRATUM_819472=y
+CONFIG_ARM64_ERRATUM_824069=y
+CONFIG_ARM64_ERRATUM_826319=y
+CONFIG_ARM64_ERRATUM_827319=y
+CONFIG_ARM64_ERRATUM_832075=y
+CONFIG_ARM64_ERRATUM_843419=y
+CONFIG_ARM64_HW_AFDBM=y
+# CONFIG_ARM64_LSE_ATOMICS is not set
+CONFIG_ARM64_MODULE_CMODEL_LARGE=y
+CONFIG_ARM64_PAGE_SHIFT=12
+CONFIG_ARM64_PAN=y
+# CONFIG_ARM64_PMEM is not set
+# CONFIG_ARM64_PTDUMP_CORE is not set
+# CONFIG_ARM64_PTDUMP_DEBUGFS is not set
+# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set
+CONFIG_ARM64_SSBD=y
+# CONFIG_ARM64_SW_TTBR0_PAN is not set
+CONFIG_ARM64_UAO=y
+CONFIG_ARM64_VA_BITS=39
+CONFIG_ARM64_VA_BITS_39=y
+# CONFIG_ARM64_VA_BITS_48 is not set
+CONFIG_ARM64_VHE=y
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y
+CONFIG_ARM_BCM2835_CPUFREQ=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_V3=y
+CONFIG_ARM_PSCI_FW=y
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_TIMER_SP804=y
+CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BCM2708_VCMEM=y
+# CONFIG_BCM2835_DEVGPIOMEM is not set
+CONFIG_BCM2835_MBOX=y
+# CONFIG_BCM2835_SMI is not set
+CONFIG_BCM2835_THERMAL=y
+CONFIG_BCM2835_VCHIQ=y
+# CONFIG_BCM2835_VCHIQ_SUPPORT_MEMDUMP is not set
+CONFIG_BCM2835_WDT=y
+# CONFIG_BCM_FLEXRM_MBOX is not set
+# CONFIG_BCM_VCIO is not set
+# CONFIG_BCM_VC_SM is not set
+CONFIG_BCM_VIDEOCORE=y
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BOUNCE=y
+CONFIG_BRCM_CHAR_DRIVERS=y
+CONFIG_BUILD_BIN2C=y
+CONFIG_CAVIUM_ERRATUM_22375=y
+CONFIG_CAVIUM_ERRATUM_23154=y
+CONFIG_CAVIUM_ERRATUM_27456=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CMA=y
+CONFIG_CMA_ALIGNMENT=8
+CONFIG_CMA_AREAS=7
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_SIZE_MBYTES=16
+# CONFIG_CMA_SIZE_SEL_MAX is not set
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+# CONFIG_CMA_SIZE_SEL_MIN is not set
+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
+CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_XGENE=y
+# CONFIG_COMPAT is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+# CONFIG_CPUFREQ_DT is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_RMAP=y
+# CONFIG_CPU_THERMAL is not set
+CONFIG_CRC16=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DMADEVICES=y
+CONFIG_DMA_BCM2708=y
+CONFIG_DMA_BCM2835=y
+CONFIG_DMA_CMA=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DNOTIFY=y
+CONFIG_DTC=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_F2FS_CHECK_FS is not set
+CONFIG_F2FS_FS=y
+# CONFIG_F2FS_FS_SECURITY is not set
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_STAT_FS=y
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CMDLINE=y
+# CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA is not set
+# CONFIG_FB_RPISENSE is not set
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_SUPPORT=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FREEZER=y
+CONFIG_FSL_ERRATUM_A008585=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ARCH_TOPOLOGY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_MIGRATION=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_BCM_EXP=y
+CONFIG_GPIO_BCM_VIRT=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GRO_CELLS is not set
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KASAN=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_VMAP_STACK=y
+CONFIG_HAVE_ARM_SMCCC=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_BUGVERBOSE=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_EBPF_JIT=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_GENERIC_GUP=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_PATA_PLATFORM=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_RCU_TABLE_FREE=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HOLES_IN_ZONE=y
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_HUGETLBFS is not set
+CONFIG_HW_CONSOLE=y
+CONFIG_I2C=y
+# CONFIG_I2C_BCM2708 is not set
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_INPUT=y
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_IOMMU_HELPER=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_JBD2=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_INPUT=y
+CONFIG_LIBFDT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAILBOX=y
+# CONFIG_MAILBOX_TEST is not set
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_MFD_RPISENSE_CORE is not set
+CONFIG_MFD_SYSCON=y
+CONFIG_MICROCHIP_PHY=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+# CONFIG_MMC_BCM2835 is not set
+CONFIG_MMC_BCM2835_DMA=y
+CONFIG_MMC_BCM2835_MMC=y
+CONFIG_MMC_BCM2835_PIO_DMA_BARRIER=2
+CONFIG_MMC_BCM2835_SDHOST=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MODULES_USE_ELF_RELA=y
+# CONFIG_MTD is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NLS=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NO_BOOTMEM=y
+CONFIG_NO_HZ=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_IOPORT_MAP=y
+CONFIG_NR_CPUS=4
+# CONFIG_NUMA is not set
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_OF_DYNAMIC=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OF_RESOLVE=y
+CONFIG_PADATA=y
+CONFIG_PARTITION_PERCPU=y
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_PHYLIB=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_BCM2835=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_PM_GENERIC_DOMAINS_OF=y
+CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PWM=y
+CONFIG_PWM_BCM2835=y
+CONFIG_PWM_SYSFS=y
+# CONFIG_RANDOMIZE_BASE is not set
+CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_RASPBERRYPI_POWER=y
+CONFIG_RATIONAL=y
+CONFIG_RAW_DRIVER=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_SCHED_INFO is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_SERIAL_8250_BCM2835AUX=y
+# CONFIG_SERIAL_8250_DMA is not set
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_FSL=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=0
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
+# CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SG_POOL=y
+CONFIG_SMP=y
+CONFIG_SPARSEMEM=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SRCU=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+# CONFIG_TEXTSEARCH is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_OF=y
+CONFIG_THREAD_INFO_IN_TASK=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_UNMAP_KERNEL_AT_EL0=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_DWCOTG=y
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_LAN78XX=y
+CONFIG_USB_NET_DRIVERS=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_UAS=y
+CONFIG_USB_USBNET=y
+CONFIG_VMAP_STACK=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_XPS=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
define Device/rpi
DEVICE_TITLE := Raspberry Pi B/B+/CM/Zero/ZeroW
DEVICE_DTS := bcm2708-rpi-b bcm2708-rpi-b-plus bcm2708-rpi-cm bcm2708-rpi-0-w
- SUPPORTED_DEVICES := rpi-b rpi-b-plus rpi-cm rpi-zero rpi-zero-w raspberrypi,model-b raspberrypi,model-b-plus raspberrypi,compute-module-1 raspberrypi,model-b-rev2 raspberrypi,model-zero raspberrypi,model-zero-w
+ SUPPORTED_DEVICES := \
+ rpi-b rpi-b-plus rpi-cm rpi-zero rpi-zero-w \
+ raspberrypi,model-b raspberrypi,model-b-plus raspberrypi,model-b-rev2 \
+ raspberrypi,compute-module raspberrypi,compute-module-1 \
+ raspberrypi,model-zero raspberrypi,model-zero-w
DEVICE_PACKAGES := brcmfmac-firmware-43430-sdio brcmfmac-board-rpi2 kmod-brcmfmac wpad-basic
endef
ifeq ($(SUBTARGET),bcm2708)
define Device/rpi-2
DEVICE_TITLE := Raspberry Pi 2B/3B/3B+/3CM
DEVICE_DTS := bcm2709-rpi-2-b bcm2710-rpi-3-b bcm2710-rpi-3-b-plus bcm2710-rpi-cm3
- SUPPORTED_DEVICES := rpi-2-b rpi-3-b rpi-3-b-plus rpi-cm raspberrypi,2-model-b raspberrypi,3-model-b raspberrypi,3-model-b-plus raspberrypi,compute-module-3
+ SUPPORTED_DEVICES := \
+ rpi-2-b rpi-3-b rpi-3-b-plus rpi-cm \
+ raspberrypi,2-model-b \
+ raspberrypi,3-model-b raspberrypi,3-model-b-plus \
+ raspberrypi,3-compute-module raspberrypi,compute-module-3
DEVICE_PACKAGES := brcmfmac-firmware-43430-sdio brcmfmac-firmware-43455-sdio brcmfmac-board-rpi2 brcmfmac-board-rpi3 kmod-brcmfmac wpad-basic
endef
ifeq ($(SUBTARGET),bcm2709)
KERNEL_IMG := kernel8.img
DEVICE_TITLE := Raspberry Pi 3B/3B+
DEVICE_DTS := broadcom/bcm2710-rpi-3-b broadcom/bcm2710-rpi-3-b-plus
- SUPPORTED_DEVICES := rpi-3-b rpi-3-b-plus raspberrypi,3-model-b raspberrypi,3-model-b-plus
+ SUPPORTED_DEVICES := \
+ rpi-3-b rpi-3-b-plus \
+ raspberrypi,3-model-b raspberrypi,3-model-b-plus \
+ raspberrypi,3-compute-module raspberrypi,compute-module-3
DEVICE_PACKAGES := brcmfmac-firmware-43430-sdio brcmfmac-board-rpi2 brcmfmac-firmware-43455-sdio brcmfmac-board-rpi3 kmod-brcmfmac wpad-basic
endef
ifeq ($(SUBTARGET),bcm2710)
--- /dev/null
+From a45a0eb188581a6c1f57b7adc4f66f5754927ad3 Mon Sep 17 00:00:00 2001
+From: Dan Pasanen <dan.pasanen@gmail.com>
+Date: Thu, 21 Sep 2017 09:55:42 -0500
+Subject: [PATCH 001/454] arm: partially revert
+ 702b94bff3c50542a6e4ab9a4f4cef093262fe65
+
+* Re-expose some dmi APIs for use in VCSM
+---
+ arch/arm/include/asm/cacheflush.h | 21 +++++++++++++++++++++
+ arch/arm/include/asm/glue-cache.h | 2 ++
+ arch/arm/mm/proc-macros.S | 2 ++
+ arch/arm/mm/proc-syms.c | 3 +++
+ 4 files changed, 28 insertions(+)
+
+--- a/arch/arm/include/asm/cacheflush.h
++++ b/arch/arm/include/asm/cacheflush.h
+@@ -94,6 +94,21 @@
+ * DMA Cache Coherency
+ * ===================
+ *
++ * dma_inv_range(start, end)
++ *
++ * Invalidate (discard) the specified virtual address range.
++ * May not write back any entries. If 'start' or 'end'
++ * are not cache line aligned, those lines must be written
++ * back.
++ * - start - virtual start address
++ * - end - virtual end address
++ *
++ * dma_clean_range(start, end)
++ *
++ * Clean (write back) the specified virtual address range.
++ * - start - virtual start address
++ * - end - virtual end address
++ *
+ * dma_flush_range(start, end)
+ *
+ * Clean and invalidate the specified virtual address range.
+@@ -115,6 +130,8 @@ struct cpu_cache_fns {
+ void (*dma_map_area)(const void *, size_t, int);
+ void (*dma_unmap_area)(const void *, size_t, int);
+
++ void (*dma_inv_range)(const void *, const void *);
++ void (*dma_clean_range)(const void *, const void *);
+ void (*dma_flush_range)(const void *, const void *);
+ } __no_randomize_layout;
+
+@@ -140,6 +157,8 @@ extern struct cpu_cache_fns cpu_cache;
+ * is visible to DMA, or data written by DMA to system memory is
+ * visible to the CPU.
+ */
++#define dmac_inv_range cpu_cache.dma_inv_range
++#define dmac_clean_range cpu_cache.dma_clean_range
+ #define dmac_flush_range cpu_cache.dma_flush_range
+
+ #else
+@@ -159,6 +178,8 @@ extern void __cpuc_flush_dcache_area(voi
+ * is visible to DMA, or data written by DMA to system memory is
+ * visible to the CPU.
+ */
++extern void dmac_inv_range(const void *, const void *);
++extern void dmac_clean_range(const void *, const void *);
+ extern void dmac_flush_range(const void *, const void *);
+
+ #endif
+--- a/arch/arm/include/asm/glue-cache.h
++++ b/arch/arm/include/asm/glue-cache.h
+@@ -154,6 +154,8 @@ static inline void nop_dma_unmap_area(co
+ #define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range)
+ #define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
+
++#define dmac_inv_range __glue(_CACHE,_dma_inv_range)
++#define dmac_clean_range __glue(_CACHE,_dma_clean_range)
+ #define dmac_flush_range __glue(_CACHE,_dma_flush_range)
+ #endif
+
+--- a/arch/arm/mm/proc-macros.S
++++ b/arch/arm/mm/proc-macros.S
+@@ -325,6 +325,8 @@ ENTRY(\name\()_cache_fns)
+ .long \name\()_flush_kern_dcache_area
+ .long \name\()_dma_map_area
+ .long \name\()_dma_unmap_area
++ .long \name\()_dma_inv_range
++ .long \name\()_dma_clean_range
+ .long \name\()_dma_flush_range
+ .size \name\()_cache_fns, . - \name\()_cache_fns
+ .endm
+--- a/arch/arm/mm/proc-syms.c
++++ b/arch/arm/mm/proc-syms.c
+@@ -30,6 +30,9 @@ EXPORT_SYMBOL(__cpuc_flush_user_all);
+ EXPORT_SYMBOL(__cpuc_flush_user_range);
+ EXPORT_SYMBOL(__cpuc_coherent_kern_range);
+ EXPORT_SYMBOL(__cpuc_flush_dcache_area);
++EXPORT_SYMBOL(dmac_inv_range);
++EXPORT_SYMBOL(dmac_clean_range);
++EXPORT_SYMBOL(dmac_flush_range);
+ #else
+ EXPORT_SYMBOL(cpu_cache);
+ #endif
--- /dev/null
+From 313db26f57beeb201e7c72acb6f0f9772f7d56d8 Mon Sep 17 00:00:00 2001
+From: Steve Glendinning <steve.glendinning@smsc.com>
+Date: Thu, 19 Feb 2015 18:47:12 +0000
+Subject: [PATCH 002/454] smsx95xx: fix crimes against truesize
+
+smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings.
+
+This patch stops smsc95xx from changing truesize.
+
+Signed-off-by: Steve Glendinning <steve.glendinning@smsc.com>
+---
+ drivers/net/usb/smsc95xx.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -82,6 +82,10 @@ static bool turbo_mode = true;
+ module_param(turbo_mode, bool, 0644);
+ MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
+
++static bool truesize_mode = false;
++module_param(truesize_mode, bool, 0644);
++MODULE_PARM_DESC(truesize_mode, "Report larger truesize value");
++
+ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data, int in_pm)
+ {
+@@ -1971,7 +1975,8 @@ static int smsc95xx_rx_fixup(struct usbn
+ if (dev->net->features & NETIF_F_RXCSUM)
+ smsc95xx_rx_csum_offload(skb);
+ skb_trim(skb, skb->len - 4); /* remove fcs */
+- skb->truesize = size + sizeof(struct sk_buff);
++ if (truesize_mode)
++ skb->truesize = size + sizeof(struct sk_buff);
+
+ return 1;
+ }
+@@ -1989,7 +1994,8 @@ static int smsc95xx_rx_fixup(struct usbn
+ if (dev->net->features & NETIF_F_RXCSUM)
+ smsc95xx_rx_csum_offload(ax_skb);
+ skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
+- ax_skb->truesize = size + sizeof(struct sk_buff);
++ if (truesize_mode)
++ ax_skb->truesize = size + sizeof(struct sk_buff);
+
+ usbnet_skb_return(dev, ax_skb);
+ }
--- /dev/null
+From 4e6c055ee7fbbe82449edafce4f1371116e6dcab Mon Sep 17 00:00:00 2001
+From: Sam Nazarko <email@samnazarko.co.uk>
+Date: Fri, 1 Apr 2016 17:27:21 +0100
+Subject: [PATCH 003/454] smsc95xx: Experimental: Enable turbo_mode and
+ packetsize=2560 by default
+
+See: http://forum.kodi.tv/showthread.php?tid=285288
+---
+ drivers/net/usb/smsc95xx.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -86,6 +86,10 @@ static bool truesize_mode = false;
+ module_param(truesize_mode, bool, 0644);
+ MODULE_PARM_DESC(truesize_mode, "Report larger truesize value");
+
++static int packetsize = 2560;
++module_param(packetsize, int, 0644);
++MODULE_PARM_DESC(packetsize, "Override the RX URB packet size");
++
+ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data, int in_pm)
+ {
+@@ -1109,13 +1113,13 @@ static int smsc95xx_reset(struct usbnet
+
+ if (!turbo_mode) {
+ burst_cap = 0;
+- dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
++ dev->rx_urb_size = packetsize ? packetsize : MAX_SINGLE_PACKET_SIZE;
+ } else if (dev->udev->speed == USB_SPEED_HIGH) {
+- burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
+- dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
++ dev->rx_urb_size = packetsize ? packetsize : DEFAULT_HS_BURST_CAP_SIZE;
++ burst_cap = dev->rx_urb_size / HS_USB_PKT_SIZE;
+ } else {
+- burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
+- dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
++ dev->rx_urb_size = packetsize ? packetsize : DEFAULT_FS_BURST_CAP_SIZE;
++ burst_cap = dev->rx_urb_size / FS_USB_PKT_SIZE;
+ }
+
+ netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
--- /dev/null
+From e592fc748cfc927a3c6ed098a21ece63b1efa682 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 26 Mar 2013 17:26:38 +0000
+Subject: [PATCH 004/454] Allow mac address to be set in smsc95xx
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -60,6 +60,7 @@
+ #define SUSPEND_SUSPEND3 (0x08)
+ #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+ SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
++#define MAC_ADDR_LEN (6)
+
+ #define CARRIER_CHECK_DELAY (2 * HZ)
+
+@@ -90,6 +91,10 @@ static int packetsize = 2560;
+ module_param(packetsize, int, 0644);
+ MODULE_PARM_DESC(packetsize, "Override the RX URB packet size");
+
++static char *macaddr = ":";
++module_param(macaddr, charp, 0);
++MODULE_PARM_DESC(macaddr, "MAC address");
++
+ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data, int in_pm)
+ {
+@@ -921,6 +926,53 @@ static int smsc95xx_ioctl(struct net_dev
+ return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+ }
+
++/* Check the macaddr module parameter for a MAC address */
++static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac)
++{
++ int i, j, got_num, num;
++ u8 mtbl[MAC_ADDR_LEN];
++
++ if (macaddr[0] == ':')
++ return 0;
++
++ i = 0;
++ j = 0;
++ num = 0;
++ got_num = 0;
++ while (j < MAC_ADDR_LEN) {
++ if (macaddr[i] && macaddr[i] != ':') {
++ got_num++;
++ if ('0' <= macaddr[i] && macaddr[i] <= '9')
++ num = num * 16 + macaddr[i] - '0';
++ else if ('A' <= macaddr[i] && macaddr[i] <= 'F')
++ num = num * 16 + 10 + macaddr[i] - 'A';
++ else if ('a' <= macaddr[i] && macaddr[i] <= 'f')
++ num = num * 16 + 10 + macaddr[i] - 'a';
++ else
++ break;
++ i++;
++ } else if (got_num == 2) {
++ mtbl[j++] = (u8) num;
++ num = 0;
++ got_num = 0;
++ i++;
++ } else {
++ break;
++ }
++ }
++
++ if (j == MAC_ADDR_LEN) {
++ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: "
++ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2],
++ mtbl[3], mtbl[4], mtbl[5]);
++ for (i = 0; i < MAC_ADDR_LEN; i++)
++ dev_mac[i] = mtbl[i];
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
+ static void smsc95xx_init_mac_address(struct usbnet *dev)
+ {
+ const u8 *mac_addr;
+@@ -942,6 +994,10 @@ static void smsc95xx_init_mac_address(st
+ }
+ }
+
++ /* Check module parameters */
++ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr))
++ return;
++
+ /* no useful static MAC address found. generate a random one */
+ eth_hw_addr_random(dev->net);
+ netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
--- /dev/null
+From f641853ee23864c1ea7c36553e6406662b8cd0ba Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 13 Mar 2015 12:43:36 +0000
+Subject: [PATCH 005/454] Protect __release_resource against resources without
+ parents
+
+Without this patch, removing a device tree overlay can crash here.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ kernel/resource.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -246,6 +246,12 @@ static int __release_resource(struct res
+ {
+ struct resource *tmp, **p, *chd;
+
++ if (!old->parent) {
++ WARN(old->sibling, "sibling but no parent");
++ if (old->sibling)
++ return -EINVAL;
++ return 0;
++ }
+ p = &old->parent->child;
+ for (;;) {
+ tmp = *p;
--- /dev/null
+From 1d7fd600451fbca94e968f552e5e663e3aa36c61 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 4 Dec 2015 17:41:50 +0000
+Subject: [PATCH 006/454] irq-bcm2836: Prevent spurious interrupts, and trap
+ them early
+
+The old arch-specific IRQ macros included a dsb to ensure the
+write to clear the mailbox interrupt completed before returning
+from the interrupt. The BCM2836 irqchip driver needs the same
+precaution to avoid spurious interrupts.
+
+Spurious interrupts are still possible for other reasons,
+though, so trap them early.
+---
+ drivers/irqchip/irq-bcm2836.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/irqchip/irq-bcm2836.c
++++ b/drivers/irqchip/irq-bcm2836.c
+@@ -175,6 +175,7 @@ __exception_irq_entry bcm2836_arm_irqchi
+ u32 ipi = ffs(mbox_val) - 1;
+
+ writel(1 << ipi, mailbox0);
++ dsb(sy);
+ handle_IPI(ipi, regs);
+ #endif
+ } else if (stat) {
--- /dev/null
+From 00931bb3a62ff22372284e8797ed17816beb264a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 9 Feb 2017 14:33:30 +0000
+Subject: [PATCH 007/454] irq-bcm2836: Avoid "Invalid trigger warning"
+
+Initialise the level for each IRQ to avoid a warning from the
+arm arch timer code.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/irqchip/irq-bcm2836.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/irqchip/irq-bcm2836.c
++++ b/drivers/irqchip/irq-bcm2836.c
+@@ -157,7 +157,7 @@ static void bcm2836_arm_irqchip_register
+
+ irq_set_percpu_devid(irq);
+ irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq);
+- irq_set_status_flags(irq, IRQ_NOAUTOEN);
++ irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_TYPE_LEVEL_LOW);
+ }
+
+ static void
--- /dev/null
+From 3bf3bf7064d688dae7fdf7b49b28073eccd9dd99 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Fri, 12 Jun 2015 19:01:05 +0200
+Subject: [PATCH 008/454] irqchip: bcm2835: Add FIQ support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add a duplicate irq range with an offset on the hwirq's so the
+driver can detect that enable_fiq() is used.
+Tested with downstream dwc_otg USB controller driver.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Acked-by: Stephen Warren <swarren@wwwdotorg.org>
+---
+ arch/arm/mach-bcm/Kconfig | 1 +
+ drivers/irqchip/irq-bcm2835.c | 51 +++++++++++++++++++++++++++++++----
+ 2 files changed, 47 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/mach-bcm/Kconfig
++++ b/arch/arm/mach-bcm/Kconfig
+@@ -155,6 +155,7 @@ config ARCH_BCM2835
+ select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
+ select TIMER_OF
+ select BCM2835_TIMER
++ select FIQ
+ select PINCTRL
+ select PINCTRL_BCM2835
+ help
+--- a/drivers/irqchip/irq-bcm2835.c
++++ b/drivers/irqchip/irq-bcm2835.c
+@@ -54,7 +54,7 @@
+ #include <asm/exception.h>
+
+ /* Put the bank and irq (32 bits) into the hwirq */
+-#define MAKE_HWIRQ(b, n) ((b << 5) | (n))
++#define MAKE_HWIRQ(b, n) (((b) << 5) | (n))
+ #define HWIRQ_BANK(i) (i >> 5)
+ #define HWIRQ_BIT(i) BIT(i & 0x1f)
+
+@@ -70,9 +70,13 @@
+ | SHORTCUT1_MASK | SHORTCUT2_MASK)
+
+ #define REG_FIQ_CONTROL 0x0c
++#define REG_FIQ_ENABLE 0x80
++#define REG_FIQ_DISABLE 0
+
+ #define NR_BANKS 3
+ #define IRQS_PER_BANK 32
++#define NUMBER_IRQS MAKE_HWIRQ(NR_BANKS, 0)
++#define FIQ_START (NR_IRQS_BANK0 + MAKE_HWIRQ(NR_BANKS - 1, 0))
+
+ static const int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
+ static const int reg_enable[] __initconst = { 0x18, 0x10, 0x14 };
+@@ -97,14 +101,38 @@ static void __exception_irq_entry bcm283
+ struct pt_regs *regs);
+ static void bcm2836_chained_handle_irq(struct irq_desc *desc);
+
++static inline unsigned int hwirq_to_fiq(unsigned long hwirq)
++{
++ hwirq -= NUMBER_IRQS;
++ /*
++ * The hwirq numbering used in this driver is:
++ * BASE (0-7) GPU1 (32-63) GPU2 (64-95).
++ * This differ from the one used in the FIQ register:
++ * GPU1 (0-31) GPU2 (32-63) BASE (64-71)
++ */
++ if (hwirq >= 32)
++ return hwirq - 32;
++
++ return hwirq + 64;
++}
++
+ static void armctrl_mask_irq(struct irq_data *d)
+ {
+- writel_relaxed(HWIRQ_BIT(d->hwirq), intc.disable[HWIRQ_BANK(d->hwirq)]);
++ if (d->hwirq >= NUMBER_IRQS)
++ writel_relaxed(REG_FIQ_DISABLE, intc.base + REG_FIQ_CONTROL);
++ else
++ writel_relaxed(HWIRQ_BIT(d->hwirq),
++ intc.disable[HWIRQ_BANK(d->hwirq)]);
+ }
+
+ static void armctrl_unmask_irq(struct irq_data *d)
+ {
+- writel_relaxed(HWIRQ_BIT(d->hwirq), intc.enable[HWIRQ_BANK(d->hwirq)]);
++ if (d->hwirq >= NUMBER_IRQS)
++ writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
++ intc.base + REG_FIQ_CONTROL);
++ else
++ writel_relaxed(HWIRQ_BIT(d->hwirq),
++ intc.enable[HWIRQ_BANK(d->hwirq)]);
+ }
+
+ static struct irq_chip armctrl_chip = {
+@@ -149,8 +177,9 @@ static int __init armctrl_of_init(struct
+ if (!base)
+ panic("%pOF: unable to map IC registers\n", node);
+
+- intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
+- &armctrl_ops, NULL);
++ intc.base = base;
++ intc.domain = irq_domain_add_linear(node, NUMBER_IRQS * 2,
++ &armctrl_ops, NULL);
+ if (!intc.domain)
+ panic("%pOF: unable to create IRQ domain\n", node);
+
+@@ -180,6 +209,18 @@ static int __init armctrl_of_init(struct
+ set_handle_irq(bcm2835_handle_irq);
+ }
+
++ /* Make a duplicate irq range which is used to enable FIQ */
++ for (b = 0; b < NR_BANKS; b++) {
++ for (i = 0; i < bank_irqs[b]; i++) {
++ irq = irq_create_mapping(intc.domain,
++ MAKE_HWIRQ(b, i) + NUMBER_IRQS);
++ BUG_ON(irq <= 0);
++ irq_set_chip(irq, &armctrl_chip);
++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++ }
++ }
++ init_FIQ(FIQ_START);
++
+ return 0;
+ }
+
--- /dev/null
+From 1d8af4d16ff95154c134b060900aefac133c50b6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Fri, 23 Oct 2015 16:26:55 +0200
+Subject: [PATCH 009/454] irqchip: irq-bcm2835: Add 2836 FIQ support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+---
+ drivers/irqchip/irq-bcm2835.c | 43 +++++++++++++++++++++++++++++++++--
+ 1 file changed, 41 insertions(+), 2 deletions(-)
+
+--- a/drivers/irqchip/irq-bcm2835.c
++++ b/drivers/irqchip/irq-bcm2835.c
+@@ -50,8 +50,11 @@
+ #include <linux/of_irq.h>
+ #include <linux/irqchip.h>
+ #include <linux/irqdomain.h>
++#include <linux/mfd/syscon.h>
++#include <linux/regmap.h>
+
+ #include <asm/exception.h>
++#include <asm/mach/irq.h>
+
+ /* Put the bank and irq (32 bits) into the hwirq */
+ #define MAKE_HWIRQ(b, n) (((b) << 5) | (n))
+@@ -69,6 +72,9 @@
+ #define BANK0_VALID_MASK (BANK0_HWIRQ_MASK | BANK1_HWIRQ | BANK2_HWIRQ \
+ | SHORTCUT1_MASK | SHORTCUT2_MASK)
+
++#undef ARM_LOCAL_GPU_INT_ROUTING
++#define ARM_LOCAL_GPU_INT_ROUTING 0x0c
++
+ #define REG_FIQ_CONTROL 0x0c
+ #define REG_FIQ_ENABLE 0x80
+ #define REG_FIQ_DISABLE 0
+@@ -94,6 +100,7 @@ struct armctrl_ic {
+ void __iomem *enable[NR_BANKS];
+ void __iomem *disable[NR_BANKS];
+ struct irq_domain *domain;
++ struct regmap *local_regmap;
+ };
+
+ static struct armctrl_ic intc __read_mostly;
+@@ -127,12 +134,35 @@ static void armctrl_mask_irq(struct irq_
+
+ static void armctrl_unmask_irq(struct irq_data *d)
+ {
+- if (d->hwirq >= NUMBER_IRQS)
++ if (d->hwirq >= NUMBER_IRQS) {
++ if (num_online_cpus() > 1) {
++ unsigned int data;
++ int ret;
++
++ if (!intc.local_regmap) {
++ pr_err("FIQ is disabled due to missing regmap\n");
++ return;
++ }
++
++ ret = regmap_read(intc.local_regmap,
++ ARM_LOCAL_GPU_INT_ROUTING, &data);
++ if (ret) {
++ pr_err("Failed to read int routing %d\n", ret);
++ return;
++ }
++
++ data &= ~0xc;
++ data |= (1 << 2);
++ regmap_write(intc.local_regmap,
++ ARM_LOCAL_GPU_INT_ROUTING, data);
++ }
++
+ writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
+ intc.base + REG_FIQ_CONTROL);
+- else
++ } else {
+ writel_relaxed(HWIRQ_BIT(d->hwirq),
+ intc.enable[HWIRQ_BANK(d->hwirq)]);
++ }
+ }
+
+ static struct irq_chip armctrl_chip = {
+@@ -209,6 +239,15 @@ static int __init armctrl_of_init(struct
+ set_handle_irq(bcm2835_handle_irq);
+ }
+
++ if (is_2836) {
++ intc.local_regmap =
++ syscon_regmap_lookup_by_compatible("brcm,bcm2836-arm-local");
++ if (IS_ERR(intc.local_regmap)) {
++ pr_err("Failed to get local register map. FIQ is disabled for cpus > 1\n");
++ intc.local_regmap = NULL;
++ }
++ }
++
+ /* Make a duplicate irq range which is used to enable FIQ */
+ for (b = 0; b < NR_BANKS; b++) {
+ for (i = 0; i < bank_irqs[b]; i++) {
--- /dev/null
+From 6b8b69ff7c4c25f01535cbe49a80516df6dbcfe8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 8 May 2017 16:43:40 +0100
+Subject: [PATCH 010/454] irq_bcm2836: Send event when onlining sleeping cores
+
+In order to reduce power consumption and bus traffic, it is sensible
+for secondary cores to enter a low-power idle state when waiting to
+be started. The wfe instruction causes a core to wait until an event
+or interrupt arrives before continuing to the next instruction.
+The sev instruction sends a wakeup event to the other cores, so call
+it from bcm2836_smp_boot_secondary, the function that wakes up the
+waiting cores during booting.
+
+It is harmless to use this patch without the corresponding change
+adding wfe to the ARMv7/ARMv8-32 stubs, but if the stubs are updated
+and this patch is not applied then the other cores will sleep forever.
+
+See: https://github.com/raspberrypi/linux/issues/1989
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/irqchip/irq-bcm2836.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/irqchip/irq-bcm2836.c
++++ b/drivers/irqchip/irq-bcm2836.c
+@@ -227,6 +227,9 @@ static int __init bcm2836_smp_boot_secon
+ writel(secondary_startup_phys,
+ intc.base + LOCAL_MAILBOX3_SET0 + 16 * cpu);
+
++ dsb(sy); /* Ensure write has completed before waking the other CPUs */
++ sev();
++
+ return 0;
+ }
+
--- /dev/null
+From 5e12841c484176b869a26955fc73730720e52b67 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 14 Jul 2015 10:26:09 +0100
+Subject: [PATCH 011/454] spidev: Add "spidev" compatible string to silence
+ warning
+
+See: https://github.com/raspberrypi/linux/issues/1054
+---
+ drivers/spi/spidev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/spi/spidev.c
++++ b/drivers/spi/spidev.c
+@@ -670,6 +670,7 @@ static const struct of_device_id spidev_
+ { .compatible = "ge,achc" },
+ { .compatible = "semtech,sx1301" },
+ { .compatible = "siliconlabs,si3210" },
++ { .compatible = "spidev" },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, spidev_dt_ids);
--- /dev/null
+From e27613dee9bede1a5d8c86c3cdc5244175651534 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 24 Jun 2015 14:10:44 +0100
+Subject: [PATCH 012/454] spi-bcm2835: Support pin groups other than 7-11
+
+The spi-bcm2835 driver automatically uses GPIO chip-selects due to
+some unreliability of the native ones. In doing so it chooses the
+same pins as the native chip-selects would use, but the existing
+code always uses pins 7 and 8, wherever the SPI function is mapped.
+
+Search the pinctrl group assigned to the driver for pins that
+correspond to native chip-selects, and use those for GPIO chip-
+selects.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/spi/spi-bcm2835.c | 45 ++++++++++++++++++++++++++++++++-------
+ 1 file changed, 37 insertions(+), 8 deletions(-)
+
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -688,6 +688,8 @@ static int bcm2835_spi_setup(struct spi_
+ {
+ int err;
+ struct gpio_chip *chip;
++ struct device_node *pins;
++ u32 pingroup_index;
+ /*
+ * sanity checking the native-chipselects
+ */
+@@ -704,15 +706,42 @@ static int bcm2835_spi_setup(struct spi_
+ "setup: only two native chip-selects are supported\n");
+ return -EINVAL;
+ }
+- /* now translate native cs to GPIO */
+
+- /* get the gpio chip for the base */
+- chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
+- if (!chip)
+- return 0;
++ /* now translate native cs to GPIO */
++ /* first look for chip select pins in the devices pin groups */
++ for (pingroup_index = 0;
++ (pins = of_parse_phandle(spi->master->dev.of_node,
++ "pinctrl-0",
++ pingroup_index)) != 0;
++ pingroup_index++) {
++ u32 pin;
++ u32 pin_index;
++ for (pin_index = 0;
++ of_property_read_u32_index(pins,
++ "brcm,pins",
++ pin_index,
++ &pin) == 0;
++ pin_index++) {
++ if (((spi->chip_select == 0) &&
++ ((pin == 8) || (pin == 36) || (pin == 46))) ||
++ ((spi->chip_select == 1) &&
++ ((pin == 7) || (pin == 35)))) {
++ spi->cs_gpio = pin;
++ break;
++ }
++ }
++ of_node_put(pins);
++ }
++ /* if that fails, assume GPIOs 7-11 are used */
++ if (!gpio_is_valid(spi->cs_gpio) ) {
++ /* get the gpio chip for the base */
++ chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
++ if (!chip)
++ return 0;
+
+- /* and calculate the real CS */
+- spi->cs_gpio = chip->base + 8 - spi->chip_select;
++ /* and calculate the real CS */
++ spi->cs_gpio = chip->base + 8 - spi->chip_select;
++ }
+
+ /* and set up the "mode" and level */
+ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n",
--- /dev/null
+From 6af2125a4aa2bfacda4e7c01ed3214a3a866eab6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Fri, 1 Jul 2016 22:09:24 +0100
+Subject: [PATCH 013/454] spi-bcm2835: Disable forced software CS
+
+Select software CS in bcm2708_common.dtsi, and disable the automatic
+conversion in the driver to allow hardware CS to be re-enabled with an
+overlay.
+
+See: https://github.com/raspberrypi/linux/issues/1547
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/spi/spi-bcm2835.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -707,6 +707,7 @@ static int bcm2835_spi_setup(struct spi_
+ return -EINVAL;
+ }
+
++#if 0
+ /* now translate native cs to GPIO */
+ /* first look for chip select pins in the devices pin groups */
+ for (pingroup_index = 0;
+@@ -756,6 +757,7 @@ static int bcm2835_spi_setup(struct spi_
+ spi->chip_select, spi->cs_gpio, err);
+ return err;
+ }
++#endif
+
+ return 0;
+ }
--- /dev/null
+From 538bc2e4d22633d87f2e4689edfd1f313baf61ab Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 8 Nov 2016 21:35:38 +0000
+Subject: [PATCH 014/454] spi-bcm2835: Remove unused code
+
+---
+ drivers/spi/spi-bcm2835.c | 61 ---------------------------------------
+ 1 file changed, 61 deletions(-)
+
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -679,17 +679,8 @@ static void bcm2835_spi_set_cs(struct sp
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+ }
+
+-static int chip_match_name(struct gpio_chip *chip, void *data)
+-{
+- return !strcmp(chip->label, data);
+-}
+-
+ static int bcm2835_spi_setup(struct spi_device *spi)
+ {
+- int err;
+- struct gpio_chip *chip;
+- struct device_node *pins;
+- u32 pingroup_index;
+ /*
+ * sanity checking the native-chipselects
+ */
+@@ -707,58 +698,6 @@ static int bcm2835_spi_setup(struct spi_
+ return -EINVAL;
+ }
+
+-#if 0
+- /* now translate native cs to GPIO */
+- /* first look for chip select pins in the devices pin groups */
+- for (pingroup_index = 0;
+- (pins = of_parse_phandle(spi->master->dev.of_node,
+- "pinctrl-0",
+- pingroup_index)) != 0;
+- pingroup_index++) {
+- u32 pin;
+- u32 pin_index;
+- for (pin_index = 0;
+- of_property_read_u32_index(pins,
+- "brcm,pins",
+- pin_index,
+- &pin) == 0;
+- pin_index++) {
+- if (((spi->chip_select == 0) &&
+- ((pin == 8) || (pin == 36) || (pin == 46))) ||
+- ((spi->chip_select == 1) &&
+- ((pin == 7) || (pin == 35)))) {
+- spi->cs_gpio = pin;
+- break;
+- }
+- }
+- of_node_put(pins);
+- }
+- /* if that fails, assume GPIOs 7-11 are used */
+- if (!gpio_is_valid(spi->cs_gpio) ) {
+- /* get the gpio chip for the base */
+- chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
+- if (!chip)
+- return 0;
+-
+- /* and calculate the real CS */
+- spi->cs_gpio = chip->base + 8 - spi->chip_select;
+- }
+-
+- /* and set up the "mode" and level */
+- dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n",
+- spi->chip_select, spi->cs_gpio);
+-
+- /* set up GPIO as output and pull to the correct level */
+- err = gpio_direction_output(spi->cs_gpio,
+- (spi->mode & SPI_CS_HIGH) ? 0 : 1);
+- if (err) {
+- dev_err(&spi->dev,
+- "could not set CS%i gpio %i as output: %i",
+- spi->chip_select, spi->cs_gpio, err);
+- return err;
+- }
+-#endif
+-
+ return 0;
+ }
+
--- /dev/null
+From 524b23e8fd0b05840b2eec5686389ead822983ef Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Wed, 3 Jun 2015 12:26:13 +0200
+Subject: [PATCH 015/454] ARM: bcm2835: Set Serial number and Revision
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The VideoCore bootloader passes in Serial number and
+Revision number through Device Tree. Make these available to
+userspace through /proc/cpuinfo.
+
+Mainline status:
+
+There is a commit in linux-next that standardize passing the serial
+number through Device Tree (string: /serial-number):
+ARM: 8355/1: arch: Show the serial number from devicetree in cpuinfo
+
+There was an attempt to do the same with the revision number, but it
+didn't get in:
+[PATCH v2 1/2] arm: devtree: Set system_rev from DT revision
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+---
+ arch/arm/mach-bcm/board_bcm2835.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -16,13 +16,23 @@
+ #include <linux/irqchip.h>
+ #include <linux/of_address.h>
+ #include <linux/clk/bcm2835.h>
++#include <asm/system_info.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+
+ static void __init bcm2835_init(void)
+ {
++ struct device_node *np = of_find_node_by_path("/system");
++ u32 val;
++ u64 val64;
++
+ bcm2835_init_clocks();
++
++ if (!of_property_read_u32(np, "linux,revision", &val))
++ system_rev = val;
++ if (!of_property_read_u64(np, "linux,serial", &val64))
++ system_serial_low = val64;
+ }
+
+ static const char * const bcm2835_compat[] = {
--- /dev/null
+From 8a9eb6f0ef9e548aaa5ac60e95e4c0c9c99adcab Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Sat, 3 Oct 2015 22:22:55 +0200
+Subject: [PATCH 016/454] dmaengine: bcm2835: Load driver early and support
+ legacy API
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Load driver early since at least bcm2708_fb doesn't support deferred
+probing and even if it did, we don't want the video driver deferred.
+Support the legacy DMA API which is needed by bcm2708_fb.
+Don't mask out channel 2.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+---
+ drivers/dma/Kconfig | 2 +-
+ drivers/dma/bcm2835-dma.c | 26 +++++++++++++++++++++++++-
+ 2 files changed, 26 insertions(+), 2 deletions(-)
+
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -131,7 +131,7 @@ config COH901318
+
+ config DMA_BCM2835
+ tristate "BCM2835 DMA engine support"
+- depends on ARCH_BCM2835
++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -37,6 +37,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/list.h>
+ #include <linux/module.h>
++#include <linux/platform_data/dma-bcm2708.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/io.h>
+@@ -48,6 +49,7 @@
+
+ #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
+ #define BCM2835_DMA_CHAN_NAME_SIZE 8
++#define BCM2835_DMA_BULK_MASK BIT(0)
+
+ struct bcm2835_dmadev {
+ struct dma_device ddev;
+@@ -925,6 +927,9 @@ static int bcm2835_dma_probe(struct plat
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
++ rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK);
++ if (rc)
++ dev_err(&pdev->dev, "Failed to initialize the legacy API\n");
+
+ od->base = base;
+
+@@ -962,6 +967,9 @@ static int bcm2835_dma_probe(struct plat
+ goto err_no_dma;
+ }
+
++ /* Channel 0 is used by the legacy API */
++ chans_available &= ~BCM2835_DMA_BULK_MASK;
++
+ /* get irqs for each channel that we support */
+ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
+ /* skip masked out channels */
+@@ -1036,6 +1044,7 @@ static int bcm2835_dma_remove(struct pla
+ {
+ struct bcm2835_dmadev *od = platform_get_drvdata(pdev);
+
++ bcm_dmaman_remove(pdev);
+ dma_async_device_unregister(&od->ddev);
+ bcm2835_dma_free(od);
+
+@@ -1051,7 +1060,22 @@ static struct platform_driver bcm2835_dm
+ },
+ };
+
+-module_platform_driver(bcm2835_dma_driver);
++static int bcm2835_dma_init(void)
++{
++ return platform_driver_register(&bcm2835_dma_driver);
++}
++
++static void bcm2835_dma_exit(void)
++{
++ platform_driver_unregister(&bcm2835_dma_driver);
++}
++
++/*
++ * Load after serial driver (arch_initcall) so we see the messages if it fails,
++ * but before drivers (module_init) that need a DMA channel.
++ */
++subsys_initcall(bcm2835_dma_init);
++module_exit(bcm2835_dma_exit);
+
+ MODULE_ALIAS("platform:bcm2835-dma");
+ MODULE_DESCRIPTION("BCM2835 DMA engine driver");
--- /dev/null
+From b9570d562487b4d9ec176838b020b02815356511 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 25 Jan 2016 17:25:12 +0000
+Subject: [PATCH 017/454] firmware: Updated mailbox header
+
+---
+ include/soc/bcm2835/raspberrypi-firmware.h | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -12,6 +12,8 @@
+ #include <linux/types.h>
+ #include <linux/of_device.h>
+
++#define RPI_FIRMWARE_CHAN_FB 1
++
+ struct rpi_firmware;
+
+ enum rpi_firmware_property_status {
+@@ -63,6 +65,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008,
+ RPI_FIRMWARE_GET_TURBO = 0x00030009,
+ RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a,
++ RPI_FIRMWARE_GET_STC = 0x0003000b,
+ RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c,
+ RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d,
+ RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e,
+@@ -72,12 +75,22 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012,
+ RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
+ RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
++ RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
+ RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
+ RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
+ RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
+ RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
+ RPI_FIRMWARE_SET_TURBO = 0x00038009,
++ RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021,
+ RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030,
++ RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041,
++ RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041,
++ RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042,
++ RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043,
++ RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043,
++ RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045,
++ RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045,
++
+
+ /* Dispmanx TAGS */
+ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001,
+@@ -91,6 +104,8 @@ 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_TOUCHBUF = 0x0004000f,
++ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
+ RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
+@@ -100,6 +115,7 @@ 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_VSYNC = 0x0004400e,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
+@@ -108,6 +124,10 @@ enum rpi_firmware_property_tag {
+ 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_BACKLIGHT = 0x0004800f,
+
+ RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+
+@@ -139,5 +159,6 @@ static inline struct rpi_firmware *rpi_f
+ return NULL;
+ }
+ #endif
++int rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data);
+
+ #endif /* __SOC_RASPBERRY_FIRMWARE_H__ */
--- /dev/null
+From 2630e731569dd34a084bc14fceb52d114604d84b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 15 Jun 2016 16:48:41 +0100
+Subject: [PATCH 018/454] rtc: Add SPI alias for pcf2123 driver
+
+Without this alias, Device Tree won't cause the driver
+to be loaded.
+
+See: https://github.com/raspberrypi/linux/pull/1510
+---
+ drivers/rtc/rtc-pcf2123.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/rtc/rtc-pcf2123.c
++++ b/drivers/rtc/rtc-pcf2123.c
+@@ -472,3 +472,4 @@ module_spi_driver(pcf2123_driver);
+ MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>");
+ MODULE_DESCRIPTION("NXP PCF2123 RTC driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("spi:rtc-pcf2123");
--- /dev/null
+From e9ee8ed10620ed2e4474af53cb23058b034a6e56 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Fri, 7 Oct 2016 16:50:59 +0200
+Subject: [PATCH 019/454] watchdog: bcm2835: Support setting reboot partition
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The Raspberry Pi firmware looks at the RSTS register to know which
+partition to boot from. The reboot syscall command
+LINUX_REBOOT_CMD_RESTART2 supports passing in a string argument.
+
+Add support for passing in a partition number 0..63 to boot from.
+Partition 63 is a special partiton indicating halt.
+If the partition doesn't exist, the firmware falls back to partition 0.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+---
+ drivers/watchdog/bcm2835_wdt.c | 49 +++++++++++++++++++---------------
+ 1 file changed, 27 insertions(+), 22 deletions(-)
+
+--- a/drivers/watchdog/bcm2835_wdt.c
++++ b/drivers/watchdog/bcm2835_wdt.c
+@@ -34,13 +34,7 @@
+ #define PM_RSTC_WRCFG_SET 0x00000030
+ #define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+ #define PM_RSTC_RESET 0x00000102
+-
+-/*
+- * The Raspberry Pi firmware uses the RSTS register to know which partition
+- * to boot from. The partition value is spread into bits 0, 2, 4, 6, 8, 10.
+- * Partition 63 is a special partition used by the firmware to indicate halt.
+- */
+-#define PM_RSTS_RASPBERRYPI_HALT 0x555
++#define PM_RSTS_PARTITION_CLR 0xfffffaaa
+
+ #define SECS_TO_WDOG_TICKS(x) ((x) << 16)
+ #define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
+@@ -97,9 +91,24 @@ static unsigned int bcm2835_wdt_get_time
+ return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
+ }
+
+-static void __bcm2835_restart(struct bcm2835_wdt *wdt)
++/*
++ * The Raspberry Pi firmware uses the RSTS register to know which partiton
++ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10.
++ * Partiton 63 is a special partition used by the firmware to indicate halt.
++ */
++
++static void __bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition)
+ {
+- u32 val;
++ u32 val, rsts;
++
++ rsts = (partition & BIT(0)) | ((partition & BIT(1)) << 1) |
++ ((partition & BIT(2)) << 2) | ((partition & BIT(3)) << 3) |
++ ((partition & BIT(4)) << 4) | ((partition & BIT(5)) << 5);
++
++ val = readl_relaxed(wdt->base + PM_RSTS);
++ val &= PM_RSTS_PARTITION_CLR;
++ val |= PM_PASSWORD | rsts;
++ writel_relaxed(val, wdt->base + PM_RSTS);
+
+ /* use a timeout of 10 ticks (~150us) */
+ writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG);
+@@ -117,7 +126,13 @@ static int bcm2835_restart(struct watchd
+ {
+ struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog);
+
+- __bcm2835_restart(wdt);
++ unsigned long long val;
++ u8 partition = 0;
++
++ if (data && !kstrtoull(data, 0, &val) && val <= 63)
++ partition = val;
++
++ __bcm2835_restart(wdt, partition);
+
+ return 0;
+ }
+@@ -155,19 +170,9 @@ static void bcm2835_power_off(void)
+ of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt");
+ struct platform_device *pdev = of_find_device_by_node(np);
+ struct bcm2835_wdt *wdt = platform_get_drvdata(pdev);
+- u32 val;
+-
+- /*
+- * We set the watchdog hard reset bit here to distinguish this reset
+- * from the normal (full) reset. bootcode.bin will not reboot after a
+- * hard reset.
+- */
+- val = readl_relaxed(wdt->base + PM_RSTS);
+- val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT;
+- writel_relaxed(val, wdt->base + PM_RSTS);
+
+- /* Continue with normal reset mechanism */
+- __bcm2835_restart(wdt);
++ /* Partition 63 tells the firmware that this is a halt */
++ __bcm2835_restart(wdt, 63);
+ }
+
+ static int bcm2835_wdt_probe(struct platform_device *pdev)
--- /dev/null
+From ac6e6825886db6760ba756f675e92fcdbd7634d4 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 5 Apr 2016 19:40:12 +0100
+Subject: [PATCH 020/454] reboot: Use power off rather than busy spinning when
+ halt is requested
+
+---
+ arch/arm/kernel/reboot.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/arch/arm/kernel/reboot.c
++++ b/arch/arm/kernel/reboot.c
+@@ -105,9 +105,7 @@ void machine_shutdown(void)
+ */
+ void machine_halt(void)
+ {
+- local_irq_disable();
+- smp_send_stop();
+- while (1);
++ machine_power_off();
+ }
+
+ /*
--- /dev/null
+From 9a4491019545e135376214b0014d6a2b4c780d02 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Wed, 9 Nov 2016 13:02:52 +0000
+Subject: [PATCH 021/454] bcm: Make RASPBERRYPI_POWER depend on PM
+
+---
+ drivers/soc/bcm/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/soc/bcm/Kconfig
++++ b/drivers/soc/bcm/Kconfig
+@@ -4,6 +4,7 @@ config RASPBERRYPI_POWER
+ bool "Raspberry Pi power domain driver"
+ depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
+ depends on RASPBERRYPI_FIRMWARE=y
++ depends on PM
+ select PM_GENERIC_DOMAINS if PM
+ help
+ This enables support for the RPi power domains which can be enabled
--- /dev/null
+From 5881d7a1df54ac9b0acf618d970737479b2f6721 Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Fri, 2 Sep 2016 16:45:27 +0100
+Subject: [PATCH 022/454] Register the clocks early during the boot process, so
+ that special/critical clocks can get enabled early on in the boot process
+ avoiding the risk of disabling a clock, pll_divider or pll when a claiming
+ driver fails to install propperly - maybe it needs to defer.
+
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -2220,8 +2220,15 @@ static int bcm2835_clk_probe(struct plat
+ if (ret)
+ return ret;
+
+- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
++ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+ &cprman->onecell);
++ if (ret)
++ return ret;
++
++ /* note that we have registered all the clocks */
++ dev_dbg(dev, "registered %d clocks\n", asize);
++
++ return 0;
+ }
+
+ static const struct of_device_id bcm2835_clk_of_match[] = {
+@@ -2238,7 +2245,11 @@ static struct platform_driver bcm2835_cl
+ .probe = bcm2835_clk_probe,
+ };
+
+-builtin_platform_driver(bcm2835_clk_driver);
++static int __init __bcm2835_clk_driver_init(void)
++{
++ return platform_driver_register(&bcm2835_clk_driver);
++}
++core_initcall(__bcm2835_clk_driver_init);
+
+ MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+ MODULE_DESCRIPTION("BCM2835 clock driver");
--- /dev/null
+From 3c343d373b5de2837e9dd827fe9b44f2563186cb Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 6 Dec 2016 17:05:39 +0000
+Subject: [PATCH 023/454] bcm2835-rng: Avoid initialising if already enabled
+
+Avoids the 0x40000 cycles of warmup again if firmware has already used it
+---
+ drivers/char/hw_random/bcm2835-rng.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/char/hw_random/bcm2835-rng.c
++++ b/drivers/char/hw_random/bcm2835-rng.c
+@@ -102,9 +102,10 @@ static int bcm2835_rng_probe(struct plat
+ rng_setup(rng_base);
+
+ /* set warm-up count & enable */
+- __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
+- __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
+-
++ if (!(__raw_readl(rng_base + RNG_CTRL) & RNG_RBGEN)) {
++ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
++ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
++ }
+ /* register driver */
+ err = hwrng_register(&bcm2835_rng_ops);
+ if (err) {
--- /dev/null
+From 4d4ac64c781eb1d565c896d6614feed9c89b1957 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 24 Aug 2016 16:28:44 +0100
+Subject: [PATCH 024/454] kbuild: Ignore dtco targets when filtering symbols
+
+---
+ scripts/Kbuild.include | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/scripts/Kbuild.include
++++ b/scripts/Kbuild.include
+@@ -294,7 +294,7 @@ ksym_dep_filter =
+ $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \
+ as_*_S|cpp_s_S) \
+ $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \
+- boot*|build*|cpp_its_S|*cpp_lds_S|dtc|host*|vdso*) : ;; \
++ boot*|build*|cpp_its_S|*cpp_lds_S|dtc*|host*|vdso*) : ;; \
+ *) echo "Don't know how to preprocess $(1)" >&2; false ;; \
+ esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p'
+
--- /dev/null
+From ecabc19a9d6a889382771e3126ed413b3a51825a Mon Sep 17 00:00:00 2001
+From: Robert Tiemann <rtie@gmx.de>
+Date: Mon, 20 Jul 2015 11:01:25 +0200
+Subject: [PATCH 025/454] BCM2835_DT: Fix I2S register map
+
+---
+ Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++--
+ Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt
++++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt
+@@ -74,8 +74,8 @@ Example:
+
+ bcm2835_i2s: i2s@7e203000 {
+ compatible = "brcm,bcm2835-i2s";
+- reg = < 0x7e203000 0x20>,
+- < 0x7e101098 0x02>;
++ reg = < 0x7e203000 0x24>,
++ < 0x7e101098 0x08>;
+
+ dmas = <&dma 2>,
+ <&dma 3>;
+--- a/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt
++++ b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt
+@@ -16,8 +16,8 @@ Example:
+
+ bcm2835_i2s: i2s@7e203000 {
+ compatible = "brcm,bcm2835-i2s";
+- reg = <0x7e203000 0x20>,
+- <0x7e101098 0x02>;
++ reg = <0x7e203000 0x24>,
++ <0x7e101098 0x08>;
+
+ dmas = <&dma 2>,
+ <&dma 3>;
--- /dev/null
+From 39c54b332bfe3cb95221b663d38b5b620e47c912 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 13 Feb 2017 17:20:08 +0000
+Subject: [PATCH 026/454] clk-bcm2835: Mark used PLLs and dividers CRITICAL
+
+The VPU configures and relies on several PLLs and dividers. Mark all
+enabled dividers and their PLLs as CRITICAL to prevent the kernel from
+switching them off.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1397,6 +1397,11 @@ bcm2835_register_pll_divider(struct bcm2
+ divider->div.hw.init = &init;
+ divider->div.table = NULL;
+
++ if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) {
++ init.flags |= CLK_IS_CRITICAL;
++ divider->div.flags |= CLK_IS_CRITICAL;
++ }
++
+ divider->cprman = cprman;
+ divider->data = data;
+
--- /dev/null
+From 7a4c12de72b705c93482f3dd28b230ced588052f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 13 Feb 2017 17:20:08 +0000
+Subject: [PATCH 027/454] clk-bcm2835: Add claim-clocks property
+
+The claim-clocks property can be used to prevent PLLs and dividers
+from being marked as critical. It contains a vector of clock IDs,
+as defined by dt-bindings/clock/bcm2835.h.
+
+Use this mechanism to claim PLLD_DSI0, PLLD_DSI1, PLLH_AUX and
+PLLH_PIX for the vc4_kms_v3d driver.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 34 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 32 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1329,6 +1329,8 @@ static const struct clk_ops bcm2835_vpu_
+ .debug_init = bcm2835_clock_debug_init,
+ };
+
++static bool bcm2835_clk_is_claimed(const char *name);
++
+ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
+ const struct bcm2835_pll_data *data)
+ {
+@@ -1345,6 +1347,9 @@ static struct clk_hw *bcm2835_register_p
+ init.ops = &bcm2835_pll_clk_ops;
+ init.flags = CLK_IGNORE_UNUSED;
+
++ if (!bcm2835_clk_is_claimed(data->name))
++ init.flags |= CLK_IS_CRITICAL;
++
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return NULL;
+@@ -1398,8 +1403,10 @@ bcm2835_register_pll_divider(struct bcm2
+ divider->div.table = NULL;
+
+ if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) {
+- init.flags |= CLK_IS_CRITICAL;
+- divider->div.flags |= CLK_IS_CRITICAL;
++ if (!bcm2835_clk_is_claimed(data->source_pll))
++ init.flags |= CLK_IS_CRITICAL;
++ if (!bcm2835_clk_is_claimed(data->name))
++ divider->div.flags |= CLK_IS_CRITICAL;
+ }
+
+ divider->cprman = cprman;
+@@ -2152,6 +2159,8 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_PERIICTL),
+ };
+
++static bool bcm2835_clk_claimed[ARRAY_SIZE(clk_desc_array)];
++
+ /*
+ * Permanently take a reference on the parent of the SDRAM clock.
+ *
+@@ -2171,6 +2180,19 @@ static int bcm2835_mark_sdc_parent_criti
+ return clk_prepare_enable(parent);
+ }
+
++static bool bcm2835_clk_is_claimed(const char *name)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) {
++ const char *clk_name = *(const char **)(clk_desc_array[i].data);
++ if (!strcmp(name, clk_name))
++ return bcm2835_clk_claimed[i];
++ }
++
++ return false;
++}
++
+ static int bcm2835_clk_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -2180,6 +2202,7 @@ static int bcm2835_clk_probe(struct plat
+ const struct bcm2835_clk_desc *desc;
+ const size_t asize = ARRAY_SIZE(clk_desc_array);
+ size_t i;
++ u32 clk_id;
+ int ret;
+
+ cprman = devm_kzalloc(dev, sizeof(*cprman) +
+@@ -2195,6 +2218,13 @@ static int bcm2835_clk_probe(struct plat
+ if (IS_ERR(cprman->regs))
+ return PTR_ERR(cprman->regs);
+
++ memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed));
++ for (i = 0;
++ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks",
++ i, &clk_id);
++ i++)
++ bcm2835_clk_claimed[clk_id]= true;
++
+ memcpy(cprman->real_parent_names, cprman_parent_names,
+ sizeof(cprman_parent_names));
+ of_clk_parent_fill(dev->of_node, cprman->real_parent_names,
--- /dev/null
+From a3927566a6d90268423ae58aad12a71b9bf39dd9 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 6 Mar 2017 09:06:18 +0000
+Subject: [PATCH 028/454] clk-bcm2835: Read max core clock from firmware
+
+The VPU is responsible for managing the core clock, usually under
+direction from the bcm2835-cpufreq driver but not via the clk-bcm2835
+driver. Since the core frequency can change without warning, it is
+safer to report the maximum clock rate to users of the core clock -
+I2C, SPI and the mini UART - to err on the safe side when calculating
+clock divisors.
+
+If the DT node for the clock driver includes a reference to the
+firmware node, use the firmware API to query the maximum core clock
+instead of reading the divider registers.
+
+Prior to this patch, a "100KHz" I2C bus was sometimes clocked at about
+160KHz. In particular, switching to the 4.9 kernel was likely to break
+SenseHAT usage on a Pi3.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 39 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 38 insertions(+), 1 deletion(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -45,6 +45,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <dt-bindings/clock/bcm2835.h>
++#include <soc/bcm2835/raspberrypi-firmware.h>
+
+ #define CM_PASSWORD 0x5a000000
+
+@@ -299,6 +300,8 @@
+ #define LOCK_TIMEOUT_NS 100000000
+ #define BCM2835_MAX_FB_RATE 1750000000u
+
++#define VCMSG_ID_CORE_CLOCK 4
++
+ /*
+ * Names of clocks used within the driver that need to be replaced
+ * with an external parent's name. This array is in the order that
+@@ -317,6 +320,7 @@ static const char *const cprman_parent_n
+ struct bcm2835_cprman {
+ struct device *dev;
+ void __iomem *regs;
++ struct rpi_firmware *fw;
+ spinlock_t regs_lock; /* spinlock for all clocks */
+
+ /*
+@@ -1032,6 +1036,30 @@ static unsigned long bcm2835_clock_get_r
+ return bcm2835_clock_rate_from_divisor(clock, parent_rate, div);
+ }
+
++static unsigned long bcm2835_clock_get_rate_vpu(struct clk_hw *hw,
++ unsigned long parent_rate)
++{
++ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
++ struct bcm2835_cprman *cprman = clock->cprman;
++
++ if (cprman->fw) {
++ struct {
++ u32 id;
++ u32 val;
++ } packet;
++
++ packet.id = VCMSG_ID_CORE_CLOCK;
++ packet.val = 0;
++
++ if (!rpi_firmware_property(cprman->fw,
++ RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
++ &packet, sizeof(packet)))
++ return packet.val;
++ }
++
++ return bcm2835_clock_get_rate(hw, parent_rate);
++}
++
+ static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock)
+ {
+ struct bcm2835_cprman *cprman = clock->cprman;
+@@ -1321,7 +1349,7 @@ static int bcm2835_vpu_clock_is_on(struc
+ */
+ static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
+ .is_prepared = bcm2835_vpu_clock_is_on,
+- .recalc_rate = bcm2835_clock_get_rate,
++ .recalc_rate = bcm2835_clock_get_rate_vpu,
+ .set_rate = bcm2835_clock_set_rate,
+ .determine_rate = bcm2835_clock_determine_rate,
+ .set_parent = bcm2835_clock_set_parent,
+@@ -2201,6 +2229,7 @@ static int bcm2835_clk_probe(struct plat
+ struct resource *res;
+ const struct bcm2835_clk_desc *desc;
+ const size_t asize = ARRAY_SIZE(clk_desc_array);
++ struct device_node *fw_node;
+ size_t i;
+ u32 clk_id;
+ int ret;
+@@ -2218,6 +2247,14 @@ static int bcm2835_clk_probe(struct plat
+ if (IS_ERR(cprman->regs))
+ return PTR_ERR(cprman->regs);
+
++ fw_node = of_parse_phandle(dev->of_node, "firmware", 0);
++ if (fw_node) {
++ struct rpi_firmware *fw = rpi_firmware_get(NULL);
++ if (!fw)
++ return -EPROBE_DEFER;
++ cprman->fw = fw;
++ }
++
+ memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed));
+ for (i = 0;
+ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks",
--- /dev/null
+From 08accfd44328954d33c264402730c1944f1c70fc Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Mon, 9 May 2016 17:28:18 -0700
+Subject: [PATCH 029/454] clk: bcm2835: Mark GPIO clocks enabled at boot as
+ critical.
+
+These divide off of PLLD_PER and are used for the ethernet and wifi
+PHYs source PLLs. Neither of them is currently represented by a phy
+device that would grab the clock for us.
+
+This keeps other drivers from killing the networking PHYs when they
+disable their own clocks and trigger PLLD_PER's refcount going to 0.
+
+v2: Skip marking as critical if they aren't on at boot.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1490,6 +1490,15 @@ static struct clk_hw *bcm2835_register_c
+ init.flags = data->flags | CLK_IGNORE_UNUSED;
+
+ /*
++ * Some GPIO clocks for ethernet/wifi PLLs are marked as
++ * critical (since some platforms use them), but if the
++ * firmware didn't have them turned on then they clearly
++ * aren't actually critical.
++ */
++ if ((cprman_read(cprman, data->ctl_reg) & CM_ENABLE) == 0)
++ init.flags &= ~CLK_IS_CRITICAL;
++
++ /*
+ * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
+ * rate changes on at least of the parents.
+ */
--- /dev/null
+From 22f73cdb523fbbc9fd20d9e04ade2957f96233d6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 9 Feb 2017 14:36:44 +0000
+Subject: [PATCH 030/454] sound: Demote deferral errors to INFO level
+
+At present there is no mechanism to specify driver load order,
+which can lead to deferrals and repeated retries until successful.
+Since this situation is expected, reduce the dmesg level to
+INFO and mention that the operation will be retried.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ sound/soc/soc-core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -1124,7 +1124,7 @@ static int soc_bind_dai_link(struct snd_
+ cpu_dai_component.dai_name = dai_link->cpu_dai_name;
+ rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component);
+ if (!rtd->cpu_dai) {
+- dev_err(card->dev, "ASoC: CPU DAI %s not registered\n",
++ dev_info(card->dev, "ASoC: CPU DAI %s not registered - will retry\n",
+ dai_link->cpu_dai_name);
+ goto _err_defer;
+ }
+@@ -1137,7 +1137,7 @@ static int soc_bind_dai_link(struct snd_
+ for (i = 0; i < rtd->num_codecs; i++) {
+ codec_dais[i] = snd_soc_find_dai(&codecs[i]);
+ if (!codec_dais[i]) {
+- dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
++ dev_info(card->dev, "ASoC: CODEC DAI %s not registered - will retry\n",
+ codecs[i].dai_name);
+ goto _err_defer;
+ }
--- /dev/null
+From 5abe6a0ebe150f320a4ca0ed73b2e15fca1b16fd Mon Sep 17 00:00:00 2001
+From: Claggy3 <stephen.maclagan@hotmail.com>
+Date: Sat, 11 Feb 2017 14:00:30 +0000
+Subject: [PATCH 031/454] Update vfpmodule.c
+
+Christopher Alexander Tobias Schulze - May 2, 2015, 11:57 a.m.
+This patch fixes a problem with VFP state save and restore related
+to exception handling (panic with message "BUG: unsupported FP
+instruction in kernel mode") present on VFP11 floating point units
+(as used with ARM1176JZF-S CPUs, e.g. on first generation Raspberry
+Pi boards). This patch was developed and discussed on
+
+ https://github.com/raspberrypi/linux/issues/859
+
+A precondition to see the crashes is that floating point exception
+traps are enabled. In this case, the VFP11 might determine that a FPU
+operation needs to trap at a point in time when it is not possible to
+signal this to the ARM11 core any more. The VFP11 will then set the
+FPEXC.EX bit and store the trapped opcode in FPINST. (In some cases,
+a second opcode might have been accepted by the VFP11 before the
+exception was detected and could be reported to the ARM11 - in this
+case, the VFP11 also sets FPEXC.FP2V and stores the second opcode in
+FPINST2.)
+
+If FPEXC.EX is set, the VFP11 will "bounce" the next FPU opcode issued
+by the ARM11 CPU, which will be seen by the ARM11 as an undefined opcode
+trap. The VFP support code examines the FPEXC.EX and FPEXC.FP2V bits
+to decide what actions to take, i.e., whether to emulate the opcodes
+found in FPINST and FPINST2, and whether to retry the bounced instruction.
+
+If a user space application has left the VFP11 in this "pending trap"
+state, the next FPU opcode issued to the VFP11 might actually be the
+VSTMIA operation vfp_save_state() uses to store the FPU registers
+to memory (in our test cases, when building the signal stack frame).
+In this case, the kernel crashes as described above.
+
+This patch fixes the problem by making sure that vfp_save_state() is
+always entered with FPEXC.EX cleared. (The current value of FPEXC has
+already been saved, so this does not corrupt the context. Clearing
+FPEXC.EX has no effects on FPINST or FPINST2. Also note that many
+callers already modify FPEXC by setting FPEXC.EN before invoking
+vfp_save_state().)
+
+This patch also addresses a second problem related to FPEXC.EX: After
+returning from signal handling, the kernel reloads the VFP context
+from the user mode stack. However, the current code explicitly clears
+both FPEXC.EX and FPEXC.FP2V during reload. As VFP11 requires these
+bits to be preserved, this patch disables clearing them for VFP
+implementations belonging to architecture 1. There should be no
+negative side effects: the user can set both bits by executing FPU
+opcodes anyway, and while user code may now place arbitrary values
+into FPINST and FPINST2 (e.g., non-VFP ARM opcodes) the VFP support
+code knows which instructions can be emulated, and rejects other
+opcodes with "unhandled bounce" messages, so there should be no
+security impact from allowing reloading FPEXC.EX and FPEXC.FP2V.
+
+Signed-off-by: Christopher Alexander Tobias Schulze <cat.schulze@alice-dsl.net>
+---
+ arch/arm/vfp/vfpmodule.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -179,8 +179,11 @@ static int vfp_notifier(struct notifier_
+ * case the thread migrates to a different CPU. The
+ * restoring is done lazily.
+ */
+- if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu])
++ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) {
++ /* vfp_save_state oopses on VFP11 if EX bit set */
++ fmxr(FPEXC, fpexc & ~FPEXC_EX);
+ vfp_save_state(vfp_current_hw_state[cpu], fpexc);
++ }
+ #endif
+
+ /*
+@@ -463,13 +466,16 @@ static int vfp_pm_suspend(void)
+ /* if vfp is on, then save state for resumption */
+ if (fpexc & FPEXC_EN) {
+ pr_debug("%s: saving vfp state\n", __func__);
++ /* vfp_save_state oopses on VFP11 if EX bit set */
++ fmxr(FPEXC, fpexc & ~FPEXC_EX);
+ vfp_save_state(&ti->vfpstate, fpexc);
+
+ /* disable, just in case */
+ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
+ } else if (vfp_current_hw_state[ti->cpu]) {
+ #ifndef CONFIG_SMP
+- fmxr(FPEXC, fpexc | FPEXC_EN);
++ /* vfp_save_state oopses on VFP11 if EX bit set */
++ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
+ vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc);
+ fmxr(FPEXC, fpexc);
+ #endif
+@@ -532,7 +538,8 @@ void vfp_sync_hwstate(struct thread_info
+ /*
+ * Save the last VFP state on this CPU.
+ */
+- fmxr(FPEXC, fpexc | FPEXC_EN);
++ /* vfp_save_state oopses on VFP11 if EX bit set */
++ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
+ vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
+ fmxr(FPEXC, fpexc);
+ }
+@@ -602,6 +609,8 @@ int vfp_restore_user_hwstate(struct user
+ struct thread_info *thread = current_thread_info();
+ struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
+ unsigned long fpexc;
++ int err = 0;
++ u32 fpsid = fmrx(FPSID);
+
+ /* Disable VFP to avoid corrupting the new thread state. */
+ vfp_flush_hwstate(thread);
+@@ -624,8 +633,12 @@ int vfp_restore_user_hwstate(struct user
+ /* Ensure the VFP is enabled. */
+ fpexc |= FPEXC_EN;
+
+- /* Ensure FPINST2 is invalid and the exception flag is cleared. */
+- fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
++ /* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */
++ if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) {
++ /* Ensure FPINST2 is invalid and the exception flag is cleared. */
++ fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
++ }
++
+ hwstate->fpexc = fpexc;
+
+ hwstate->fpinst = ufp_exc->fpinst;
+@@ -695,7 +708,8 @@ void kernel_neon_begin(void)
+ cpu = get_cpu();
+
+ fpexc = fmrx(FPEXC) | FPEXC_EN;
+- fmxr(FPEXC, fpexc);
++ /* vfp_save_state oopses on VFP11 if EX bit set */
++ fmxr(FPEXC, fpexc & ~FPEXC_EX);
+
+ /*
+ * Save the userland NEON/VFP state. Under UP,
--- /dev/null
+From 3221c46961b4dcc88791f4a80dc8bd503c6cfe00 Mon Sep 17 00:00:00 2001
+From: Matt Flax <flatmax@flatmax.org>
+Date: Wed, 8 Mar 2017 21:13:24 +1100
+Subject: [PATCH 032/454] ASoC: bcm2835_i2s.c: relax the ch2 register setting
+ for 8 channels
+
+This patch allows ch2 registers to be set for 8 channels of audio.
+---
+ sound/soc/bcm/bcm2835-i2s.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/soc/bcm/bcm2835-i2s.c
++++ b/sound/soc/bcm/bcm2835-i2s.c
+@@ -312,6 +312,7 @@ static int bcm2835_i2s_hw_params(struct
+
+ switch (params_channels(params)) {
+ case 2:
++ case 8:
+ format = BCM2835_I2S_CH1(format) | BCM2835_I2S_CH2(format);
+ format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos));
+ format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos));
--- /dev/null
+From 390de19e8520898d19726ffa3d9a420349342442 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Tue, 1 Nov 2016 15:15:41 +0100
+Subject: [PATCH 033/454] i2c: bcm2835: Add debug support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This adds a debug module parameter to aid in debugging transfer issues
+by printing info to the kernel log. When enabled, status values are
+collected in the interrupt routine and msg info in
+bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid
+affecting timing. Having printk in the isr can mask issues.
+
+debug values (additive):
+1: Print info on error
+2: Print info on all transfers
+3: Print messages before transfer is started
+
+The value can be changed at runtime:
+/sys/module/i2c_bcm2835/parameters/debug
+
+Example output, debug=3:
+[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1]
+[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1]
+[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1]
+[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1]
+[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1]
+[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1]
+[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1]
+[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1]
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++-
+ 1 file changed, 98 insertions(+), 1 deletion(-)
+
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -56,6 +56,18 @@
+ #define BCM2835_I2C_CDIV_MIN 0x0002
+ #define BCM2835_I2C_CDIV_MAX 0xFFFE
+
++static unsigned int debug;
++module_param(debug, uint, 0644);
++MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer");
++
++#define BCM2835_DEBUG_MAX 512
++struct bcm2835_debug {
++ struct i2c_msg *msg;
++ int msg_idx;
++ size_t remain;
++ u32 status;
++};
++
+ struct bcm2835_i2c_dev {
+ struct device *dev;
+ void __iomem *regs;
+@@ -69,8 +81,78 @@ struct bcm2835_i2c_dev {
+ u32 msg_err;
+ u8 *msg_buf;
+ size_t msg_buf_remaining;
++ struct bcm2835_debug debug[BCM2835_DEBUG_MAX];
++ unsigned int debug_num;
++ unsigned int debug_num_msgs;
+ };
+
++static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s)
++{
++ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX)
++ return;
++
++ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg;
++ i2c_dev->debug[i2c_dev->debug_num].msg_idx =
++ i2c_dev->debug_num_msgs - i2c_dev->num_msgs;
++ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining;
++ i2c_dev->debug[i2c_dev->debug_num].status = s;
++ i2c_dev->debug_num++;
++}
++
++static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev,
++ struct bcm2835_debug *d)
++{
++ u32 s = d->status;
++
++ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n",
++ d->remain, s,
++ s & BCM2835_I2C_S_TA ? "TA " : "",
++ s & BCM2835_I2C_S_DONE ? "DONE " : "",
++ s & BCM2835_I2C_S_TXW ? "TXW " : "",
++ s & BCM2835_I2C_S_RXR ? "RXR " : "",
++ s & BCM2835_I2C_S_TXD ? "TXD " : "",
++ s & BCM2835_I2C_S_RXD ? "RXD " : "",
++ s & BCM2835_I2C_S_TXE ? "TXE " : "",
++ s & BCM2835_I2C_S_RXF ? "RXF " : "",
++ s & BCM2835_I2C_S_ERR ? "ERR " : "",
++ s & BCM2835_I2C_S_CLKT ? "CLKT " : "",
++ i2c_dev->adapter.nr);
++}
++
++static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev,
++ struct i2c_msg *msg, int i, int total,
++ const char *fname)
++{
++ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n",
++ fname, i, total,
++ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len,
++ msg->flags & I2C_M_TEN ? "TEN" : "",
++ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "",
++ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "",
++ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "",
++ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "",
++ msg->flags & I2C_M_NOSTART ? "NOSTART" : "",
++ msg->flags & I2C_M_STOP ? "STOP" : "",
++ i2c_dev->adapter.nr);
++}
++
++static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev)
++{
++ struct bcm2835_debug *d;
++ unsigned int i;
++
++ for (i = 0; i < i2c_dev->debug_num; i++) {
++ d = &i2c_dev->debug[i];
++ if (d->status == ~0)
++ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx,
++ i2c_dev->debug_num_msgs, "start_transfer");
++ else
++ bcm2835_debug_print_status(i2c_dev, d);
++ }
++ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX)
++ pr_info("BCM2835_DEBUG_MAX reached\n");
++}
++
+ static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev,
+ u32 reg, u32 val)
+ {
+@@ -189,6 +271,7 @@ static void bcm2835_i2c_start_transfer(s
+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
++ bcm2835_debug_add(i2c_dev, ~0);
+ }
+
+ /*
+@@ -206,6 +289,7 @@ static irqreturn_t bcm2835_i2c_isr(int t
+ u32 val, err;
+
+ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
++ bcm2835_debug_add(i2c_dev, val);
+
+ err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
+ if (err) {
+@@ -272,6 +356,13 @@ static int bcm2835_i2c_xfer(struct i2c_a
+ unsigned long time_left;
+ int i, ret;
+
++ if (debug)
++ i2c_dev->debug_num_msgs = num;
++
++ if (debug > 2)
++ for (i = 0; i < num; i++)
++ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__);
++
+ for (i = 0; i < (num - 1); i++)
+ if (msgs[i].flags & I2C_M_RD) {
+ dev_warn_once(i2c_dev->dev,
+@@ -291,6 +382,10 @@ static int bcm2835_i2c_xfer(struct i2c_a
+
+ time_left = wait_for_completion_timeout(&i2c_dev->completion,
+ adap->timeout);
++ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err)))
++ bcm2835_debug_print(i2c_dev);
++ i2c_dev->debug_num_msgs = 0;
++ i2c_dev->debug_num = 0;
+ if (!time_left) {
+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
+ BCM2835_I2C_C_CLEAR);
+@@ -301,7 +396,9 @@ static int bcm2835_i2c_xfer(struct i2c_a
+ if (!i2c_dev->msg_err)
+ return num;
+
+- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
++ if (debug)
++ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n",
++ i2c_dev->msg_err);
+
+ if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+ return -EREMOTEIO;
--- /dev/null
+From 311430df64b6d7992d1fbde8dab4995bcb082a9b Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Thu, 18 Dec 2014 16:07:15 -0800
+Subject: [PATCH 034/454] mm: Remove the PFN busy warning
+
+See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is
+expected sometimes when using CMA. However, that commit still spams
+my kernel log with these warnings.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+---
+ mm/page_alloc.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -7618,8 +7618,6 @@ int alloc_contig_range(unsigned long sta
+
+ /* Make sure the range is really isolated. */
+ if (test_pages_isolated(outer_start, end, false)) {
+- pr_info_ratelimited("%s: [%lx, %lx) PFNs busy\n",
+- __func__, outer_start, end);
+ ret = -EBUSY;
+ goto done;
+ }
--- /dev/null
+From 138508ce754d2451be8583fca4484056fe720e97 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 23 Mar 2017 10:06:56 +0000
+Subject: [PATCH 035/454] ASoC: Add prompt for ICS43432 codec
+
+Without a prompt string, a config setting can't be included in a
+defconfig. Give CONFIG_SND_SOC_ICS43432 a prompt so that Pi soundcards
+can use the driver.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ sound/soc/codecs/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -579,7 +579,7 @@ config SND_SOC_HDAC_HDMI
+ select HDMI
+
+ config SND_SOC_ICS43432
+- tristate
++ tristate "InvenSense ICS43432 I2S microphone codec"
+
+ config SND_SOC_INNO_RK3036
+ tristate "Inno codec driver for RK3036 SoC"
--- /dev/null
+From 456ed3c197e8aec439ebeca39060c204d2429896 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Sun, 12 May 2013 12:24:19 +0100
+Subject: [PATCH 036/454] Main bcm2708/bcm2709 linux port
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+bcm2709: Drop platform smp and timer init code
+
+irq-bcm2836 handles this through these functions:
+bcm2835_init_local_timer_frequency()
+bcm2836_arm_irqchip_smp_init()
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+bcm270x: Use watchdog for reboot/poweroff
+
+The watchdog driver already has support for reboot/poweroff.
+Make use of this and remove the code from the platform files.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+---
+ arch/arm/mach-bcm/Kconfig | 1 +
+ arch/arm/mach-bcm/board_bcm2835.c | 9 +++++++++
+ arch/arm/mm/proc-v6.S | 15 ++++++++++++---
+ drivers/irqchip/irq-bcm2835.c | 7 ++++++-
+ drivers/mailbox/bcm2835-mailbox.c | 18 ++++++++++++++++--
+ 5 files changed, 44 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/mach-bcm/Kconfig
++++ b/arch/arm/mach-bcm/Kconfig
+@@ -158,6 +158,7 @@ config ARCH_BCM2835
+ select FIQ
+ select PINCTRL
+ select PINCTRL_BCM2835
++ select MFD_SYSCON if ARCH_MULTI_V7
+ help
+ This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
+ This SoC is used in the Raspberry Pi and Roku 2 devices.
+--- a/arch/arm/mach-bcm/board_bcm2835.c
++++ b/arch/arm/mach-bcm/board_bcm2835.c
+@@ -21,6 +21,8 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+
++#include <linux/dma-mapping.h>
++
+ static void __init bcm2835_init(void)
+ {
+ struct device_node *np = of_find_node_by_path("/system");
+@@ -35,6 +37,12 @@ static void __init bcm2835_init(void)
+ system_serial_low = val64;
+ }
+
++static void __init bcm2835_init_early(void)
++{
++ /* dwc_otg needs this for bounce buffers on non-aligned transfers */
++ init_dma_coherent_pool_size(SZ_1M);
++}
++
+ static const char * const bcm2835_compat[] = {
+ #ifdef CONFIG_ARCH_MULTI_V6
+ "brcm,bcm2835",
+@@ -47,5 +55,6 @@ static const char * const bcm2835_compat
+
+ DT_MACHINE_START(BCM2835, "BCM2835")
+ .init_machine = bcm2835_init,
++ .init_early = bcm2835_init_early,
+ .dt_compat = bcm2835_compat
+ MACHINE_END
+--- a/arch/arm/mm/proc-v6.S
++++ b/arch/arm/mm/proc-v6.S
+@@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset)
+ *
+ * IRQs are already disabled.
+ */
++
++/* See jira SW-5991 for details of this workaround */
+ ENTRY(cpu_v6_do_idle)
+- mov r1, #0
+- mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode
+- mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt
++ .align 5
++ mov r1, #2
++1: subs r1, #1
++ nop
++ mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode
++ mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt
++ nop
++ nop
++ nop
++ bne 1b
+ ret lr
+
+ ENTRY(cpu_v6_dcache_clean_area)
+--- a/drivers/irqchip/irq-bcm2835.c
++++ b/drivers/irqchip/irq-bcm2835.c
+@@ -54,7 +54,9 @@
+ #include <linux/regmap.h>
+
+ #include <asm/exception.h>
++#ifndef CONFIG_ARM64
+ #include <asm/mach/irq.h>
++#endif
+
+ /* Put the bank and irq (32 bits) into the hwirq */
+ #define MAKE_HWIRQ(b, n) (((b) << 5) | (n))
+@@ -82,6 +84,7 @@
+ #define NR_BANKS 3
+ #define IRQS_PER_BANK 32
+ #define NUMBER_IRQS MAKE_HWIRQ(NR_BANKS, 0)
++#undef FIQ_START
+ #define FIQ_START (NR_IRQS_BANK0 + MAKE_HWIRQ(NR_BANKS - 1, 0))
+
+ static const int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
+@@ -255,10 +258,12 @@ static int __init armctrl_of_init(struct
+ MAKE_HWIRQ(b, i) + NUMBER_IRQS);
+ BUG_ON(irq <= 0);
+ irq_set_chip(irq, &armctrl_chip);
+- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++ irq_set_probe(irq);
+ }
+ }
++#ifndef CONFIG_ARM64
+ init_FIQ(FIQ_START);
++#endif
+
+ return 0;
+ }
+--- a/drivers/mailbox/bcm2835-mailbox.c
++++ b/drivers/mailbox/bcm2835-mailbox.c
+@@ -51,12 +51,15 @@
+ #define MAIL1_WRT (ARM_0_MAIL1 + 0x00)
+ #define MAIL1_STA (ARM_0_MAIL1 + 0x18)
+
++/* On ARCH_BCM270x these come through <linux/interrupt.h> (arm_control.h ) */
++#ifndef ARM_MS_FULL
+ /* Status register: FIFO state. */
+ #define ARM_MS_FULL BIT(31)
+ #define ARM_MS_EMPTY BIT(30)
+
+ /* Configuration register: Enable interrupts. */
+ #define ARM_MC_IHAVEDATAIRQEN BIT(0)
++#endif
+
+ struct bcm2835_mbox {
+ void __iomem *regs;
+@@ -151,7 +154,7 @@ static int bcm2835_mbox_probe(struct pla
+ return -ENOMEM;
+ spin_lock_init(&mbox->lock);
+
+- ret = devm_request_irq(dev, irq_of_parse_and_map(dev->of_node, 0),
++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
+ bcm2835_mbox_irq, 0, dev_name(dev), mbox);
+ if (ret) {
+ dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n",
+@@ -209,7 +212,18 @@ static struct platform_driver bcm2835_mb
+ .probe = bcm2835_mbox_probe,
+ .remove = bcm2835_mbox_remove,
+ };
+-module_platform_driver(bcm2835_mbox_driver);
++
++static int __init bcm2835_mbox_init(void)
++{
++ return platform_driver_register(&bcm2835_mbox_driver);
++}
++arch_initcall(bcm2835_mbox_init);
++
++static void __init bcm2835_mbox_exit(void)
++{
++ platform_driver_unregister(&bcm2835_mbox_driver);
++}
++module_exit(bcm2835_mbox_exit);
+
+ MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
+ MODULE_DESCRIPTION("BCM2835 mailbox IPC driver");
--- /dev/null
+From 451dab6b675762f8889979b04ee3e529eee915e8 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Wed, 1 May 2013 19:46:17 +0100
+Subject: [PATCH 037/454] Add dwc_otg driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+
+usb: dwc: fix lockdep false positive
+
+Signed-off-by: Kari Suvanto <karis79@gmail.com>
+
+usb: dwc: fix inconsistent lock state
+
+Signed-off-by: Kari Suvanto <karis79@gmail.com>
+
+Add FIQ patch to dwc_otg driver. Enable with dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance.
+Thanks to Gordon and Costas
+
+Avoid dynamic memory allocation for channel lock in USB driver. Thanks ddv2005.
+
+Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh
+
+Make sure we wait for the reset to finish
+
+dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel
+ memory corruption, escalating to OOPS under high USB load.
+
+dwc_otg: Fix unsafe access of QTD during URB enqueue
+
+In dwc_otg_hcd_urb_enqueue during qtd creation, it was possible that the
+transaction could complete almost immediately after the qtd was assigned
+to a host channel during URB enqueue, which meant the qtd pointer was no
+longer valid having been completed and removed. Usually, this resulted in
+an OOPS during URB submission. By predetermining whether transactions
+need to be queued or not, this unsafe pointer access is avoided.
+
+This bug was only evident on the Pi model A where a device was attached
+that had no periodic endpoints (e.g. USB pendrive or some wlan devices).
+
+dwc_otg: Fix incorrect URB allocation error handling
+
+If the memory allocation for a dwc_otg_urb failed, the kernel would OOPS
+because for some reason a member of the *unallocated* struct was set to
+zero. Error handling changed to fail correctly.
+
+dwc_otg: fix potential use-after-free case in interrupt handler
+
+If a transaction had previously aborted, certain interrupts are
+enabled to track error counts and reset where necessary. On IN
+endpoints the host generates an ACK interrupt near-simultaneously
+with completion of transfer. In the case where this transfer had
+previously had an error, this results in a use-after-free on
+the QTD memory space with a 1-byte length being overwritten to
+0x00.
+
+dwc_otg: add handling of SPLIT transaction data toggle errors
+
+Previously a data toggle error on packets from a USB1.1 device behind
+a TT would result in the Pi locking up as the driver never handled
+the associated interrupt. Patch adds basic retry mechanism and
+interrupt acknowledgement to cater for either a chance toggle error or
+for devices that have a broken initial toggle state (FT8U232/FT232BM).
+
+dwc_otg: implement tasklet for returning URBs to usbcore hcd layer
+
+The dwc_otg driver interrupt handler for transfer completion will spend
+a very long time with interrupts disabled when a URB is completed -
+this is because usb_hcd_giveback_urb is called from within the handler
+which for a USB device driver with complicated processing (e.g. webcam)
+will take an exorbitant amount of time to complete. This results in
+missed completion interrupts for other USB packets which lead to them
+being dropped due to microframe overruns.
+
+This patch splits returning the URB to the usb hcd layer into a
+high-priority tasklet. This will have most benefit for isochronous IN
+transfers but will also have incidental benefit where multiple periodic
+devices are active at once.
+
+dwc_otg: fix NAK holdoff and allow on split transactions only
+
+This corrects a bug where if a single active non-periodic endpoint
+had at least one transaction in its qh, on frnum == MAX_FRNUM the qh
+would get skipped and never get queued again. This would result in
+a silent device until error detection (automatic or otherwise) would
+either reset the device or flush and requeue the URBs.
+
+Additionally the NAK holdoff was enabled for all transactions - this
+would potentially stall a HS endpoint for 1ms if a previous error state
+enabled this interrupt and the next response was a NAK. Fix so that
+only split transactions get held off.
+
+dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held in completion handler
+
+usb_hcd_unlink_urb_from_ep must be called with the HCD lock held. Calling it
+asynchronously in the tasklet was not safe (regression in
+c4564d4a1a0a9b10d4419e48239f5d99e88d2667).
+
+This change unlinks it from the endpoint prior to queueing it for handling in
+the tasklet, and also adds a check to ensure the urb is OK to be unlinked
+before doing so.
+
+NULL pointer dereference kernel oopses had been observed in usb_hcd_giveback_urb
+when a USB device was unplugged/replugged during data transfer. This effect
+was reproduced using automated USB port power control, hundreds of replug
+events were performed during active transfers to confirm that the problem was
+eliminated.
+
+USB fix using a FIQ to implement split transactions
+
+This commit adds a FIQ implementaion that schedules
+the split transactions using a FIQ so we don't get
+held off by the interrupt latency of Linux
+
+dwc_otg: fix device attributes and avoid kernel warnings on boot
+
+dcw_otg: avoid logging function that can cause panics
+
+See: https://github.com/raspberrypi/firmware/issues/21
+Thanks to cleverca22 for fix
+
+dwc_otg: mask correct interrupts after transaction error recovery
+
+The dwc_otg driver will unmask certain interrupts on a transaction
+that previously halted in the error state in order to reset the
+QTD error count. The various fine-grained interrupt handlers do not
+consider that other interrupts besides themselves were unmasked.
+
+By disabling the two other interrupts only ever enabled in DMA mode
+for this purpose, we can avoid unnecessary function calls in the
+IRQ handler. This will also prevent an unneccesary FIQ interrupt
+from being generated if the FIQ is enabled.
+
+dwc_otg: fiq: prevent FIQ thrash and incorrect state passing to IRQ
+
+In the case of a transaction to a device that had previously aborted
+due to an error, several interrupts are enabled to reset the error
+count when a device responds. This has the side-effect of making the
+FIQ thrash because the hardware will generate multiple instances of
+a NAK on an IN bulk/interrupt endpoint and multiple instances of ACK
+on an OUT bulk/interrupt endpoint. Make the FIQ mask and clear the
+associated interrupts.
+
+Additionally, on non-split transactions make sure that only unmasked
+interrupts are cleared. This caused a hard-to-trigger but serious
+race condition when you had the combination of an endpoint awaiting
+error recovery and a transaction completed on an endpoint - due to
+the sequencing and timing of interrupts generated by the dwc_otg core,
+it was possible to confuse the IRQ handler.
+
+Fix function tracing
+
+dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue
+
+dwc_otg: prevent OOPSes during device disconnects
+
+The dwc_otg_urb_enqueue function is thread-unsafe. In particular the
+access of urb->hcpriv, usb_hcd_link_urb_to_ep, dwc_otg_urb->qtd and
+friends does not occur within a critical section and so if a device
+was unplugged during activity there was a high chance that the
+usbcore hub_thread would try to disable the endpoint with partially-
+formed entries in the URB queue. This would result in BUG() or null
+pointer dereferences.
+
+Fix so that access of urb->hcpriv, enqueuing to the hardware and
+adding to usbcore endpoint URB lists is contained within a single
+critical section.
+
+dwc_otg: prevent BUG() in TT allocation if hub address is > 16
+
+A fixed-size array is used to track TT allocation. This was
+previously set to 16 which caused a crash because
+dwc_otg_hcd_allocate_port would read past the end of the array.
+
+This was hit if a hub was plugged in which enumerated as addr > 16,
+due to previous device resets or unplugs.
+
+Also add #ifdef FIQ_DEBUG around hcd->hub_port_alloc[], which grows
+to a large size if 128 hub addresses are supported. This field is
+for debug only for tracking which frame an allocate happened in.
+
+dwc_otg: make channel halts with unknown state less damaging
+
+If the IRQ received a channel halt interrupt through the FIQ
+with no other bits set, the IRQ would not release the host
+channel and never complete the URB.
+
+Add catchall handling to treat as a transaction error and retry.
+
+dwc_otg: fiq_split: use TTs with more granularity
+
+This fixes certain issues with split transaction scheduling.
+
+- Isochronous multi-packet OUT transactions now hog the TT until
+ they are completed - this prevents hubs aborting transactions
+ if they get a periodic start-split out-of-order
+- Don't perform TT allocation on non-periodic endpoints - this
+ allows simultaneous use of the TT's bulk/control and periodic
+ transaction buffers
+
+This commit will mainly affect USB audio playback.
+
+dwc_otg: fix potential sleep while atomic during urb enqueue
+
+Fixes a regression introduced with eb1b482a. Kmalloc called from
+dwc_otg_hcd_qtd_add / dwc_otg_hcd_qtd_create did not always have
+the GPF_ATOMIC flag set. Force this flag when inside the larger
+critical section.
+
+dwc_otg: make fiq_split_enable imply fiq_fix_enable
+
+Failing to set up the FIQ correctly would result in
+"IRQ 32: nobody cared" errors in dmesg.
+
+dwc_otg: prevent crashes on host port disconnects
+
+Fix several issues resulting in crashes or inconsistent state
+if a Model A root port was disconnected.
+
+- Clean up queue heads properly in kill_urbs_in_qh_list by
+ removing the empty QHs from the schedule lists
+- Set the halt status properly to prevent IRQ handlers from
+ using freed memory
+- Add fiq_split related cleanup for saved registers
+- Make microframe scheduling reclaim host channels if
+ active during a disconnect
+- Abort URBs with -ESHUTDOWN status response, informing
+ device drivers so they respond in a more correct fashion
+ and don't try to resubmit URBs
+- Prevent IRQ handlers from attempting to handle channel
+ interrupts if the associated URB was dequeued (and the
+ driver state was cleared)
+
+dwc_otg: prevent leaking URBs during enqueue
+
+A dwc_otg_urb would get leaked if the HCD enqueue function
+failed for any reason. Free the URB at the appropriate points.
+
+dwc_otg: Enable NAK holdoff for control split transactions
+
+Certain low-speed devices take a very long time to complete a
+data or status stage of a control transaction, producing NAK
+responses until they complete internal processing - the USB2.0
+spec limit is up to 500mS. This causes the same type of interrupt
+storm as seen with USB-serial dongles prior to c8edb238.
+
+In certain circumstances, usually while booting, this interrupt
+storm could cause SD card timeouts.
+
+dwc_otg: Fix for occasional lockup on boot when doing a USB reset
+
+dwc_otg: Don't issue traffic to LS devices in FS mode
+
+Issuing low-speed packets when the root port is in full-speed mode
+causes the root port to stop responding. Explicitly fail when
+enqueuing URBs to a LS endpoint on a FS bus.
+
+Fix ARM architecture issue with local_irq_restore()
+
+If local_fiq_enable() is called before a local_irq_restore(flags) where
+the flags variable has the F bit set, the FIQ will be erroneously disabled.
+
+Fixup arch_local_irq_restore to avoid trampling the F bit in CPSR.
+
+Also fix some of the hacks previously implemented for previous dwc_otg
+incarnations.
+
+dwc_otg: fiq_fsm: Base commit for driver rewrite
+
+This commit removes the previous FIQ fixes entirely and adds fiq_fsm.
+
+This rewrite features much more complete support for split transactions
+and takes into account several OTG hardware bugs. High-speed
+isochronous transactions are also capable of being performed by fiq_fsm.
+
+All driver options have been removed and replaced with:
+ - dwc_otg.fiq_enable (bool)
+ - dwc_otg.fiq_fsm_enable (bool)
+ - dwc_otg.fiq_fsm_mask (bitmask)
+ - dwc_otg.nak_holdoff (unsigned int)
+
+Defaults are specified such that fiq_fsm behaves similarly to the
+previously implemented FIQ fixes.
+
+fiq_fsm: Push error recovery into the FIQ when fiq_fsm is used
+
+If the transfer associated with a QTD failed due to a bus error, the HCD
+would retry the transfer up to 3 times (implementing the USB2.0
+three-strikes retry in software).
+
+Due to the masking mechanism used by fiq_fsm, it is only possible to pass
+a single interrupt through to the HCD per-transfer.
+
+In this instance host channels would fall off the radar because the error
+reset would function, but the subsequent channel halt would be lost.
+
+Push the error count reset into the FIQ handler.
+
+fiq_fsm: Implement timeout mechanism
+
+For full-speed endpoints with a large packet size, interrupt latency
+runs the risk of the FIQ starting a transaction too late in a full-speed
+frame. If the device is still transmitting data when EOF2 for the
+downstream frame occurs, the hub will disable the port. This change is
+not reflected in the hub status endpoint and the device becomes
+unresponsive.
+
+Prevent high-bandwidth transactions from being started too late in a
+frame. The mechanism is not guaranteed: a combination of bit stuffing
+and hub latency may still result in a device overrunning.
+
+fiq_fsm: fix bounce buffer utilisation for Isochronous OUT
+
+Multi-packet isochronous OUT transactions were subject to a few bounday
+bugs. Fix them.
+
+Audio playback is now much more robust: however, an issue stands with
+devices that have adaptive sinks - ALSA plays samples too fast.
+
+dwc_otg: Return full-speed frame numbers in HS mode
+
+The frame counter increments on every *microframe* in high-speed mode.
+Most device drivers expect this number to be in full-speed frames - this
+caused considerable confusion to e.g. snd_usb_audio which uses the
+frame counter to estimate the number of samples played.
+
+fiq_fsm: save PID on completion of interrupt OUT transfers
+
+Also add edge case handling for interrupt transports.
+
+Note that for periodic split IN, data toggles are unimplemented in the
+OTG host hardware - it unconditionally accepts any PID.
+
+fiq_fsm: add missing case for fiq_fsm_tt_in_use()
+
+Certain combinations of bitrate and endpoint activity could
+result in a periodic transaction erroneously getting started
+while the previous Isochronous OUT was still active.
+
+fiq_fsm: clear hcintmsk for aborted transactions
+
+Prevents the FIQ from erroneously handling interrupts
+on a timed out channel.
+
+fiq_fsm: enable by default
+
+fiq_fsm: fix dequeues for non-periodic split transactions
+
+If a dequeue happened between the SSPLIT and CSPLIT phases of the
+transaction, the HCD would never receive an interrupt.
+
+fiq_fsm: Disable by default
+
+fiq_fsm: Handle HC babble errors
+
+The HCTSIZ transfer size field raises a babble interrupt if
+the counter wraps. Handle the resulting interrupt in this case.
+
+dwc_otg: fix interrupt registration for fiq_enable=0
+
+Additionally make the module parameter conditional for wherever
+hcd->fiq_state is touched.
+
+fiq_fsm: Enable by default
+
+dwc_otg: Fix various issues with root port and transaction errors
+
+Process the host port interrupts correctly (and don't trample them).
+Root port hotplug now functional again.
+
+Fix a few thinkos with the transaction error passthrough for fiq_fsm.
+
+fiq_fsm: Implement hack for Split Interrupt transactions
+
+Hubs aren't too picky about which endpoint we send Control type split
+transactions to. By treating Interrupt transfers as Control, it is
+possible to use the non-periodic queue in the OTG core as well as the
+non-periodic FIFOs in the hub itself. This massively reduces the
+microframe exclusivity/contention that periodic split transactions
+otherwise have to enforce.
+
+It goes without saying that this is a fairly egregious USB specification
+violation, but it works.
+
+Original idea by Hans Petter Selasky @ FreeBSD.org.
+
+dwc_otg: FIQ support on SMP. Set up FIQ stack and handler on Core 0 only.
+
+dwc_otg: introduce fiq_fsm_spin(un|)lock()
+
+SMP safety for the FIQ relies on register read-modify write cycles being
+completed in the correct order. Several places in the DWC code modify
+registers also touched by the FIQ. Protect these by a bare-bones lock
+mechanism.
+
+This also makes it possible to run the FIQ and IRQ handlers on different
+cores.
+
+fiq_fsm: fix build on bcm2708 and bcm2709 platforms
+
+dwc_otg: put some barriers back where they should be for UP
+
+bcm2709/dwc_otg: Setup FIQ on core 1 if >1 core active
+
+dwc_otg: fixup read-modify-write in critical paths
+
+Be more careful about read-modify-write on registers that the FIQ
+also touches.
+
+Guard fiq_fsm_spin_lock with fiq_enable check
+
+fiq_fsm: Falling out of the state machine isn't fatal
+
+This edge case can be hit if the port is disabled while the FIQ is
+in the middle of a transaction. Make the effects less severe.
+
+Also get rid of the useless return value.
+
+squash: dwc_otg: Allow to build without SMP
+
+usb: core: make overcurrent messages more prominent
+
+Hub overcurrent messages are more serious than "debug". Increase loglevel.
+
+usb: dwc_otg: Don't use dma_to_virt()
+
+Commit 6ce0d20 changes dma_to_virt() which breaks this driver.
+Open code the old dma_to_virt() implementation to work around this.
+
+Limit the use of __bus_to_virt() to cases where transfer_buffer_length
+is set and transfer_buffer is not set. This is done to increase the
+chance that this driver will also work on ARCH_BCM2835.
+
+transfer_buffer should not be NULL if the length is set, but the
+comment in the code indicates that there are situations where this
+might happen. drivers/usb/isp1760/isp1760-hcd.c also has a similar
+comment pointing to a possible: 'usb storage / SCSI bug'.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+dwc_otg: Fix crash when fiq_enable=0
+
+dwc_otg: fiq_fsm: Make high-speed isochronous strided transfers work properly
+
+Certain low-bandwidth high-speed USB devices (specialist audio devices,
+compressed-frame webcams) have packet intervals > 1 microframe.
+
+Stride these transfers in the FIQ by using the start-of-frame interrupt
+to restart the channel at the right time.
+
+dwc_otg: Force host mode to fix incorrect compute module boards
+
+dwc_otg: Add ARCH_BCM2835 support
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+dwc_otg: Simplify FIQ irq number code
+
+Dropping ATAGS means we can simplify the FIQ irq number code.
+Also add error checking on the returned irq number.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+dwc_otg: Remove duplicate gadget probe/unregister function
+
+dwc_otg: Properly set the HFIR
+
+Douglas Anderson reported:
+
+According to the most up to date version of the dwc2 databook, the FRINT
+field of the HFIR register should be programmed to:
+* 125 us * (PHY clock freq for HS) - 1
+* 1000 us * (PHY clock freq for FS/LS) - 1
+
+This is opposed to older versions of the doc that claimed it should be:
+* 125 us * (PHY clock freq for HS)
+* 1000 us * (PHY clock freq for FS/LS)
+
+and reported lower timing jitter on a USB analyser
+
+dcw_otg: trim xfer length when buffer larger than allocated size is received
+
+dwc_otg: Don't free qh align buffers in atomic context
+
+dwc_otg: Enable the hack for Split Interrupt transactions by default
+
+dwc_otg.fiq_fsm_mask=0xF has long been a suggestion for users with audio stutters or other USB bandwidth issues.
+So far we are aware of many success stories but no failure caused by this setting.
+Make it a default to learn more.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=70437
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+
+dwc_otg: Use kzalloc when suitable
+
+dwc_otg: Pass struct device to dma_alloc*()
+
+This makes it possible to get the bus address from Device Tree.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+dwc_otg: fix summarize urb->actual_length for isochronous transfers
+
+Kernel does not copy input data of ISO transfers to userspace
+if actual_length is set only in ISO transfers and not summarized
+in urb->actual_length. Fixes raspberrypi/linux#903
+
+fiq_fsm: Use correct states when starting isoc OUT transfers
+
+In fiq_fsm_start_next_periodic() if an isochronous OUT transfer
+was selected, no regard was given as to whether this was a single-packet
+transfer or a multi-packet staged transfer.
+
+For single-packet transfers, this had the effect of repeatedly sending
+OUT packets with bogus data and lengths.
+
+Eventually if the channel was repeatedly enabled enough times, this
+would lock up the OTG core and no further bus transfers would happen.
+
+Set the FSM state up properly if we select a single-packet transfer.
+
+Fixes https://github.com/raspberrypi/linux/issues/1842
+
+dwc_otg: make nak_holdoff work as intended with empty queues
+
+If URBs reading from non-periodic split endpoints were dequeued and
+the last transfer from the endpoint was a NAK handshake, the resulting
+qh->nak_frame value was stale which would result in unnecessarily long
+polling intervals for the first subsequent transfer with a fresh URB.
+
+Fixup qh->nak_frame in dwc_otg_hcd_urb_dequeue and also guard against
+a case where a single URB is submitted to the endpoint, a NAK was
+received on the transfer immediately prior to receiving data and the
+device subsequently resubmits another URB past the qh->nak_frame interval.
+
+Fixes https://github.com/raspberrypi/linux/issues/1709
+
+dwc_otg: fix split transaction data toggle handling around dequeues
+
+See https://github.com/raspberrypi/linux/issues/1709
+
+Fix several issues regarding endpoint state when URBs are dequeued
+- If the HCD is disconnected, flush FIQ-enabled channels properly
+- Save the data toggle state for bulk endpoints if the last transfer
+ from an endpoint where URBs were dequeued returned a data packet
+- Reset hc->start_pkt_count properly in assign_and_init_hc()
+
+dwc_otg: fix several potential crash sources
+
+On root port disconnect events, the host driver state is cleared and
+in-progress host channels are forcibly stopped. This doesn't play
+well with the FIQ running in the background, so:
+- Guard the disconnect callback with both the host spinlock and FIQ
+ spinlock
+- Move qtd dereference in dwc_otg_handle_hc_fsm() after the early-out
+ so we don't dereference a qtd that has gone away
+- Turn catch-all BUG()s in dwc_otg_handle_hc_fsm() into warnings.
+
+dwc_otg: delete hcd->channel_lock
+
+The lock serves no purpose as it is only held while the HCD spinlock
+is already being held.
+
+dwc_otg: remove unnecessary dma-mode channel halts on disconnect interrupt
+
+Host channels are already halted in kill_urbs_in_qh_list() with the
+subsequent interrupt processing behaving as if the URB was dequeued
+via HCD callback.
+
+There's no need to clobber the host channel registers a second time
+as this exposes races between the driver and host channel resulting
+in hcd->free_hc_list becoming corrupted.
+
+dwcotg: Allow to build without FIQ on ARM64
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+
+dwc_otg: make periodic scheduling behave properly for FS buses
+
+If the root port is in full-speed mode, transfer times at 12mbit/s
+would be calculated but matched against high-speed quotas.
+
+Reinitialise hcd->frame_usecs[i] on each port enable event so that
+full-speed bandwidth can be tracked sensibly.
+
+Also, don't bother using the FIQ for transfers when in full-speed
+mode - at the slower bus speed, interrupt frequency is reduced by
+an order of magnitude.
+
+Related issue: https://github.com/raspberrypi/linux/issues/2020
+
+dwc_otg: fiq_fsm: Make isochronous compatibility checks work properly
+
+Get rid of the spammy printk and local pointer mangling.
+Also, there is a nominal benefit for using fiq_fsm for isochronous
+transfers in FS mode (~1.1k IRQs per second vs 2.1k IRQs per second)
+so remove the root port speed check.
+
+dwc_otg: add module parameter int_ep_interval_min
+
+Add a module parameter (defaulting to ignored) that clamps the polling rate
+of high-speed Interrupt endpoints to a minimum microframe interval.
+
+The parameter is modifiable at runtime as it is used when activating new
+endpoints (such as on device connect).
+
+dwc_otg: fiq_fsm: Add non-periodic TT exclusivity constraints
+
+Certain hub types do not discriminate between pipe direction (IN or OUT)
+when considering non-periodic transfers. Therefore these hubs get confused
+if multiple transfers are issued in different directions with the same
+device address and endpoint number.
+
+Constrain queuing non-periodic split transactions so they are performed
+serially in such cases.
+
+Related: https://github.com/raspberrypi/linux/issues/2024
+
+dwc_otg: Fixup change to DRIVER_ATTR interface
+
+dwc_otg: Fix compilation warnings
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+
+USB_DWCOTG: Disable building dwc_otg as a module (#2265)
+
+When dwc_otg is built as a module, build will fail with the following
+error:
+
+ERROR: "DWC_TASK_HI_SCHEDULE" [drivers/usb/host/dwc_otg/dwc_otg.ko] undefined!
+scripts/Makefile.modpost:91: recipe for target '__modpost' failed
+make[1]: *** [__modpost] Error 1
+Makefile:1199: recipe for target 'modules' failed
+make: *** [modules] Error 2
+
+Even if the error is solved by including the missing
+DWC_TASK_HI_SCHEDULE function, the kernel will panic when loading
+dwc_otg.
+
+As a workaround, simply prevent user from building dwc_otg as a module
+as the current kernel does not support it.
+
+See: https://github.com/raspberrypi/linux/issues/2258
+
+Signed-off-by: Malik Olivier Boussejra <malik@boussejra.com>
+---
+ arch/arm/include/asm/irqflags.h | 16 +-
+ arch/arm/kernel/fiqasm.S | 4 +
+ drivers/usb/Makefile | 1 +
+ drivers/usb/core/generic.c | 1 +
+ drivers/usb/core/hub.c | 2 +-
+ drivers/usb/core/message.c | 79 +
+ drivers/usb/core/otg_whitelist.h | 114 +-
+ drivers/usb/gadget/file_storage.c | 3676 +++++++++
+ drivers/usb/host/Kconfig | 10 +
+ drivers/usb/host/Makefile | 2 +
+ drivers/usb/host/dwc_common_port/Makefile | 58 +
+ .../usb/host/dwc_common_port/Makefile.fbsd | 17 +
+ .../usb/host/dwc_common_port/Makefile.linux | 49 +
+ drivers/usb/host/dwc_common_port/changes.txt | 174 +
+ .../usb/host/dwc_common_port/doc/doxygen.cfg | 270 +
+ drivers/usb/host/dwc_common_port/dwc_cc.c | 532 ++
+ drivers/usb/host/dwc_common_port/dwc_cc.h | 224 +
+ .../host/dwc_common_port/dwc_common_fbsd.c | 1308 +++
+ .../host/dwc_common_port/dwc_common_linux.c | 1418 ++++
+ .../host/dwc_common_port/dwc_common_nbsd.c | 1275 +++
+ drivers/usb/host/dwc_common_port/dwc_crypto.c | 308 +
+ drivers/usb/host/dwc_common_port/dwc_crypto.h | 111 +
+ drivers/usb/host/dwc_common_port/dwc_dh.c | 291 +
+ drivers/usb/host/dwc_common_port/dwc_dh.h | 106 +
+ drivers/usb/host/dwc_common_port/dwc_list.h | 594 ++
+ drivers/usb/host/dwc_common_port/dwc_mem.c | 245 +
+ drivers/usb/host/dwc_common_port/dwc_modpow.c | 636 ++
+ drivers/usb/host/dwc_common_port/dwc_modpow.h | 34 +
+ .../usb/host/dwc_common_port/dwc_notifier.c | 319 +
+ .../usb/host/dwc_common_port/dwc_notifier.h | 122 +
+ drivers/usb/host/dwc_common_port/dwc_os.h | 1276 +++
+ drivers/usb/host/dwc_common_port/usb.h | 946 +++
+ drivers/usb/host/dwc_otg/Makefile | 82 +
+ drivers/usb/host/dwc_otg/doc/doxygen.cfg | 224 +
+ drivers/usb/host/dwc_otg/dummy_audio.c | 1574 ++++
+ drivers/usb/host/dwc_otg/dwc_cfi_common.h | 142 +
+ drivers/usb/host/dwc_otg/dwc_otg_adp.c | 854 ++
+ drivers/usb/host/dwc_otg/dwc_otg_adp.h | 80 +
+ drivers/usb/host/dwc_otg/dwc_otg_attr.c | 1212 +++
+ drivers/usb/host/dwc_otg/dwc_otg_attr.h | 89 +
+ drivers/usb/host/dwc_otg/dwc_otg_cfi.c | 1876 +++++
+ drivers/usb/host/dwc_otg/dwc_otg_cfi.h | 320 +
+ drivers/usb/host/dwc_otg/dwc_otg_cil.c | 7141 +++++++++++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_cil.h | 1464 ++++
+ drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 1596 ++++
+ drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 705 ++
+ drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 117 +
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1760 ++++
+ drivers/usb/host/dwc_otg/dwc_otg_driver.h | 86 +
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 1389 ++++
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 372 +
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S | 80 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4283 ++++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 870 ++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1134 +++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 417 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2752 +++++++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 1007 +++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 971 +++
+ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 188 +
+ drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2725 +++++++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 273 +
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 361 +
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 5148 ++++++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1280 +++
+ drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2550 ++++++
+ drivers/usb/host/dwc_otg/test/Makefile | 16 +
+ drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 +
+ .../usb/host/dwc_otg/test/test_mod_param.pl | 133 +
+ drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 +
+ 70 files changed, 60003 insertions(+), 16 deletions(-)
+ create mode 100644 drivers/usb/gadget/file_storage.c
+ create mode 100644 drivers/usb/host/dwc_common_port/Makefile
+ create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd
+ create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux
+ create mode 100644 drivers/usb/host/dwc_common_port/changes.txt
+ create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h
+ create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h
+ create mode 100644 drivers/usb/host/dwc_common_port/usb.h
+ create mode 100644 drivers/usb/host/dwc_otg/Makefile
+ create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg
+ create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
+ create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h
+ create mode 100644 drivers/usb/host/dwc_otg/test/Makefile
+ create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
+ create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl
+ create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl
+
+--- a/arch/arm/include/asm/irqflags.h
++++ b/arch/arm/include/asm/irqflags.h
+@@ -163,13 +163,23 @@ static inline unsigned long arch_local_s
+ }
+
+ /*
+- * restore saved IRQ & FIQ state
++ * restore saved IRQ state
+ */
+ #define arch_local_irq_restore arch_local_irq_restore
+ static inline void arch_local_irq_restore(unsigned long flags)
+ {
+- asm volatile(
+- " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
++ unsigned long temp = 0;
++ flags &= ~(1 << 6);
++ asm volatile (
++ " mrs %0, cpsr"
++ : "=r" (temp)
++ :
++ : "memory", "cc");
++ /* Preserve FIQ bit */
++ temp &= (1 << 6);
++ flags = flags | temp;
++ asm volatile (
++ " msr cpsr_c, %0 @ local_irq_restore"
+ :
+ : "r" (flags)
+ : "memory", "cc");
+--- a/arch/arm/kernel/fiqasm.S
++++ b/arch/arm/kernel/fiqasm.S
+@@ -47,3 +47,7 @@ ENTRY(__get_fiq_regs)
+ mov r0, r0 @ avoid hazard prior to ARMv4
+ ret lr
+ ENDPROC(__get_fiq_regs)
++
++ENTRY(__FIQ_Branch)
++ mov pc, r8
++ENDPROC(__FIQ_Branch)
+--- a/drivers/usb/Makefile
++++ b/drivers/usb/Makefile
+@@ -8,6 +8,7 @@
+ obj-$(CONFIG_USB) += core/
+ obj-$(CONFIG_USB_SUPPORT) += phy/
+
++obj-$(CONFIG_USB_DWCOTG) += host/
+ obj-$(CONFIG_USB_DWC3) += dwc3/
+ obj-$(CONFIG_USB_DWC2) += dwc2/
+ obj-$(CONFIG_USB_ISP1760) += isp1760/
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -154,6 +154,7 @@ int usb_choose_configuration(struct usb_
+ dev_warn(&udev->dev,
+ "no configuration chosen from %d choice%s\n",
+ num_configs, plural(num_configs));
++ dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
+ }
+ return i;
+ }
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5084,7 +5084,7 @@ static void port_event(struct usb_hub *h
+ if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
+ u16 status = 0, unused;
+
+- dev_dbg(&port_dev->dev, "over-current change\n");
++ dev_notice(&port_dev->dev, "over-current change\n");
+ usb_clear_port_feature(hdev, port1,
+ USB_PORT_FEAT_C_OVER_CURRENT);
+ msleep(100); /* Cool down */
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1924,6 +1924,85 @@ free_interfaces:
+ if (cp->string == NULL &&
+ !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
+ cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
++/* Uncomment this define to enable the HS Electrical Test support */
++#define DWC_HS_ELECT_TST 1
++#ifdef DWC_HS_ELECT_TST
++ /* Here we implement the HS Electrical Test support. The
++ * tester uses a vendor ID of 0x1A0A to indicate we should
++ * run a special test sequence. The product ID tells us
++ * which sequence to run. We invoke the test sequence by
++ * sending a non-standard SetFeature command to our root
++ * hub port. Our dwc_otg_hcd_hub_control() routine will
++ * recognize the command and perform the desired test
++ * sequence.
++ */
++ if (dev->descriptor.idVendor == 0x1A0A) {
++ /* HSOTG Electrical Test */
++ dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
++
++ if (dev->bus && dev->bus->root_hub) {
++ struct usb_device *hdev = dev->bus->root_hub;
++ dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
++
++ switch (dev->descriptor.idProduct) {
++ case 0x0101: /* TEST_SE0_NAK */
++ dev_warn(&dev->dev, "TEST_SE0_NAK\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
++ break;
++
++ case 0x0102: /* TEST_J */
++ dev_warn(&dev->dev, "TEST_J\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
++ break;
++
++ case 0x0103: /* TEST_K */
++ dev_warn(&dev->dev, "TEST_K\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
++ break;
++
++ case 0x0104: /* TEST_PACKET */
++ dev_warn(&dev->dev, "TEST_PACKET\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
++ break;
++
++ case 0x0105: /* TEST_FORCE_ENABLE */
++ dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
++ break;
++
++ case 0x0106: /* HS_HOST_PORT_SUSPEND_RESUME */
++ dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
++ break;
++
++ case 0x0107: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
++ dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
++ break;
++
++ case 0x0108: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
++ dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
++ USB_REQ_SET_FEATURE, USB_RT_PORT,
++ USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
++ }
++ }
++ }
++#endif /* DWC_HS_ELECT_TST */
+
+ /* Now that the interfaces are installed, re-enable LPM. */
+ usb_unlocked_enable_lpm(dev);
+--- a/drivers/usb/core/otg_whitelist.h
++++ b/drivers/usb/core/otg_whitelist.h
+@@ -19,33 +19,82 @@
+ static struct usb_device_id whitelist_table[] = {
+
+ /* hubs are optional in OTG, but very handy ... */
++#define CERT_WITHOUT_HUBS
++#if defined(CERT_WITHOUT_HUBS)
++{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
++#else
+ { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
+ { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
++{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
++#endif
+
+ #ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */
+ /* FIXME actually, printers are NOT supposed to use device classes;
+ * they're supposed to use interface classes...
+ */
+-{ USB_DEVICE_INFO(7, 1, 1) },
+-{ USB_DEVICE_INFO(7, 1, 2) },
+-{ USB_DEVICE_INFO(7, 1, 3) },
++//{ USB_DEVICE_INFO(7, 1, 1) },
++//{ USB_DEVICE_INFO(7, 1, 2) },
++//{ USB_DEVICE_INFO(7, 1, 3) },
+ #endif
+
+ #ifdef CONFIG_USB_NET_CDCETHER
+ /* Linux-USB CDC Ethernet gadget */
+-{ USB_DEVICE(0x0525, 0xa4a1), },
++//{ USB_DEVICE(0x0525, 0xa4a1), },
+ /* Linux-USB CDC Ethernet + RNDIS gadget */
+-{ USB_DEVICE(0x0525, 0xa4a2), },
++//{ USB_DEVICE(0x0525, 0xa4a2), },
+ #endif
+
+ #if IS_ENABLED(CONFIG_USB_TEST)
+ /* gadget zero, for testing */
+-{ USB_DEVICE(0x0525, 0xa4a0), },
++//{ USB_DEVICE(0x0525, 0xa4a0), },
+ #endif
+
++/* OPT Tester */
++{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
++{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
++{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
++{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
++{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
++{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME */
++{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
++{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
++
++/* Sony cameras */
++{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
++
++/* Memory Devices */
++//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
++//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
++//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
++//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD */
++{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
++//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
++
++/* HP Printers */
++//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
++//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
++
++/* Speakers */
++//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
++//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
++
+ { } /* Terminating entry */
+ };
+
++static inline void report_errors(struct usb_device *dev)
++{
++ /* OTG MESSAGE: report errors here, customize to match your product */
++ dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
++ le16_to_cpu(dev->descriptor.idVendor),
++ le16_to_cpu(dev->descriptor.idProduct));
++ if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
++ dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
++ } else {
++ dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
++ }
++}
++
++
+ static int is_targeted(struct usb_device *dev)
+ {
+ struct usb_device_id *id = whitelist_table;
+@@ -95,16 +144,57 @@ static int is_targeted(struct usb_device
+ continue;
+
+ return 1;
+- }
++ /* NOTE: can't use usb_match_id() since interface caches
++ * aren't set up yet. this is cut/paste from that code.
++ */
++ for (id = whitelist_table; id->match_flags; id++) {
++#ifdef DEBUG
++ dev_dbg(&dev->dev,
++ "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
++ id->idVendor,
++ id->idProduct,
++ id->bDeviceClass,
++ id->bDeviceSubClass,
++ id->bDeviceProtocol);
++#endif
+
+- /* add other match criteria here ... */
++ if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
++ id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
++ continue;
++
++ if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
++ id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
++ continue;
++
++ /* No need to test id->bcdDevice_lo != 0, since 0 is never
++ greater than any unsigned number. */
++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
++ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
++ continue;
++
++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
++ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
++ continue;
++
++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
++ (id->bDeviceClass != dev->descriptor.bDeviceClass))
++ continue;
++
++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
++ (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
++ continue;
++
++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
++ (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
++ continue;
+
++ return 1;
++ }
++ }
+
+- /* OTG MESSAGE: report errors here, customize to match your product */
+- dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
+- le16_to_cpu(dev->descriptor.idVendor),
+- le16_to_cpu(dev->descriptor.idProduct));
++ /* add other match criteria here ... */
+
++ report_errors(dev);
+ return 0;
+ }
+
+--- /dev/null
++++ b/drivers/usb/gadget/file_storage.c
+@@ -0,0 +1,3676 @@
++/*
++ * file_storage.c -- File-backed USB Storage Gadget, for USB development
++ *
++ * Copyright (C) 2003-2008 Alan Stern
++ * 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") as published by the Free Software
++ * Foundation, either version 2 of that License or (at your option) any
++ * later version.
++ *
++ * 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.
++ */
++
++
++/*
++ * The File-backed Storage Gadget acts as a USB Mass Storage device,
++ * appearing to the host as a disk drive or as a CD-ROM drive. In addition
++ * to providing an example of a genuinely useful gadget driver for a USB
++ * device, it also illustrates a technique of double-buffering for increased
++ * throughput. Last but not least, it gives an easy way to probe the
++ * behavior of the Mass Storage drivers in a USB host.
++ *
++ * Backing storage is provided by a regular file or a block device, specified
++ * by the "file" module parameter. Access can be limited to read-only by
++ * setting the optional "ro" module parameter. (For CD-ROM emulation,
++ * access is always read-only.) The gadget will indicate that it has
++ * removable media if the optional "removable" module parameter is set.
++ *
++ * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
++ * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
++ * by the optional "transport" module parameter. It also supports the
++ * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
++ * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
++ * the optional "protocol" module parameter. In addition, the default
++ * Vendor ID, Product ID, release number and serial number can be overridden.
++ *
++ * There is support for multiple logical units (LUNs), each of which has
++ * its own backing file. The number of LUNs can be set using the optional
++ * "luns" module parameter (anywhere from 1 to 8), and the corresponding
++ * files are specified using comma-separated lists for "file" and "ro".
++ * The default number of LUNs is taken from the number of "file" elements;
++ * it is 1 if "file" is not given. If "removable" is not set then a backing
++ * file must be specified for each LUN. If it is set, then an unspecified
++ * or empty backing filename means the LUN's medium is not loaded. Ideally
++ * each LUN would be settable independently as a disk drive or a CD-ROM
++ * drive, but currently all LUNs have to be the same type. The CD-ROM
++ * emulation includes a single data track and no audio tracks; hence there
++ * need be only one backing file per LUN.
++ *
++ * Requirements are modest; only a bulk-in and a bulk-out endpoint are
++ * needed (an interrupt-out endpoint is also needed for CBI). The memory
++ * requirement amounts to two 16K buffers, size configurable by a parameter.
++ * Support is included for both full-speed and high-speed operation.
++ *
++ * Note that the driver is slightly non-portable in that it assumes a
++ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
++ * interrupt-in endpoints. With most device controllers this isn't an
++ * issue, but there may be some with hardware restrictions that prevent
++ * a buffer from being used by more than one endpoint.
++ *
++ * Module options:
++ *
++ * file=filename[,filename...]
++ * Required if "removable" is not set, names of
++ * the files or block devices used for
++ * backing storage
++ * serial=HHHH... Required serial number (string of hex chars)
++ * ro=b[,b...] Default false, booleans for read-only access
++ * removable Default false, boolean for removable media
++ * luns=N Default N = number of filenames, number of
++ * LUNs to support
++ * nofua=b[,b...] Default false, booleans for ignore FUA flag
++ * in SCSI WRITE(10,12) commands
++ * stall Default determined according to the type of
++ * USB device controller (usually true),
++ * boolean to permit the driver to halt
++ * bulk endpoints
++ * cdrom Default false, boolean for whether to emulate
++ * a CD-ROM drive
++ * transport=XXX Default BBB, transport name (CB, CBI, or BBB)
++ * protocol=YYY Default SCSI, protocol name (RBC, 8020 or
++ * ATAPI, QIC, UFI, 8070, or SCSI;
++ * also 1 - 6)
++ * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID
++ * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID
++ * release=0xRRRR Override the USB release number (bcdDevice)
++ * buflen=N Default N=16384, buffer size used (will be
++ * rounded down to a multiple of
++ * PAGE_CACHE_SIZE)
++ *
++ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
++ * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
++ * default values are used for everything else.
++ *
++ * The pathnames of the backing files and the ro settings are available in
++ * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
++ * the gadget's sysfs directory. If the "removable" option is set, writing to
++ * these files will simulate ejecting/loading the medium (writing an empty
++ * line means eject) and adjusting a write-enable tab. Changes to the ro
++ * setting are not allowed when the medium is loaded or if CD-ROM emulation
++ * is being used.
++ *
++ * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
++ * The driver's SCSI command interface was based on the "Information
++ * technology - Small Computer System Interface - 2" document from
++ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
++ * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception
++ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
++ * "Universal Serial Bus Mass Storage Class UFI Command Specification"
++ * document, Revision 1.0, December 14, 1998, available at
++ * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
++ */
++
++
++/*
++ * Driver Design
++ *
++ * The FSG driver is fairly straightforward. There is a main kernel
++ * thread that handles most of the work. Interrupt routines field
++ * callbacks from the controller driver: bulk- and interrupt-request
++ * completion notifications, endpoint-0 events, and disconnect events.
++ * Completion events are passed to the main thread by wakeup calls. Many
++ * ep0 requests are handled at interrupt time, but SetInterface,
++ * SetConfiguration, and device reset requests are forwarded to the
++ * thread in the form of "exceptions" using SIGUSR1 signals (since they
++ * should interrupt any ongoing file I/O operations).
++ *
++ * The thread's main routine implements the standard command/data/status
++ * parts of a SCSI interaction. It and its subroutines are full of tests
++ * for pending signals/exceptions -- all this polling is necessary since
++ * the kernel has no setjmp/longjmp equivalents. (Maybe this is an
++ * indication that the driver really wants to be running in userspace.)
++ * An important point is that so long as the thread is alive it keeps an
++ * open reference to the backing file. This will prevent unmounting
++ * the backing file's underlying filesystem and could cause problems
++ * during system shutdown, for example. To prevent such problems, the
++ * thread catches INT, TERM, and KILL signals and converts them into
++ * an EXIT exception.
++ *
++ * In normal operation the main thread is started during the gadget's
++ * fsg_bind() callback and stopped during fsg_unbind(). But it can also
++ * exit when it receives a signal, and there's no point leaving the
++ * gadget running when the thread is dead. So just before the thread
++ * exits, it deregisters the gadget driver. This makes things a little
++ * tricky: The driver is deregistered at two places, and the exiting
++ * thread can indirectly call fsg_unbind() which in turn can tell the
++ * thread to exit. The first problem is resolved through the use of the
++ * REGISTERED atomic bitflag; the driver will only be deregistered once.
++ * The second problem is resolved by having fsg_unbind() check
++ * fsg->state; it won't try to stop the thread if the state is already
++ * FSG_STATE_TERMINATED.
++ *
++ * To provide maximum throughput, the driver uses a circular pipeline of
++ * buffer heads (struct fsg_buffhd). In principle the pipeline can be
++ * arbitrarily long; in practice the benefits don't justify having more
++ * than 2 stages (i.e., double buffering). But it helps to think of the
++ * pipeline as being a long one. Each buffer head contains a bulk-in and
++ * a bulk-out request pointer (since the buffer can be used for both
++ * output and input -- directions always are given from the host's
++ * point of view) as well as a pointer to the buffer and various state
++ * variables.
++ *
++ * Use of the pipeline follows a simple protocol. There is a variable
++ * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
++ * At any time that buffer head may still be in use from an earlier
++ * request, so each buffer head has a state variable indicating whether
++ * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the
++ * buffer head to be EMPTY, filling the buffer either by file I/O or by
++ * USB I/O (during which the buffer head is BUSY), and marking the buffer
++ * head FULL when the I/O is complete. Then the buffer will be emptied
++ * (again possibly by USB I/O, during which it is marked BUSY) and
++ * finally marked EMPTY again (possibly by a completion routine).
++ *
++ * A module parameter tells the driver to avoid stalling the bulk
++ * endpoints wherever the transport specification allows. This is
++ * necessary for some UDCs like the SuperH, which cannot reliably clear a
++ * halt on a bulk endpoint. However, under certain circumstances the
++ * Bulk-only specification requires a stall. In such cases the driver
++ * will halt the endpoint and set a flag indicating that it should clear
++ * the halt in software during the next device reset. Hopefully this
++ * will permit everything to work correctly. Furthermore, although the
++ * specification allows the bulk-out endpoint to halt when the host sends
++ * too much data, implementing this would cause an unavoidable race.
++ * The driver will always use the "no-stall" approach for OUT transfers.
++ *
++ * One subtle point concerns sending status-stage responses for ep0
++ * requests. Some of these requests, such as device reset, can involve
++ * interrupting an ongoing file I/O operation, which might take an
++ * arbitrarily long time. During that delay the host might give up on
++ * the original ep0 request and issue a new one. When that happens the
++ * driver should not notify the host about completion of the original
++ * request, as the host will no longer be waiting for it. So the driver
++ * assigns to each ep0 request a unique tag, and it keeps track of the
++ * tag value of the request associated with a long-running exception
++ * (device-reset, interface-change, or configuration-change). When the
++ * exception handler is finished, the status-stage response is submitted
++ * only if the current ep0 request tag is equal to the exception request
++ * tag. Thus only the most recently received ep0 request will get a
++ * status-stage response.
++ *
++ * Warning: This driver source file is too long. It ought to be split up
++ * into a header file plus about 3 separate .c files, to handle the details
++ * of the Gadget, USB Mass Storage, and SCSI protocols.
++ */
++
++
++/* #define VERBOSE_DEBUG */
++/* #define DUMP_MSGS */
++
++
++#include <linux/blkdev.h>
++#include <linux/completion.h>
++#include <linux/dcache.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/fcntl.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/kref.h>
++#include <linux/kthread.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/rwsem.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/freezer.h>
++#include <linux/utsname.h>
++
++#include <linux/usb/ch9.h>
++#include <linux/usb/gadget.h>
++
++#include "gadget_chips.h"
++
++
++
++/*
++ * Kbuild is not very cooperative with respect to linking separately
++ * compiled library objects into one module. So for now we won't use
++ * separate compilation ... ensuring init/exit sections work to shrink
++ * the runtime footprint, and giving us at least some parts of what
++ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
++ */
++#include "usbstring.c"
++#include "config.c"
++#include "epautoconf.c"
++
++/*-------------------------------------------------------------------------*/
++
++#define DRIVER_DESC "File-backed Storage Gadget"
++#define DRIVER_NAME "g_file_storage"
++#define DRIVER_VERSION "1 September 2010"
++
++static char fsg_string_manufacturer[64];
++static const char fsg_string_product[] = DRIVER_DESC;
++static const char fsg_string_config[] = "Self-powered";
++static const char fsg_string_interface[] = "Mass Storage";
++
++
++#include "storage_common.c"
++
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_AUTHOR("Alan Stern");
++MODULE_LICENSE("Dual BSD/GPL");
++
++/*
++ * This driver assumes self-powered hardware and has no way for users to
++ * trigger remote wakeup. It uses autoconfiguration to select endpoints
++ * and endpoint addresses.
++ */
++
++
++/*-------------------------------------------------------------------------*/
++
++
++/* Encapsulate the module parameter settings */
++
++static struct {
++ char *file[FSG_MAX_LUNS];
++ char *serial;
++ bool ro[FSG_MAX_LUNS];
++ bool nofua[FSG_MAX_LUNS];
++ unsigned int num_filenames;
++ unsigned int num_ros;
++ unsigned int num_nofuas;
++ unsigned int nluns;
++
++ bool removable;
++ bool can_stall;
++ bool cdrom;
++
++ char *transport_parm;
++ char *protocol_parm;
++ unsigned short vendor;
++ unsigned short product;
++ unsigned short release;
++ unsigned int buflen;
++
++ int transport_type;
++ char *transport_name;
++ int protocol_type;
++ char *protocol_name;
++
++} mod_data = { // Default values
++ .transport_parm = "BBB",
++ .protocol_parm = "SCSI",
++ .removable = 0,
++ .can_stall = 1,
++ .cdrom = 0,
++ .vendor = FSG_VENDOR_ID,
++ .product = FSG_PRODUCT_ID,
++ .release = 0xffff, // Use controller chip type
++ .buflen = 16384,
++ };
++
++
++module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
++ S_IRUGO);
++MODULE_PARM_DESC(file, "names of backing files or devices");
++
++module_param_named(serial, mod_data.serial, charp, S_IRUGO);
++MODULE_PARM_DESC(serial, "USB serial number");
++
++module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
++MODULE_PARM_DESC(ro, "true to force read-only");
++
++module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
++ S_IRUGO);
++MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
++
++module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
++MODULE_PARM_DESC(luns, "number of LUNs");
++
++module_param_named(removable, mod_data.removable, bool, S_IRUGO);
++MODULE_PARM_DESC(removable, "true to simulate removable media");
++
++module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
++MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
++
++module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
++MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
++
++/* In the non-TEST version, only the module parameters listed above
++ * are available. */
++#ifdef CONFIG_USB_FILE_STORAGE_TEST
++
++module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
++MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
++
++module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
++MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
++ "8070, or SCSI)");
++
++module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
++MODULE_PARM_DESC(vendor, "USB Vendor ID");
++
++module_param_named(product, mod_data.product, ushort, S_IRUGO);
++MODULE_PARM_DESC(product, "USB Product ID");
++
++module_param_named(release, mod_data.release, ushort, S_IRUGO);
++MODULE_PARM_DESC(release, "USB release number");
++
++module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
++MODULE_PARM_DESC(buflen, "I/O buffer size");
++
++#endif /* CONFIG_USB_FILE_STORAGE_TEST */
++
++
++/*
++ * These definitions will permit the compiler to avoid generating code for
++ * parts of the driver that aren't used in the non-TEST version. Even gcc
++ * can recognize when a test of a constant expression yields a dead code
++ * path.
++ */
++
++#ifdef CONFIG_USB_FILE_STORAGE_TEST
++
++#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK)
++#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI)
++#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI)
++
++#else
++
++#define transport_is_bbb() 1
++#define transport_is_cbi() 0
++#define protocol_is_scsi() 1
++
++#endif /* CONFIG_USB_FILE_STORAGE_TEST */
++
++
++/*-------------------------------------------------------------------------*/
++
++
++struct fsg_dev {
++ /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
++ spinlock_t lock;
++ struct usb_gadget *gadget;
++
++ /* filesem protects: backing files in use */
++ struct rw_semaphore filesem;
++
++ /* reference counting: wait until all LUNs are released */
++ struct kref ref;
++
++ struct usb_ep *ep0; // Handy copy of gadget->ep0
++ struct usb_request *ep0req; // For control responses
++ unsigned int ep0_req_tag;
++ const char *ep0req_name;
++
++ struct usb_request *intreq; // For interrupt responses
++ int intreq_busy;
++ struct fsg_buffhd *intr_buffhd;
++
++ unsigned int bulk_out_maxpacket;
++ enum fsg_state state; // For exception handling
++ unsigned int exception_req_tag;
++
++ u8 config, new_config;
++
++ unsigned int running : 1;
++ unsigned int bulk_in_enabled : 1;
++ unsigned int bulk_out_enabled : 1;
++ unsigned int intr_in_enabled : 1;
++ unsigned int phase_error : 1;
++ unsigned int short_packet_received : 1;
++ unsigned int bad_lun_okay : 1;
++
++ unsigned long atomic_bitflags;
++#define REGISTERED 0
++#define IGNORE_BULK_OUT 1
++#define SUSPENDED 2
++
++ struct usb_ep *bulk_in;
++ struct usb_ep *bulk_out;
++ struct usb_ep *intr_in;
++
++ struct fsg_buffhd *next_buffhd_to_fill;
++ struct fsg_buffhd *next_buffhd_to_drain;
++
++ int thread_wakeup_needed;
++ struct completion thread_notifier;
++ struct task_struct *thread_task;
++
++ int cmnd_size;
++ u8 cmnd[MAX_COMMAND_SIZE];
++ enum data_direction data_dir;
++ u32 data_size;
++ u32 data_size_from_cmnd;
++ u32 tag;
++ unsigned int lun;
++ u32 residue;
++ u32 usb_amount_left;
++
++ /* The CB protocol offers no way for a host to know when a command
++ * has completed. As a result the next command may arrive early,
++ * and we will still have to handle it. For that reason we need
++ * a buffer to store new commands when using CB (or CBI, which
++ * does not oblige a host to wait for command completion either). */
++ int cbbuf_cmnd_size;
++ u8 cbbuf_cmnd[MAX_COMMAND_SIZE];
++
++ unsigned int nluns;
++ struct fsg_lun *luns;
++ struct fsg_lun *curlun;
++ /* Must be the last entry */
++ struct fsg_buffhd buffhds[];
++};
++
++typedef void (*fsg_routine_t)(struct fsg_dev *);
++
++static int exception_in_progress(struct fsg_dev *fsg)
++{
++ return (fsg->state > FSG_STATE_IDLE);
++}
++
++/* Make bulk-out requests be divisible by the maxpacket size */
++static void set_bulk_out_req_length(struct fsg_dev *fsg,
++ struct fsg_buffhd *bh, unsigned int length)
++{
++ unsigned int rem;
++
++ bh->bulk_out_intended_length = length;
++ rem = length % fsg->bulk_out_maxpacket;
++ if (rem > 0)
++ length += fsg->bulk_out_maxpacket - rem;
++ bh->outreq->length = length;
++}
++
++static struct fsg_dev *the_fsg;
++static struct usb_gadget_driver fsg_driver;
++
++
++/*-------------------------------------------------------------------------*/
++
++static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
++{
++ const char *name;
++
++ if (ep == fsg->bulk_in)
++ name = "bulk-in";
++ else if (ep == fsg->bulk_out)
++ name = "bulk-out";
++ else
++ name = ep->name;
++ DBG(fsg, "%s set halt\n", name);
++ return usb_ep_set_halt(ep);
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * DESCRIPTORS ... most are static, but strings and (full) configuration
++ * descriptors are built on demand. Also the (static) config and interface
++ * descriptors are adjusted during fsg_bind().
++ */
++
++/* There is only one configuration. */
++#define CONFIG_VALUE 1
++
++static struct usb_device_descriptor
++device_desc = {
++ .bLength = sizeof device_desc,
++ .bDescriptorType = USB_DT_DEVICE,
++
++ .bcdUSB = cpu_to_le16(0x0200),
++ .bDeviceClass = USB_CLASS_PER_INTERFACE,
++
++ /* The next three values can be overridden by module parameters */
++ .idVendor = cpu_to_le16(FSG_VENDOR_ID),
++ .idProduct = cpu_to_le16(FSG_PRODUCT_ID),
++ .bcdDevice = cpu_to_le16(0xffff),
++
++ .iManufacturer = FSG_STRING_MANUFACTURER,
++ .iProduct = FSG_STRING_PRODUCT,
++ .iSerialNumber = FSG_STRING_SERIAL,
++ .bNumConfigurations = 1,
++};
++
++static struct usb_config_descriptor
++config_desc = {
++ .bLength = sizeof config_desc,
++ .bDescriptorType = USB_DT_CONFIG,
++
++ /* wTotalLength computed by usb_gadget_config_buf() */
++ .bNumInterfaces = 1,
++ .bConfigurationValue = CONFIG_VALUE,
++ .iConfiguration = FSG_STRING_CONFIG,
++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
++ .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
++};
++
++
++static struct usb_qualifier_descriptor
++dev_qualifier = {
++ .bLength = sizeof dev_qualifier,
++ .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
++
++ .bcdUSB = cpu_to_le16(0x0200),
++ .bDeviceClass = USB_CLASS_PER_INTERFACE,
++
++ .bNumConfigurations = 1,
++};
++
++static int populate_bos(struct fsg_dev *fsg, u8 *buf)
++{
++ memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
++ buf += USB_DT_BOS_SIZE;
++
++ memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
++ buf += USB_DT_USB_EXT_CAP_SIZE;
++
++ memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
++
++ return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
++ + USB_DT_USB_EXT_CAP_SIZE;
++}
++
++/*
++ * Config descriptors must agree with the code that sets configurations
++ * and with code managing interfaces and their altsettings. They must
++ * also handle different speeds and other-speed requests.
++ */
++static int populate_config_buf(struct usb_gadget *gadget,
++ u8 *buf, u8 type, unsigned index)
++{
++ enum usb_device_speed speed = gadget->speed;
++ int len;
++ const struct usb_descriptor_header **function;
++
++ if (index > 0)
++ return -EINVAL;
++
++ if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
++ speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
++ function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
++ ? (const struct usb_descriptor_header **)fsg_hs_function
++ : (const struct usb_descriptor_header **)fsg_fs_function;
++
++ /* for now, don't advertise srp-only devices */
++ if (!gadget_is_otg(gadget))
++ function++;
++
++ len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
++ ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
++ return len;
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++/* These routines may be called in process context or in_irq */
++
++/* Caller must hold fsg->lock */
++static void wakeup_thread(struct fsg_dev *fsg)
++{
++ /* Tell the main thread that something has happened */
++ fsg->thread_wakeup_needed = 1;
++ if (fsg->thread_task)
++ wake_up_process(fsg->thread_task);
++}
++
++
++static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
++{
++ unsigned long flags;
++
++ /* Do nothing if a higher-priority exception is already in progress.
++ * If a lower-or-equal priority exception is in progress, preempt it
++ * and notify the main thread by sending it a signal. */
++ spin_lock_irqsave(&fsg->lock, flags);
++ if (fsg->state <= new_state) {
++ fsg->exception_req_tag = fsg->ep0_req_tag;
++ fsg->state = new_state;
++ if (fsg->thread_task)
++ send_sig_info(SIGUSR1, SEND_SIG_FORCED,
++ fsg->thread_task);
++ }
++ spin_unlock_irqrestore(&fsg->lock, flags);
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++/* The disconnect callback and ep0 routines. These always run in_irq,
++ * except that ep0_queue() is called in the main thread to acknowledge
++ * completion of various requests: set config, set interface, and
++ * Bulk-only device reset. */
++
++static void fsg_disconnect(struct usb_gadget *gadget)
++{
++ struct fsg_dev *fsg = get_gadget_data(gadget);
++
++ DBG(fsg, "disconnect or port reset\n");
++ raise_exception(fsg, FSG_STATE_DISCONNECT);
++}
++
++
++static int ep0_queue(struct fsg_dev *fsg)
++{
++ int rc;
++
++ rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
++ if (rc != 0 && rc != -ESHUTDOWN) {
++
++ /* We can't do much more than wait for a reset */
++ WARNING(fsg, "error in submission: %s --> %d\n",
++ fsg->ep0->name, rc);
++ }
++ return rc;
++}
++
++static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
++{
++ struct fsg_dev *fsg = ep->driver_data;
++
++ if (req->actual > 0)
++ dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
++ if (req->status || req->actual != req->length)
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
++ req->status, req->actual, req->length);
++ if (req->status == -ECONNRESET) // Request was cancelled
++ usb_ep_fifo_flush(ep);
++
++ if (req->status == 0 && req->context)
++ ((fsg_routine_t) (req->context))(fsg);
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++/* Bulk and interrupt endpoint completion handlers.
++ * These always run in_irq. */
++
++static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
++{
++ struct fsg_dev *fsg = ep->driver_data;
++ struct fsg_buffhd *bh = req->context;
++
++ if (req->status || req->actual != req->length)
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
++ req->status, req->actual, req->length);
++ if (req->status == -ECONNRESET) // Request was cancelled
++ usb_ep_fifo_flush(ep);
++
++ /* Hold the lock while we update the request and buffer states */
++ smp_wmb();
++ spin_lock(&fsg->lock);
++ bh->inreq_busy = 0;
++ bh->state = BUF_STATE_EMPTY;
++ wakeup_thread(fsg);
++ spin_unlock(&fsg->lock);
++}
++
++static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
++{
++ struct fsg_dev *fsg = ep->driver_data;
++ struct fsg_buffhd *bh = req->context;
++
++ dump_msg(fsg, "bulk-out", req->buf, req->actual);
++ if (req->status || req->actual != bh->bulk_out_intended_length)
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
++ req->status, req->actual,
++ bh->bulk_out_intended_length);
++ if (req->status == -ECONNRESET) // Request was cancelled
++ usb_ep_fifo_flush(ep);
++
++ /* Hold the lock while we update the request and buffer states */
++ smp_wmb();
++ spin_lock(&fsg->lock);
++ bh->outreq_busy = 0;
++ bh->state = BUF_STATE_FULL;
++ wakeup_thread(fsg);
++ spin_unlock(&fsg->lock);
++}
++
++
++#ifdef CONFIG_USB_FILE_STORAGE_TEST
++static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
++{
++ struct fsg_dev *fsg = ep->driver_data;
++ struct fsg_buffhd *bh = req->context;
++
++ if (req->status || req->actual != req->length)
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
++ req->status, req->actual, req->length);
++ if (req->status == -ECONNRESET) // Request was cancelled
++ usb_ep_fifo_flush(ep);
++
++ /* Hold the lock while we update the request and buffer states */
++ smp_wmb();
++ spin_lock(&fsg->lock);
++ fsg->intreq_busy = 0;
++ bh->state = BUF_STATE_EMPTY;
++ wakeup_thread(fsg);
++ spin_unlock(&fsg->lock);
++}
++
++#else
++static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
++{}
++#endif /* CONFIG_USB_FILE_STORAGE_TEST */
++
++
++/*-------------------------------------------------------------------------*/
++
++/* Ep0 class-specific handlers. These always run in_irq. */
++
++#ifdef CONFIG_USB_FILE_STORAGE_TEST
++static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
++{
++ struct usb_request *req = fsg->ep0req;
++ static u8 cbi_reset_cmnd[6] = {
++ SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
++
++ /* Error in command transfer? */
++ if (req->status || req->length != req->actual ||
++ req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
++
++ /* Not all controllers allow a protocol stall after
++ * receiving control-out data, but we'll try anyway. */
++ fsg_set_halt(fsg, fsg->ep0);
++ return; // Wait for reset
++ }
++
++ /* Is it the special reset command? */
++ if (req->actual >= sizeof cbi_reset_cmnd &&
++ memcmp(req->buf, cbi_reset_cmnd,
++ sizeof cbi_reset_cmnd) == 0) {
++
++ /* Raise an exception to stop the current operation
++ * and reinitialize our state. */
++ DBG(fsg, "cbi reset request\n");
++ raise_exception(fsg, FSG_STATE_RESET);
++ return;
++ }
++
++ VDBG(fsg, "CB[I] accept device-specific command\n");
++ spin_lock(&fsg->lock);
++
++ /* Save the command for later */
++ if (fsg->cbbuf_cmnd_size)
++ WARNING(fsg, "CB[I] overwriting previous command\n");
++ fsg->cbbuf_cmnd_size = req->actual;
++ memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
++
++ wakeup_thread(fsg);
++ spin_unlock(&fsg->lock);
++}
++
++#else
++static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
++{}
++#endif /* CONFIG_USB_FILE_STORAGE_TEST */
++
++
++static int class_setup_req(struct fsg_dev *fsg,
++ const struct usb_ctrlrequest *ctrl)
++{
++ struct usb_request *req = fsg->ep0req;
++ int value = -EOPNOTSUPP;
++ u16 w_index = le16_to_cpu(ctrl->wIndex);
++ u16 w_value = le16_to_cpu(ctrl->wValue);
++ u16 w_length = le16_to_cpu(ctrl->wLength);
++
++ if (!fsg->config)
++ return value;
++
++ /* Handle Bulk-only class-specific requests */
++ if (transport_is_bbb()) {
++ switch (ctrl->bRequest) {
++
++ case US_BULK_RESET_REQUEST:
++ if (ctrl->bRequestType != (USB_DIR_OUT |
++ USB_TYPE_CLASS | USB_RECIP_INTERFACE))
++ break;
++ if (w_index != 0 || w_value != 0 || w_length != 0) {
++ value = -EDOM;
++ break;
++ }
++
++ /* Raise an exception to stop the current operation
++ * and reinitialize our state. */
++ DBG(fsg, "bulk reset request\n");
++ raise_exception(fsg, FSG_STATE_RESET);
++ value = DELAYED_STATUS;
++ break;
++
++ case US_BULK_GET_MAX_LUN:
++ if (ctrl->bRequestType != (USB_DIR_IN |
++ USB_TYPE_CLASS | USB_RECIP_INTERFACE))
++ break;
++ if (w_index != 0 || w_value != 0 || w_length != 1) {
++ value = -EDOM;
++ break;
++ }
++ VDBG(fsg, "get max LUN\n");
++ *(u8 *) req->buf = fsg->nluns - 1;
++ value = 1;
++ break;
++ }
++ }
++
++ /* Handle CBI class-specific requests */
++ else {
++ switch (ctrl->bRequest) {
++
++ case USB_CBI_ADSC_REQUEST:
++ if (ctrl->bRequestType != (USB_DIR_OUT |
++ USB_TYPE_CLASS | USB_RECIP_INTERFACE))
++ break;
++ if (w_index != 0 || w_value != 0) {
++ value = -EDOM;
++ break;
++ }
++ if (w_length > MAX_COMMAND_SIZE) {
++ value = -EOVERFLOW;
++ break;
++ }
++ value = w_length;
++ fsg->ep0req->context = received_cbi_adsc;
++ break;
++ }
++ }
++
++ if (value == -EOPNOTSUPP)
++ VDBG(fsg,
++ "unknown class-specific control req "
++ "%02x.%02x v%04x i%04x l%u\n",
++ ctrl->bRequestType, ctrl->bRequest,
++ le16_to_cpu(ctrl->wValue), w_index, w_length);
++ return value;
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++/* Ep0 standard request handlers. These always run in_irq. */
++
++static int standard_setup_req(struct fsg_dev *fsg,
++ const struct usb_ctrlrequest *ctrl)
++{
++ struct usb_request *req = fsg->ep0req;
++ int value = -EOPNOTSUPP;
++ u16 w_index = le16_to_cpu(ctrl->wIndex);
++ u16 w_value = le16_to_cpu(ctrl->wValue);
++
++ /* Usually this just stores reply data in the pre-allocated ep0 buffer,
++ * but config change events will also reconfigure hardware. */
++ switch (ctrl->bRequest) {
++
++ case USB_REQ_GET_DESCRIPTOR:
++ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
++ USB_RECIP_DEVICE))
++ break;
++ switch (w_value >> 8) {
++
++ case USB_DT_DEVICE:
++ VDBG(fsg, "get device descriptor\n");
++ device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
++ value = sizeof device_desc;
++ memcpy(req->buf, &device_desc, value);
++ break;
++ case USB_DT_DEVICE_QUALIFIER:
++ VDBG(fsg, "get device qualifier\n");
++ if (!gadget_is_dualspeed(fsg->gadget) ||
++ fsg->gadget->speed == USB_SPEED_SUPER)
++ break;
++ /*
++ * Assume ep0 uses the same maxpacket value for both
++ * speeds
++ */
++ dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
++ value = sizeof dev_qualifier;
++ memcpy(req->buf, &dev_qualifier, value);
++ break;
++
++ case USB_DT_OTHER_SPEED_CONFIG:
++ VDBG(fsg, "get other-speed config descriptor\n");
++ if (!gadget_is_dualspeed(fsg->gadget) ||
++ fsg->gadget->speed == USB_SPEED_SUPER)
++ break;
++ goto get_config;
++ case USB_DT_CONFIG:
++ VDBG(fsg, "get configuration descriptor\n");
++get_config:
++ value = populate_config_buf(fsg->gadget,
++ req->buf,
++ w_value >> 8,
++ w_value & 0xff);
++ break;
++
++ case USB_DT_STRING:
++ VDBG(fsg, "get string descriptor\n");
++
++ /* wIndex == language code */
++ value = usb_gadget_get_string(&fsg_stringtab,
++ w_value & 0xff, req->buf);
++ break;
++
++ case USB_DT_BOS:
++ VDBG(fsg, "get bos descriptor\n");
++
++ if (gadget_is_superspeed(fsg->gadget))
++ value = populate_bos(fsg, req->buf);
++ break;
++ }
++
++ break;
++
++ /* One config, two speeds */
++ case USB_REQ_SET_CONFIGURATION:
++ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
++ USB_RECIP_DEVICE))
++ break;
++ VDBG(fsg, "set configuration\n");
++ if (w_value == CONFIG_VALUE || w_value == 0) {
++ fsg->new_config = w_value;
++
++ /* Raise an exception to wipe out previous transaction
++ * state (queued bufs, etc) and set the new config. */
++ raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
++ value = DELAYED_STATUS;
++ }
++ break;
++ case USB_REQ_GET_CONFIGURATION:
++ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
++ USB_RECIP_DEVICE))
++ break;
++ VDBG(fsg, "get configuration\n");
++ *(u8 *) req->buf = fsg->config;
++ value = 1;
++ break;
++
++ case USB_REQ_SET_INTERFACE:
++ if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
++ USB_RECIP_INTERFACE))
++ break;
++ if (fsg->config && w_index == 0) {
++
++ /* Raise an exception to wipe out previous transaction
++ * state (queued bufs, etc) and install the new
++ * interface altsetting. */
++ raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
++ value = DELAYED_STATUS;
++ }
++ break;
++ case USB_REQ_GET_INTERFACE:
++ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
++ USB_RECIP_INTERFACE))
++ break;
++ if (!fsg->config)
++ break;
++ if (w_index != 0) {
++ value = -EDOM;
++ break;
++ }
++ VDBG(fsg, "get interface\n");
++ *(u8 *) req->buf = 0;
++ value = 1;
++ break;
++
++ default:
++ VDBG(fsg,
++ "unknown control req %02x.%02x v%04x i%04x l%u\n",
++ ctrl->bRequestType, ctrl->bRequest,
++ w_value, w_index, le16_to_cpu(ctrl->wLength));
++ }
++
++ return value;
++}
++
++
++static int fsg_setup(struct usb_gadget *gadget,
++ const struct usb_ctrlrequest *ctrl)
++{
++ struct fsg_dev *fsg = get_gadget_data(gadget);
++ int rc;
++ int w_length = le16_to_cpu(ctrl->wLength);
++
++ ++fsg->ep0_req_tag; // Record arrival of a new request
++ fsg->ep0req->context = NULL;
++ fsg->ep0req->length = 0;
++ dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
++
++ if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
++ rc = class_setup_req(fsg, ctrl);
++ else
++ rc = standard_setup_req(fsg, ctrl);
++
++ /* Respond with data/status or defer until later? */
++ if (rc >= 0 && rc != DELAYED_STATUS) {
++ rc = min(rc, w_length);
++ fsg->ep0req->length = rc;
++ fsg->ep0req->zero = rc < w_length;
++ fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
++ "ep0-