target: add Apple Silicon SoC platform (M1/M2) family init support

This commit is contained in:
coolsnowwolf 2022-08-07 03:58:27 +00:00
parent 960844ee21
commit bbdcf9095c
173 changed files with 36779 additions and 0 deletions

View File

@ -0,0 +1,29 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
include $(TOPDIR)/rules.mk
ARCH:=arm
BOARD:=silicon
BOARDNAME:=Apple Silicon family
FEATURES:=audio boot-part ext4 fpu squashfs usbgadget
SUBTARGETS:=armv8
KERNEL_PATCHVER:=5.19
define Target/Description
Build firmware image for Apple Silicon family
endef
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += \
e2fsprogs \
kmod-sound-core \
kmod-usb-hid \
mkf2fs \
partx-utils
KERNELNAME:=Image dtbs
$(eval $(call BuildTarget))

View File

@ -0,0 +1,510 @@
CONFIG_64BIT=y
# CONFIG_AIO is not set
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
CONFIG_ARCH_APPLE=y
CONFIG_ARCH_MMAP_RND_BITS=18
CONFIG_ARCH_MMAP_RND_BITS_MAX=33
CONFIG_ARCH_MMAP_RND_BITS_MIN=18
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
CONFIG_ARCH_PROC_KCORE_TEXT=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARM64=y
CONFIG_ARM64_4K_PAGES=y
CONFIG_ARM64_CNP=y
CONFIG_ARM64_ERRATUM_1165522=y
CONFIG_ARM64_ERRATUM_1286807=y
CONFIG_ARM64_ERRATUM_819472=y
CONFIG_ARM64_ERRATUM_824069=y
CONFIG_ARM64_ERRATUM_826319=y
CONFIG_ARM64_ERRATUM_827319=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_ERRATUM_858921=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_MODULE_PLTS=y
CONFIG_ARM64_PAGE_SHIFT=12
CONFIG_ARM64_PAN=y
CONFIG_ARM64_PA_BITS=48
CONFIG_ARM64_PA_BITS_48=y
CONFIG_ARM64_PMEM=y
CONFIG_ARM64_PTR_AUTH=y
CONFIG_ARM64_SVE=y
# CONFIG_ARM64_SW_TTBR0_PAN is not set
CONFIG_ARM64_TAGGED_ADDR_ABI=y
CONFIG_ARM64_UAO=y
CONFIG_ARM64_VA_BITS=48
# CONFIG_ARM64_VA_BITS_39 is not set
CONFIG_ARM64_VA_BITS_48=y
CONFIG_ARM64_VHE=y
CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y
CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=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_GIC=y
CONFIG_ARM_GIC_V3=y
CONFIG_ARM_GIC_V3_ITS=y
CONFIG_ARM_PSCI_FW=y
# CONFIG_ARM_SCMI_PROTOCOL is not set
CONFIG_ARM_SCPI_POWER_DOMAIN=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ASN1=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
CONFIG_BLK_DEBUG_FS=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_PM=y
CONFIG_BLK_SCSI_REQUEST=y
CONFIG_CAVIUM_TX2_ERRATUM_219=y
# CONFIG_CEC_CH7322 is not set
# CONFIG_CEC_MESON_AO is not set
# CONFIG_CEC_MESON_G12A_AO is not set
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLK_QORIQ=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CLZ_TAB=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_AXG=y
# CONFIG_COMMON_CLK_AXG_AUDIO is not set
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_G12A=y
CONFIG_COMMON_CLK_GXBB=y
CONFIG_COMMON_CLK_MESON_AO_CLKC=y
CONFIG_COMMON_CLK_MESON_CPU_DYNDIV=y
CONFIG_COMMON_CLK_MESON_DUALDIV=y
CONFIG_COMMON_CLK_MESON_EE_CLKC=y
CONFIG_COMMON_CLK_MESON_MPLL=y
CONFIG_COMMON_CLK_MESON_PLL=y
CONFIG_COMMON_CLK_MESON_REGMAP=y
CONFIG_COMMON_CLK_MESON_VID_PLL_DIV=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_XGENE=y
# CONFIG_COMPAT_32BIT_TIME is not set
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_CONTIG_ALLOC=y
CONFIG_COREDUMP=y
CONFIG_CPU_RMAP=y
CONFIG_CRC16=y
CONFIG_CRC7=y
CONFIG_CRC_ITU_T=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_AKCIPHER=y
CONFIG_CRYPTO_AKCIPHER2=y
CONFIG_CRYPTO_CCM=y
CONFIG_CRYPTO_CMAC=y
CONFIG_CRYPTO_CRC32=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_GF128MUL=y
CONFIG_CRYPTO_GHASH=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_RSA=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_SHA256=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_INFO=y
CONFIG_DMA_CMA=y
CONFIG_DMA_DIRECT_REMAP=y
CONFIG_DMA_REMAP=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DRM=y
CONFIG_DRM_BRIDGE=y
CONFIG_DRM_DW_HDMI=y
# CONFIG_DRM_DW_HDMI_I2S_AUDIO is not set
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_FBDEV_OVERALLOC=100
CONFIG_DRM_GEM_CMA_HELPER=y
CONFIG_DRM_KMS_CMA_HELPER=y
CONFIG_DRM_KMS_FB_HELPER=y
CONFIG_DRM_KMS_HELPER=y
CONFIG_DRM_MALI_DISPLAY=y
CONFIG_DRM_MESON=y
CONFIG_DRM_MESON_DW_HDMI=y
CONFIG_DRM_PANEL=y
CONFIG_DRM_PANEL_BRIDGE=y
CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
CONFIG_DTC=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DVB_CORE=y
CONFIG_DWMAC_DWC_QOS_ETH=y
# CONFIG_DWMAC_GENERIC is not set
CONFIG_DWMAC_MESON=y
CONFIG_EDAC_SUPPORT=y
CONFIG_ELF_CORE=y
# CONFIG_ENABLE_DEFAULT_TRACERS is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXTCON=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_FB=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_CMDLINE=y
CONFIG_FB_DEFERRED_IO=y
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_SYS_IMAGEBLIT=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
# CONFIG_FLATMEM_MANUAL is not set
CONFIG_FONT_8x16=y
CONFIG_FONT_8x8=y
CONFIG_FONT_SUPPORT=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FRAME_POINTER=y
CONFIG_FSL_ERRATUM_A008585=y
CONFIG_FS_IOMAP=y
CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_FTRACE=y
# CONFIG_FTRACE_SYSCALLS is not set
CONFIG_FUJITSU_ERRATUM_010001=y
CONFIG_FW_LOADER_PAGED_BUF=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_CPU_VULNERABILITIES=y
CONFIG_GENERIC_CSUM=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=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_GLOB=y
CONFIG_GPIOLIB=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HDMI=y
CONFIG_HISILICON_ERRATUM_161010101=y
# CONFIG_HIST_TRIGGERS is not set
CONFIG_HOLES_IN_ZONE=y
CONFIG_HWMON=y
CONFIG_HW_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MESON=y
CONFIG_I2C=y
CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_MESON=y
CONFIG_ICPLUS_PHY=y
CONFIG_IIO=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_INPUT=y
CONFIG_IPV6=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_MULTIPLE_TABLES=y
# CONFIG_IPV6_PIMSM_V2 is not set
CONFIG_IPV6_SUBTREES=y
CONFIG_IP_MROUTE_COMMON=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
# CONFIG_IR_IMON_RAW is not set
CONFIG_IR_MESON=y
# CONFIG_IR_SERIAL is not set
# CONFIG_IR_SIR is not set
# CONFIG_IR_TOY is not set
CONFIG_JBD2=y
CONFIG_KCMP=y
CONFIG_KEYS=y
# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
CONFIG_LEDS_GPIO=y
CONFIG_LIBFDT=y
# CONFIG_LIRC is not set
CONFIG_LLD_VERSION=0
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAILBOX=y
# CONFIG_MAILBOX_TEST is not set
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_BUS_MUX=y
# CONFIG_MDIO_BUS_MUX_MESON_G12A is not set
CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
# CONFIG_MDIO_GPIO is not set
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_ATTACH=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_CEC_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_MEDIA_RADIO_SUPPORT=y
CONFIG_MEDIA_SDR_SUPPORT=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_TEST_SUPPORT=y
CONFIG_MEDIA_TUNER=y
CONFIG_MEMFD_CREATE=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_MESON_CANVAS=y
CONFIG_MESON_CLK_MEASURE=y
CONFIG_MESON_EE_PM_DOMAINS=y
CONFIG_MESON_EFUSE=y
CONFIG_MESON_GXBB_WATCHDOG=y
CONFIG_MESON_GXL_PHY=y
CONFIG_MESON_GX_PM_DOMAINS=y
CONFIG_MESON_GX_SOCINFO=y
CONFIG_MESON_IRQ_GPIO=y
# CONFIG_MESON_MX_EFUSE is not set
CONFIG_MESON_MX_SOCINFO=y
CONFIG_MESON_SARADC=y
CONFIG_MESON_SECURE_PM_DOMAINS=y
CONFIG_MESON_SM=y
CONFIG_MESON_WATCHDOG=y
# CONFIG_MFD_KHADAS_MCU is not set
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_CQHCI=y
CONFIG_MMC_DW=y
# CONFIG_MMC_DW_BLUEFIELD is not set
# CONFIG_MMC_DW_EXYNOS is not set
# CONFIG_MMC_DW_HI3798CV200 is not set
CONFIG_MMC_DW_K3=y
CONFIG_MMC_DW_PLTFM=y
CONFIG_MMC_MESON_GX=y
# CONFIG_MMC_MESON_MX_SDIO is not set
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SPI=y
CONFIG_MMC_STM32_SDMMC=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_MPILIB=y
CONFIG_MQ_IOSCHED_DEADLINE=y
CONFIG_MQ_IOSCHED_KYBER=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_EMATCH=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_PTP_CLASSIFY=y
CONFIG_NLS=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_IOPORT_MAP=y
CONFIG_NR_CPUS=8
CONFIG_NVMEM=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_NET=y
CONFIG_OID_REGISTRY=y
CONFIG_PADATA=y
CONFIG_PAGE_POOL=y
CONFIG_PARTITION_PERCPU=y
CONFIG_PCS_XPCS=y
CONFIG_PGTABLE_LEVELS=4
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_PHY_MESON8B_USB2=y
CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG=y
CONFIG_PHY_MESON_AXG_PCIE=y
# CONFIG_PHY_MESON_G12A_USB2 is not set
# CONFIG_PHY_MESON_G12A_USB3_PCIE is not set
CONFIG_PHY_MESON_GXL_USB2=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_MESON=y
CONFIG_PINCTRL_MESON8_PMX=y
# CONFIG_PINCTRL_MESON_A1 is not set
# CONFIG_PINCTRL_MESON_AXG is not set
# CONFIG_PINCTRL_MESON_G12A is not set
CONFIG_PINCTRL_MESON_GXBB=y
CONFIG_PINCTRL_MESON_GXL=y
CONFIG_PKCS7_MESSAGE_PARSER=y
# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set
CONFIG_PLATFORM_MHU=y
CONFIG_PM=y
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_POWER_RESET=y
CONFIG_POWER_SUPPLY=y
CONFIG_POWER_SUPPLY_HWMON=y
CONFIG_PPS=y
CONFIG_PRINTK_TIME=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PWM=y
CONFIG_PWM_MESON=y
CONFIG_PWM_SYSFS=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_RATIONAL=y
CONFIG_RCU_NEED_SEGCBLIST=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RC_CORE=y
CONFIG_RC_DEVICES=y
# CONFIG_RC_XBOX_DVD is not set
CONFIG_REALTEK_AUTOPM=y
CONFIG_REALTEK_PHY=y
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_DEBUG=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_MESON=y
# CONFIG_RESET_MESON_AUDIO_ARB is not set
CONFIG_RFS_ACCEL=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
CONFIG_RPS=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SCSI=y
CONFIG_SDIO_UART=y
# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_MESON=y
CONFIG_SERIAL_MESON_CONSOLE=y
CONFIG_SG_POOL=y
CONFIG_SMP=y
CONFIG_SOC_BUS=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_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MESON_SPICC=y
CONFIG_SPI_MESON_SPIFC=y
CONFIG_SRCU=y
CONFIG_STACKTRACE=y
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
# CONFIG_STMMAC_SELFTESTS is not set
CONFIG_SWIOTLB=y
CONFIG_SWPHY=y
CONFIG_SYNC_FILE=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_SYS_SUPPORTS_HUGETLBFS=y
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_TUN=y
CONFIG_UNMAP_KERNEL_AT_EL0=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_DWC2=y
CONFIG_USB_DWC2_DUAL_ROLE=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_DUAL_ROLE=y
# CONFIG_USB_DWC3_GADGET is not set
# CONFIG_USB_DWC3_HOST is not set
CONFIG_USB_DWC3_MESON_G12A=y
CONFIG_USB_DWC3_OF_SIMPLE=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
# CONFIG_USB_ETH is not set
CONFIG_USB_GADGET=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_OTG=y
CONFIG_USB_OTG_FSM=y
CONFIG_USB_PHY=y
# CONFIG_USB_PULSE8_CEC is not set
# CONFIG_USB_RAINSHADOW_CEC is not set
CONFIG_USB_ROLE_SWITCH=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_REALTEK=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ULPI=y
CONFIG_USB_ULPI_VIEWPORT=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_PLATFORM=y
CONFIG_VIDEOMODE_HELPERS=y
CONFIG_VMAP_STACK=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_WATCHDOG_CORE=y
CONFIG_X509_CERTIFICATE_PARSER=y
CONFIG_XPS=y
CONFIG_ZONE_DMA32=y

View File

@ -0,0 +1,313 @@
From 6515c017a89844b13e041b739cba63ca1fd5dcb2 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 3 May 2022 00:08:56 +0900
Subject: [PATCH 001/171] arm64: dts: apple: Add CPU topology & cpufreq nodes
for t8103
Add the missing CPU topology/capacity information and the cpufreq nodes,
so we can have CPU frequency scaling and the scheduler has the
information it needs to make the correct decisions.
Boost states are commented out, as they are not yet available (that
requires CPU deep sleep support, to be eventually done via PSCI).
The driver supports them fine; the hardware will just refuse to ever
go into them at this time, so don't expose them to users until that's
done.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103.dtsi | 203 +++++++++++++++++++++++++--
1 file changed, 193 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 9f8f4145db88..3df126a5a7dd 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -22,71 +22,245 @@ cpus {
#address-cells = <2>;
#size-cells = <0>;
- cpu0: cpu@0 {
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu_e0>;
+ };
+ core1 {
+ cpu = <&cpu_e1>;
+ };
+ core2 {
+ cpu = <&cpu_e2>;
+ };
+ core3 {
+ cpu = <&cpu_e3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu_p0>;
+ };
+ core1 {
+ cpu = <&cpu_p1>;
+ };
+ core2 {
+ cpu = <&cpu_p2>;
+ };
+ core3 {
+ cpu = <&cpu_p3>;
+ };
+ };
+ };
+
+ cpu_e0: cpu@0 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x0>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 0>;
};
- cpu1: cpu@1 {
+ cpu_e1: cpu@1 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x1>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 0>;
};
- cpu2: cpu@2 {
+ cpu_e2: cpu@2 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x2>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 0>;
};
- cpu3: cpu@3 {
+ cpu_e3: cpu@3 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x3>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 0>;
};
- cpu4: cpu@10100 {
+ cpu_p0: cpu@10100 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10100>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
};
- cpu5: cpu@10101 {
+ cpu_p1: cpu@10101 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10101>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
};
- cpu6: cpu@10102 {
+ cpu_p2: cpu@10102 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10102>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
};
- cpu7: cpu@10103 {
+ cpu_p3: cpu@10103 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10103>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
+ };
+ };
+
+ ecluster_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <7500>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <972000000>;
+ opp-level = <2>;
+ clock-latency-ns = <22000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1332000000>;
+ opp-level = <3>;
+ clock-latency-ns = <27000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-level = <4>;
+ clock-latency-ns = <33000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <2064000000>;
+ opp-level = <5>;
+ clock-latency-ns = <50000>;
};
};
+ pcluster_opp: opp-table-1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <8000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <828000000>;
+ opp-level = <2>;
+ clock-latency-ns = <19000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-level = <3>;
+ clock-latency-ns = <21000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1284000000>;
+ opp-level = <4>;
+ clock-latency-ns = <23000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-level = <5>;
+ clock-latency-ns = <24000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1728000000>;
+ opp-level = <6>;
+ clock-latency-ns = <29000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1956000000>;
+ opp-level = <7>;
+ clock-latency-ns = <31000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <2184000000>;
+ opp-level = <8>;
+ clock-latency-ns = <34000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <2388000000>;
+ opp-level = <9>;
+ clock-latency-ns = <36000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <2592000000>;
+ opp-level = <10>;
+ clock-latency-ns = <51000>;
+ };
+ opp11 {
+ opp-hz = /bits/ 64 <2772000000>;
+ opp-level = <11>;
+ clock-latency-ns = <54000>;
+ };
+ opp12 {
+ opp-hz = /bits/ 64 <2988000000>;
+ opp-level = <12>;
+ clock-latency-ns = <55000>;
+ };
+#if 0
+ /* Not available until CPU deep sleep is implemented */
+ opp13 {
+ opp-hz = /bits/ 64 <3096000000>;
+ opp-level = <13>;
+ clock-latency-ns = <55000>;
+ turbo-mode;
+ };
+ opp14 {
+ opp-hz = /bits/ 64 <3144000000>;
+ opp-level = <14>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+ opp15 {
+ opp-hz = /bits/ 64 <3204000000>;
+ opp-level = <15>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+#endif
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupt-parent = <&aic>;
@@ -124,6 +298,15 @@ soc {
ranges;
nonposted-mmio;
+ cpufreq_hw: cpufreq@210e20000 {
+ compatible = "apple,t8103-soc-cpufreq", "apple,soc-cpufreq";
+ reg = <0x2 0x10e20000 0 0x1000>,
+ <0x2 0x11e20000 0 0x1000>;
+ reg-names = "cluster0", "cluster1";
+
+ #freq-domain-cells = <1>;
+ };
+
i2c0: i2c@235010000 {
compatible = "apple,t8103-i2c", "apple,i2c";
reg = <0x2 0x35010000 0x0 0x4000>;
@@ -229,12 +412,12 @@ aic: interrupt-controller@23b100000 {
affinities {
e-core-pmu-affinity {
apple,fiq-index = <AIC_CPU_PMU_E>;
- cpus = <&cpu0 &cpu1 &cpu2 &cpu3>;
+ cpus = <&cpu_e0 &cpu_e1 &cpu_e2 &cpu_e3>;
};
p-core-pmu-affinity {
apple,fiq-index = <AIC_CPU_PMU_P>;
- cpus = <&cpu4 &cpu5 &cpu6 &cpu7>;
+ cpus = <&cpu_p0 &cpu_p1 &cpu_p2 &cpu_p3>;
};
};
};
--
2.34.1

View File

@ -0,0 +1,56 @@
From a994e9c9c1e45fbffeb9844c182e27c58c208404 Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Thu, 9 Dec 2021 17:22:51 +0100
Subject: [PATCH 002/171] arm64: dts: apple: t8103: Add ANS2 nodes
---
arch/arm64/boot/dts/apple/t8103.dtsi | 33 ++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 3df126a5a7dd..66544e39a20a 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -561,6 +561,39 @@ pinctrl_aop: pinctrl@24a820000 {
<AIC_IRQ 274 IRQ_TYPE_LEVEL_HIGH>;
};
+ ans_mbox: mbox@277408000 {
+ compatible = "apple,t8103-asc-mailbox", "apple,asc-mailbox-v4";
+ reg = <0x2 0x77408000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 583 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 584 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 585 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 586 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "send-empty", "send-not-empty",
+ "recv-empty", "recv-not-empty";
+ #mbox-cells = <0>;
+ power-domains = <&ps_ans2>;
+ };
+
+ sart: sart@27bc50000 {
+ compatible = "apple,t8103-sart", "apple,sart2";
+ reg = <0x2 0x7bc50000 0x0 0x10000>;
+ power-domains = <&ps_ans2>;
+ };
+
+ nvme@27bcc0000 {
+ compatible = "apple,t8103-nvme-ans2", "apple,nvme-ans2";
+ reg = <0x2 0x7bcc0000 0x0 0x40000>,
+ <0x2 0x77400000 0x0 0x4000>;
+ reg-names = "nvme", "ans";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 590 IRQ_TYPE_LEVEL_HIGH>;
+ mboxes = <&ans_mbox>;
+ apple,sart = <&sart>;
+ power-domains = <&ps_ans2>;
+ resets = <&ps_ans2>;
+ };
+
pcie0_dart_0: dart@681008000 {
compatible = "apple,t8103-dart";
reg = <0x6 0x81008000 0x0 0x4000>;
--
2.34.1

View File

@ -0,0 +1,274 @@
From ba2a0e6cfe463e97ee1056dd45d7fd4eee24bf09 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Fri, 26 Nov 2021 15:37:23 +0900
Subject: [PATCH 003/171] arm64: dts: apple: t8103: Add dwc3 nodes
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-j274.dts | 12 +++++
arch/arm64/boot/dts/apple/t8103-j293.dts | 12 +++++
arch/arm64/boot/dts/apple/t8103-j313.dts | 12 +++++
arch/arm64/boot/dts/apple/t8103-j456.dts | 12 +++++
arch/arm64/boot/dts/apple/t8103-j457.dts | 12 +++++
arch/arm64/boot/dts/apple/t8103-jxxx.dtsi | 51 +++++++++++++++++++
arch/arm64/boot/dts/apple/t8103.dtsi | 60 +++++++++++++++++++++++
7 files changed, 171 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-j274.dts b/arch/arm64/boot/dts/apple/t8103-j274.dts
index 2cd429efba5b..214476814797 100644
--- a/arch/arm64/boot/dts/apple/t8103-j274.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j274.dts
@@ -21,6 +21,18 @@ aliases {
};
};
+/*
+ * Provide labels for the USB type C ports.
+ */
+
+&typec0 {
+ label = "USB-C Back-left";
+};
+
+&typec1 {
+ label = "USB-C Back-right";
+};
+
/*
* Force the bus number assignments so that we can declare some of the
* on-board devices and properties that are populated by the bootloader
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 49cdf4b560a3..6f08fd64f482 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -17,6 +17,18 @@ / {
model = "Apple MacBook Pro (13-inch, M1, 2020)";
};
+/*
+ * Provide labels for the USB type C ports.
+ */
+
+&typec0 {
+ label = "USB-C Left-back";
+};
+
+&typec1 {
+ label = "USB-C Left-front";
+};
+
/*
* Remove unused PCIe ports and disable the associated DARTs.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index b0ebb45bdb6f..114aa87c8cb4 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -17,6 +17,18 @@ / {
model = "Apple MacBook Air (M1, 2020)";
};
+/*
+ * Provide labels for the USB type C ports.
+ */
+
+&typec0 {
+ label = "USB-C Left-back";
+};
+
+&typec1 {
+ label = "USB-C Left-front";
+};
+
/*
* Remove unused PCIe ports and disable the associated DARTs.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index 884fddf7d363..9814c97cd9ba 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -39,6 +39,18 @@ hpm3: usb-pd@3c {
};
};
+/*
+ * Provide labels for the USB type C ports.
+ */
+
+&typec0 {
+ label = "USB-C Back-right";
+};
+
+&typec1 {
+ label = "USB-C Back-right-middle";
+};
+
/*
* Force the bus number assignments so that we can declare some of the
* on-board devices and properties that are populated by the bootloader
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index d7c622931627..0f4cc643741c 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -21,6 +21,18 @@ aliases {
};
};
+/*
+ * Provide labels for the USB type C ports.
+ */
+
+&typec0 {
+ label = "USB-C Back-right";
+};
+
+&typec1 {
+ label = "USB-C Back-left";
+};
+
/*
* Force the bus number assignments so that we can declare some of the
* on-board devices and properties that are populated by the bootloader
diff --git a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
index fe2ae40fa9dd..020a9d8b31e9 100644
--- a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
@@ -52,6 +52,23 @@ hpm0: usb-pd@38 {
interrupt-parent = <&pinctrl_ap>;
interrupts = <106 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec0: connector {
+ compatible = "usb-c-connector";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec0_con_hs: endpoint {
+ remote-endpoint = <&typec0_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm1: usb-pd@3f {
@@ -60,6 +77,40 @@ hpm1: usb-pd@3f {
interrupt-parent = <&pinctrl_ap>;
interrupts = <106 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec1: connector {
+ compatible = "usb-c-connector";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec1_con_hs: endpoint {
+ remote-endpoint = <&typec1_usb_hs>;
+ };
+ };
+ };
+ };
+ };
+};
+
+/* USB controllers */
+&dwc3_0 {
+ port {
+ typec0_usb_hs: endpoint {
+ remote-endpoint = <&typec0_con_hs>;
+ };
+ };
+};
+
+&dwc3_1 {
+ port {
+ typec1_usb_hs: endpoint {
+ remote-endpoint = <&typec1_con_hs>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 66544e39a20a..ec7234cdc861 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -594,6 +594,66 @@ nvme@27bcc0000 {
resets = <&ps_ans2>;
};
+ dwc3_0: usb@382280000 {
+ compatible = "apple,t8103-dwc3", "apple,dwc3", "snps,dwc3";
+ reg = <0x3 0x82280000 0x0 0x100000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 777 IRQ_TYPE_LEVEL_HIGH>;
+ dr_mode = "otg";
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ iommus = <&dwc3_0_dart_0 0>, <&dwc3_0_dart_1 1>;
+ power-domains = <&ps_atc0_usb>;
+ };
+
+ dwc3_0_dart_0: iommu@382f00000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x3 0x82f00000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 781 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_atc0_usb>;
+ };
+
+ dwc3_0_dart_1: iommu@382f80000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x3 0x82f80000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 781 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_atc0_usb>;
+ };
+
+ dwc3_1: usb@502280000 {
+ compatible = "apple,t8103-dwc3", "apple,dwc3", "snps,dwc3";
+ reg = <0x5 0x02280000 0x0 0x100000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 857 IRQ_TYPE_LEVEL_HIGH>;
+ dr_mode = "otg";
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ iommus = <&dwc3_1_dart_0 0>, <&dwc3_1_dart_1 1>;
+ power-domains = <&ps_atc1_usb>;
+ };
+
+ dwc3_1_dart_0: iommu@502f00000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x5 0x02f00000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 861 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_atc1_usb>;
+ };
+
+ dwc3_1_dart_1: iommu@502f80000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x5 0x02f80000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 861 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_atc1_usb>;
+ };
+
pcie0_dart_0: dart@681008000 {
compatible = "apple,t8103-dart";
reg = <0x6 0x81008000 0x0 0x4000>;
--
2.34.1

View File

@ -0,0 +1,133 @@
From 226311814eda36c1ad693189e5402ced55e91f11 Mon Sep 17 00:00:00 2001
From: Janne Grunau <j@jannau.net>
Date: Fri, 26 Nov 2021 00:24:15 +0100
Subject: [PATCH 004/171] arm64: dts: apple: t8103: Add spi3/keyboard nodes
Enables keyboard and touchpad input on MacBook Air (M1, 2020) and
MacBook Pro (13-inch, M1, 2020).
Signed-off-by: Janne Grunau <j@jannau.net>
---
arch/arm64/boot/dts/apple/t8103-j293.dts | 20 +++++++++++++++++
arch/arm64/boot/dts/apple/t8103-j313.dts | 20 +++++++++++++++++
arch/arm64/boot/dts/apple/t8103.dtsi | 28 ++++++++++++++++++++++++
3 files changed, 68 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 6f08fd64f482..9405e97a85f2 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -29,6 +29,26 @@ &typec1 {
label = "USB-C Left-front";
};
+&spi3 {
+ status = "okay";
+
+ hid-transport@0 {
+ compatible = "apple,spi-hid-transport";
+ reg = <0>;
+ spi-max-frequency = <8000000>;
+ /*
+ * cs-setup and cs-hold delays are derived from Apple's ADT
+ * Mac OS driver meta data secify 45 us for 'cs to clock' and
+ * 'clock to cs' delays.
+ */
+ spi-cs-setup-delay-ns = <20000>;
+ spi-cs-hold-delay-ns = <20000>;
+ spi-cs-inactive-delay-ns = <250000>;
+ spien-gpios = <&pinctrl_ap 195 0>;
+ interrupts-extended = <&pinctrl_nub 13 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
/*
* Remove unused PCIe ports and disable the associated DARTs.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index 114aa87c8cb4..bc84f8af0b1d 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -29,6 +29,26 @@ &typec1 {
label = "USB-C Left-front";
};
+&spi3 {
+ status = "okay";
+
+ hid-transport@0 {
+ compatible = "apple,spi-hid-transport";
+ reg = <0>;
+ spi-max-frequency = <8000000>;
+ /*
+ * cs-setup and cs-hold delays are derived from Apple's ADT
+ * Mac OS driver meta data secify 45 us for 'cs to clock' and
+ * 'clock to cs' delays.
+ */
+ spi-cs-setup-delay-ns = <20000>;
+ spi-cs-hold-delay-ns = <20000>;
+ spi-cs-inactive-delay-ns = <250000>;
+ spien-gpios = <&pinctrl_ap 195 0>;
+ interrupts-extended = <&pinctrl_nub 13 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
/*
* Remove unused PCIe ports and disable the associated DARTs.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index ec7234cdc861..9750438c30dd 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -290,6 +290,13 @@ clkref: clock-ref {
clock-output-names = "clkref";
};
+ clk_120m: clock-120m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <120000000>;
+ clock-output-names = "clk_120m";
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <2>;
@@ -374,6 +381,20 @@ i2c4: i2c@235020000 {
status = "disabled"; /* only used in J293 */
};
+ spi3: spi@23510c000 {
+ compatible = "apple,t8103-spi", "apple,spi";
+ reg = <0x2 0x3510c000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 617 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_120m>;
+ pinctrl-0 = <&spi3_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_spi3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled"; /* only used in J293/J313 */
+ };
+
serial0: serial@235200000 {
compatible = "apple,s5l-uart";
reg = <0x2 0x35200000 0x0 0x1000>;
@@ -475,6 +496,13 @@ i2c4_pins: i2c4-pins {
<APPLE_PINMUX(134, 1)>;
};
+ spi3_pins: spi3-pins {
+ pinmux = <APPLE_PINMUX(46, 1)>,
+ <APPLE_PINMUX(47, 1)>,
+ <APPLE_PINMUX(48, 1)>,
+ <APPLE_PINMUX(49, 1)>;
+ };
+
pcie_pins: pcie-pins {
pinmux = <APPLE_PINMUX(150, 1)>,
<APPLE_PINMUX(151, 1)>,
--
2.34.1

View File

@ -0,0 +1,40 @@
From d1cc45edca0943c77a7125cb9de0300329314169 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sat, 19 Mar 2022 05:50:47 +0900
Subject: [PATCH 005/171] arm64: dts: apple: Fix j45x model years
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-j456.dts | 2 +-
arch/arm64/boot/dts/apple/t8103-j457.dts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index 9814c97cd9ba..bb48255250c7 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -14,7 +14,7 @@
/ {
compatible = "apple,j456", "apple,t8103", "apple,arm-platform";
- model = "Apple iMac (24-inch, 4x USB-C, M1, 2020)";
+ model = "Apple iMac (24-inch, 4x USB-C, M1, 2021)";
aliases {
ethernet0 = &ethernet0;
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index 0f4cc643741c..80600c3fa769 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -14,7 +14,7 @@
/ {
compatible = "apple,j457", "apple,t8103", "apple,arm-platform";
- model = "Apple iMac (24-inch, 2x USB-C, M1, 2020)";
+ model = "Apple iMac (24-inch, 2x USB-C, M1, 2021)";
aliases {
ethernet0 = &ethernet0;
--
2.34.1

View File

@ -0,0 +1,112 @@
From 30c1cffd27d0154787eba4a4a2e9c6a3e7504879 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:07:17 +0900
Subject: [PATCH 006/171] arm64: dts: apple: Add WiFi module and antenna
properties
Add the new module-instance/antenna-sku properties required to select
WiFi firmwares properly to all board device trees.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-j274.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j293.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j313.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j456.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j457.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-jxxx.dtsi | 2 ++
6 files changed, 22 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-j274.dts b/arch/arm64/boot/dts/apple/t8103-j274.dts
index 214476814797..aaa3019a4db2 100644
--- a/arch/arm64/boot/dts/apple/t8103-j274.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j274.dts
@@ -21,6 +21,10 @@ aliases {
};
};
+&wifi0 {
+ brcm,board-type = "apple,atlantisb";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 9405e97a85f2..4f5f7d38e799 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -17,6 +17,10 @@ / {
model = "Apple MacBook Pro (13-inch, M1, 2020)";
};
+&wifi0 {
+ brcm,board-type = "apple,honshu";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index bc84f8af0b1d..d6722d8809d1 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -17,6 +17,10 @@ / {
model = "Apple MacBook Air (M1, 2020)";
};
+&wifi0 {
+ brcm,board-type = "apple,shikoku";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index bb48255250c7..3d0a91ac29ae 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -21,6 +21,10 @@ aliases {
};
};
+&wifi0 {
+ brcm,board-type = "apple,capri";
+};
+
&i2c0 {
hpm2: usb-pd@3b {
compatible = "apple,cd321x";
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index 80600c3fa769..7e3a0e95e837 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -21,6 +21,10 @@ aliases {
};
};
+&wifi0 {
+ brcm,board-type = "apple,santorini";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
index 020a9d8b31e9..4fb89066bd17 100644
--- a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
@@ -122,8 +122,10 @@ typec1_usb_hs: endpoint {
&port00 {
bus-range = <1 1>;
wifi0: network@0,0 {
+ compatible = "pci14e4,4425";
reg = <0x10000 0x0 0x0 0x0 0x0>;
/* To be filled by the loader */
local-mac-address = [00 00 00 00 00 00];
+ apple,antenna-sku = "XX";
};
};
--
2.34.1

View File

@ -0,0 +1,31 @@
From 8d2ddaeace21e3960326fb52a052083b5a1f5e1d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 6 Feb 2022 21:22:29 +0900
Subject: [PATCH 007/171] arm64: dts: apple: Add PCI power enable GPIOs
t8103:
- WLAN (SMC PMU GPIO #13)
t600x:
- WLAN (SMC PMU GPIO #13)
- SD (SMC PMU GPIO #26)
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-jxxx.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
index 4fb89066bd17..e62664b6e450 100644
--- a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
@@ -121,6 +121,7 @@ typec1_usb_hs: endpoint {
*/
&port00 {
bus-range = <1 1>;
+ pwren-gpios = <&smc_gpio 13 GPIO_ACTIVE_HIGH>;
wifi0: network@0,0 {
compatible = "pci14e4,4425";
reg = <0x10000 0x0 0x0 0x0 0x0>;
--
2.34.1

View File

@ -0,0 +1,51 @@
From 6728598e7a5a5fb2cb05c65294269b6844b1ea5d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Fri, 4 Feb 2022 12:59:39 +0900
Subject: [PATCH 008/171] arm64: dts: apple: Add SMC node to t8103/t6001
devicetrees
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103.dtsi | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 9750438c30dd..23cc325a49bb 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -547,6 +547,32 @@ wdt: watchdog@23d2b0000 {
interrupts = <AIC_IRQ 338 IRQ_TYPE_LEVEL_HIGH>;
};
+ smc_mbox: mbox@23e408000 {
+ compatible = "apple,t8103-asc-mailbox", "apple,asc-mailbox-v4";
+ reg = <0x2 0x3e408000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 400 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 401 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 402 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 403 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "send-empty", "send-not-empty",
+ "recv-empty", "recv-not-empty";
+ #mbox-cells = <0>;
+ };
+
+ smc: smc@23e400000 {
+ compatible = "apple,t8103-smc", "apple,smc";
+ reg = <0x2 0x3e400000 0x0 0x4000>,
+ <0x2 0x3fe00000 0x0 0x100000>;
+ reg-names = "smc", "sram";
+ mboxes = <&smc_mbox>;
+
+ smc_gpio: gpio {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
pinctrl_smc: pinctrl@23e820000 {
compatible = "apple,t8103-pinctrl", "apple,pinctrl";
reg = <0x2 0x3e820000 0x0 0x4000>;
--
2.34.1

View File

@ -0,0 +1,127 @@
From aee7c563697559e06f306d8a9e1b5a33c5c330d9 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 15 Feb 2022 18:54:35 +0900
Subject: [PATCH 009/171] arm64: dts: apple: Add PMU NVMEM and SMC RTC/reboot
nodes
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103.dtsi | 88 ++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 23cc325a49bb..c2fb4f32590c 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -11,6 +11,7 @@
#include <dt-bindings/interrupt-controller/apple-aic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pinctrl/apple.h>
+#include <dt-bindings/spmi/spmi.h>
/ {
compatible = "apple,t8103", "apple,arm-platform";
@@ -510,6 +511,81 @@ pcie_pins: pcie-pins {
};
};
+ nub_spmi: spmi@23d0d9300 {
+ compatible = "apple,t8103-spmi", "apple,spmi";
+ reg = <0x2 0x3d0d9300 0x0 0x100>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ pmu1: pmu@f {
+ compatible = "apple,sera-pmu", "apple,spmi-pmu";
+ reg = <0xf SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ rtc_nvmem@d000 {
+ compatible = "apple,spmi-pmu-nvmem";
+ reg = <0xd000 0x300>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm_setting: pm-setting@1 {
+ reg = <0x1 0x1>;
+ };
+
+ rtc_offset: rtc-offset@100 {
+ reg = <0x100 0x6>;
+ };
+ };
+
+ legacy_nvmem@9f00 {
+ compatible = "apple,spmi-pmu-nvmem";
+ reg = <0x9f00 0x20>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot_stage: boot-stage@1 {
+ reg = <0x1 0x1>;
+ };
+
+ boot_error_count: boot-error-count@2 {
+ reg = <0x2 0x1>;
+ bits = <0 4>;
+ };
+
+ panic_count: panic-count@2 {
+ reg = <0x2 0x1>;
+ bits = <4 4>;
+ };
+
+ boot_error_stage: boot-error-stage@3 {
+ reg = <0x3 0x1>;
+ };
+
+ shutdown_flag: shutdown-flag@f {
+ reg = <0xf 0x1>;
+ bits = <3 1>;
+ };
+ };
+
+ scrpad_nvmem@a000 {
+ compatible = "apple,spmi-pmu-nvmem";
+ reg = <0xa000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ fault_shadow: fault-shadow@67b {
+ reg = <0x67b 0x10>;
+ };
+
+ socd: socd@b00 {
+ reg = <0xb00 0x400>;
+ };
+ };
+
+ };
+ };
+
pinctrl_nub: pinctrl@23d1f0000 {
compatible = "apple,t8103-pinctrl", "apple,pinctrl";
reg = <0x2 0x3d1f0000 0x0 0x4000>;
@@ -571,6 +647,18 @@ smc_gpio: gpio {
gpio-controller;
#gpio-cells = <2>;
};
+
+ smc_rtc: rtc {
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "rtc_offset";
+ };
+
+ smc_reboot: reboot {
+ nvmem-cells = <&shutdown_flag>, <&boot_stage>,
+ <&boot_error_count>, <&panic_count>, <&pm_setting>;
+ nvmem-cell-names = "shutdown_flag", "boot_stage",
+ "boot_error_count", "panic_count", "pm_setting";
+ };
};
pinctrl_smc: pinctrl@23e820000 {
--
2.34.1

View File

@ -0,0 +1,56 @@
From ed05baab200d58bdc024e7797780a1d95677dce3 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Wed, 2 Mar 2022 23:23:51 +0900
Subject: [PATCH 010/171] arm64: dts: apple: Re-parent ANS2 power domains
Turns out that the APCIE_ST*_SYS domains do hard-depend on ANS2, so
without this they refuse to power up.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-pmgr.dtsi | 7 +------
arch/arm64/boot/dts/apple/t8103.dtsi | 3 ++-
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
index fc51bc872468..a6dbb1f485d8 100644
--- a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
@@ -725,11 +725,6 @@ ps_ans2: power-controller@3f0 {
#power-domain-cells = <0>;
#reset-cells = <0>;
label = "ans2";
- /*
- * The ADT makes ps_apcie_st depend on ps_ans2 instead, but this
- * doesn't make much sense since ANS2 uses APCIE_ST.
- */
- power-domains = <&ps_apcie_st>;
};
ps_gfx: power-controller@3f8 {
@@ -836,7 +831,7 @@ ps_apcie_st: power-controller@418 {
#power-domain-cells = <0>;
#reset-cells = <0>;
label = "apcie_st";
- power-domains = <&ps_apcie>;
+ power-domains = <&ps_apcie>, <&ps_ans2>;
};
ps_ane_sys: power-controller@470 {
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index c2fb4f32590c..f96a732e6211 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -732,7 +732,8 @@ nvme@27bcc0000 {
interrupts = <AIC_IRQ 590 IRQ_TYPE_LEVEL_HIGH>;
mboxes = <&ans_mbox>;
apple,sart = <&sart>;
- power-domains = <&ps_ans2>;
+ power-domains = <&ps_ans2>, <&ps_apcie_st>;
+ power-domain-names = "ans", "apcie0";
resets = <&ps_ans2>;
};
--
2.34.1

View File

@ -0,0 +1,39 @@
From b348548945561245a2aea95ef9a9b5afe1efa78c Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 3 Mar 2022 02:20:39 +0900
Subject: [PATCH 011/171] arm64: dts: apple: Mark ATC USB AON domains as
always-on
Shutting these down breaks dwc3 init done by the firmware. We probably
never want to do this anyway. It might be possible remove this once
a PHY driver is in place to do the init properly, but it may not be
worth it.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-pmgr.dtsi | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
index a6dbb1f485d8..926b1e54b64b 100644
--- a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
@@ -1103,6 +1103,7 @@ ps_atc0_usb_aon: power-controller@88 {
#power-domain-cells = <0>;
#reset-cells = <0>;
label = "atc0_usb_aon";
+ apple,always-on; /* Needs to stay on for dwc3 to work */
};
ps_atc1_usb_aon: power-controller@90 {
@@ -1111,6 +1112,7 @@ ps_atc1_usb_aon: power-controller@90 {
#power-domain-cells = <0>;
#reset-cells = <0>;
label = "atc1_usb_aon";
+ apple,always-on; /* Needs to stay on for dwc3 to work */
};
ps_atc0_usb: power-controller@98 {
--
2.34.1

View File

@ -0,0 +1,64 @@
From 470d9385f7c772c4cb88e0fdfa3484baba9d15c9 Mon Sep 17 00:00:00 2001
From: Thomas Glanzmann <thomas@glanzmann.de>
Date: Mon, 21 Feb 2022 23:01:36 +0100
Subject: [PATCH 012/171] arm64: dts: apple: Add backlight node to j293/j313
It can be turned off with:
echo 1 > /sys/class/backlight/backlight/bl_power
It can be turned on with:
echo 0 > /sys/class/backlight/backlight/bl_power
Needs CONFIG_BACKLIGHT_GPIO=m.
Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
---
arch/arm64/boot/dts/apple/t8103-j293.dts | 12 ++++++++++++
arch/arm64/boot/dts/apple/t8103-j313.dts | 12 ++++++++++++
2 files changed, 24 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 4f5f7d38e799..6f1050185a80 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -75,3 +75,15 @@ &i2c2 {
&i2c4 {
status = "okay";
};
+
+/ {
+ backlight: gpio-bl {
+ compatible = "gpio-backlight";
+ gpios = <&smc_gpio 18 GPIO_ACTIVE_HIGH>;
+ default-on;
+ };
+};
+
+&framebuffer0 {
+ backlight = <&backlight>;
+};
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index d6722d8809d1..3e4045c05905 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -67,3 +67,15 @@ &pcie0_dart_2 {
/delete-node/ &port01;
/delete-node/ &port02;
+
+/ {
+ backlight: gpio-bl {
+ compatible = "gpio-backlight";
+ gpios = <&smc_gpio 18 GPIO_ACTIVE_HIGH>;
+ default-on;
+ };
+};
+
+&framebuffer0 {
+ backlight = <&backlight>;
+};
--
2.34.1

View File

@ -0,0 +1,438 @@
From 3af244a2705f3894814a305428501a614c26fb7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:49:59 +0100
Subject: [PATCH 013/171] arm64: dts: apple: t8103*: Put in audio nodes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
arch/arm64/boot/dts/apple/t8103-j274.dts | 52 +++++++++++++++
arch/arm64/boot/dts/apple/t8103-j293.dts | 85 ++++++++++++++++++++++++
arch/arm64/boot/dts/apple/t8103-j313.dts | 61 +++++++++++++++++
arch/arm64/boot/dts/apple/t8103-j456.dts | 31 +++++++++
arch/arm64/boot/dts/apple/t8103-j457.dts | 40 +++++++++++
arch/arm64/boot/dts/apple/t8103.dtsi | 73 ++++++++++++++++++++
6 files changed, 342 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-j274.dts b/arch/arm64/boot/dts/apple/t8103-j274.dts
index aaa3019a4db2..811008bd73f3 100644
--- a/arch/arm64/boot/dts/apple/t8103-j274.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j274.dts
@@ -56,6 +56,58 @@ ethernet0: ethernet@0,0 {
};
};
+&i2c1 {
+ speaker_amp: codec@31 {
+ compatible = "ti,tas5770l", "ti,tas2770";
+ reg = <0x31>;
+ shutdown-gpios = <&pinctrl_ap 181 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ };
+};
+
&i2c2 {
status = "okay";
+
+ jack_codec: codec@48 {
+ compatible = "cirrus,cs42l83", "cirrus,cs42l42";
+ reg = <0x48>;
+ reset-gpios = <&pinctrl_nub 11 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <183 IRQ_TYPE_LEVEL_LOW>;
+ #sound-dai-cells = <0>;
+ cirrus,ts-inv = <1>;
+ sound-name-prefix = "Jack";
+ };
+};
+
+/ {
+ sound {
+ compatible = "apple,j274-macaudio", "apple,macaudio";
+ model = "Mac mini J274 integrated audio";
+
+ dai-link@0 {
+ link-name = "Speaker";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 0>;
+ };
+ codec {
+ sound-dai = <&speaker_amp>;
+ };
+ };
+
+ dai-link@1 {
+ link-name = "Headphone Jack";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 2>;
+ };
+ codec {
+ sound-dai = <&jack_codec>;
+ };
+ };
+
+ };
};
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 6f1050185a80..7eb98e6b947c 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -68,8 +68,54 @@ &pcie0_dart_2 {
/delete-node/ &port01;
/delete-node/ &port02;
+&i2c1 {
+ speaker_left_rear: codec@31 {
+ compatible = "ti,tas5770l", "ti,tas2770";
+ reg = <0x31>;
+ shutdown-gpios = <&pinctrl_ap 181 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Left Rear";
+ };
+
+ speaker_left_front: codec@32 {
+ compatible = "ti,tas5770l", "ti,tas2770";
+ reg = <0x32>;
+ shutdown-gpios = <&pinctrl_ap 181 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Left Front";
+ };
+};
+
&i2c2 {
status = "okay";
+
+ jack_codec: codec@48 {
+ compatible = "cirrus,cs42l83", "cirrus,cs42l42";
+ reg = <0x48>;
+ reset-gpios = <&pinctrl_nub 11 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <183 IRQ_TYPE_LEVEL_LOW>;
+ #sound-dai-cells = <0>;
+ cirrus,ts-inv = <1>;
+ };
+};
+
+&i2c3 {
+ speaker_right_rear: codec@34 {
+ compatible = "ti,tas5770l", "ti,tas2770";
+ reg = <0x34>;
+ shutdown-gpios = <&pinctrl_ap 181 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Right Rear";
+ };
+
+ speaker_right_front: codec@35 {
+ compatible = "ti,tas5770l", "ti,tas2770";
+ reg = <0x35>;
+ shutdown-gpios = <&pinctrl_ap 181 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Right Front";
+ };
};
&i2c4 {
@@ -82,6 +128,45 @@ backlight: gpio-bl {
gpios = <&smc_gpio 18 GPIO_ACTIVE_HIGH>;
default-on;
};
+
+ sound {
+ compatible = "apple,j293-macaudio", "apple,macaudio";
+ model = "MacBook Pro J293 integrated audio";
+
+ dai-link@0 {
+ /*
+ * DANGER ZONE: You can blow your speakers!
+ *
+ * The drivers are not ready, and unless you are careful
+ * to attenuate the audio stream, you run the risk of
+ * blowing your speakers.
+ */
+ status = "disabled";
+
+ link-name = "Speakers";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 0>, <&mca 1>;
+ };
+ codec {
+ sound-dai = <&speaker_left_front>, <&speaker_right_front>,
+ <&speaker_left_rear>, <&speaker_right_rear>;
+ };
+ };
+
+ dai-link@1 {
+ link-name = "Headphone Jack";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 2>;
+ };
+ codec {
+ sound-dai = <&jack_codec>;
+ };
+ };
+ };
};
&framebuffer0 {
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index 3e4045c05905..ad3a6edeb651 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -68,12 +68,73 @@ &pcie0_dart_2 {
/delete-node/ &port01;
/delete-node/ &port02;
+&i2c1 {
+ speaker_left: codec@31 {
+ compatible = "ti,tas5770l", "ti,tas2770";
+ reg = <0x31>;
+ shutdown-gpios = <&pinctrl_ap 181 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Left";
+
+ };
+};
+
+&i2c3 {
+ speaker_right: codec@34 {
+ compatible = "ti,tas5770l", "ti,tas2770";
+ reg = <0x34>;
+ shutdown-gpios = <&pinctrl_ap 181 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Right";
+ };
+
+ jack_codec: codec@48 {
+ compatible = "cirrus,cs42l83", "cirrus,cs42l42";
+ reg = <0x48>;
+ reset-gpios = <&pinctrl_nub 11 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <183 IRQ_TYPE_LEVEL_LOW>;
+ #sound-dai-cells = <0>;
+ cirrus,ts-inv = <1>;
+ sound-name-prefix = "Jack";
+ };
+};
+
/ {
backlight: gpio-bl {
compatible = "gpio-backlight";
gpios = <&smc_gpio 18 GPIO_ACTIVE_HIGH>;
default-on;
};
+
+ sound {
+ compatible = "apple,j313-macaudio", "apple,macaudio";
+ model = "MacBook Air J313 integrated audio";
+
+ dai-link@0 {
+ link-name = "Speakers";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 0>, <&mca 1>;
+ };
+ codec {
+ sound-dai = <&speaker_left>, <&speaker_right>;
+ };
+ };
+
+ dai-link@1 {
+ link-name = "Headphone Jack";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 2>;
+ };
+ codec {
+ sound-dai = <&jack_codec>;
+ };
+ };
+ };
};
&framebuffer0 {
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index 3d0a91ac29ae..e65053f3bd2c 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -73,3 +73,34 @@ ethernet0: ethernet@0,0 {
local-mac-address = [00 10 18 00 00 00];
};
};
+
+&i2c1 {
+ jack_codec: codec@48 {
+ compatible = "cirrus,cs42l83", "cirrus,cs42l42";
+ reg = <0x48>;
+ reset-gpios = <&pinctrl_nub 11 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <183 IRQ_TYPE_LEVEL_LOW>;
+ #sound-dai-cells = <0>;
+ cirrus,ts-inv = <1>;
+ };
+};
+
+/ {
+ sound {
+ compatible = "apple,j456-macaudio", "apple,macaudio";
+ model = "iMac J456 integrated audio";
+
+ dai-link@0 {
+ link-name = "Headphone Jack";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 2>;
+ };
+ codec {
+ sound-dai = <&jack_codec>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index 7e3a0e95e837..925fe4058055 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -61,3 +61,43 @@ &pcie0_dart_1 {
};
/delete-node/ &port01;
+
+&i2c1 {
+ jack_codec: codec@48 {
+ compatible = "cirrus,cs42l83", "cirrus,cs42l42";
+ reg = <0x48>;
+ reset-gpios = <&pinctrl_nub 11 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <183 IRQ_TYPE_LEVEL_LOW>;
+ #sound-dai-cells = <0>;
+ cirrus,ts-inv = <1>;
+ };
+};
+
+/ {
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "iMac integrated audio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,dai-link@0 {
+ bitclock-inversion;
+ frame-inversion;
+ reg = <0>;
+ format = "i2s";
+ mclk-fs = <64>;
+ tdm-slot-width = <32>;
+
+ link0_cpu: cpu {
+ sound-dai = <&mca 2>;
+ bitclock-master;
+ frame-master;
+ };
+
+ link0_codec: codec {
+ sound-dai = <&jack_codec>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index f96a732e6211..afb0688cb1c2 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -917,6 +917,79 @@ port02: pci@2,0 {
<0 0 0 4 &port02 0 0 0 3>;
};
};
+
+ dart_sio: iommu@235004000 {
+ compatible = "apple,t8103-dart", "apple,dart";
+ reg = <0x2 0x35004000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 635 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_sio_cpu>;
+ };
+
+ nco_inp: clock-ref {
+ compatible = "fixed-factor-clock";
+ clocks = <&clkref>;
+ #clock-cells = <0>;
+ clock-mult = <75>;
+ clock-div = <2>; // 24 MHz * (75/2) = 900 MHz
+ clock-output-names = "nco_inp";
+ };
+
+ nco: nco@23b044000 {
+ compatible = "apple,t8103-nco", "apple,nco";
+ reg = <0x2 0x3b044000 0x0 0x14000>;
+ clocks = <&nco_inp>;
+ #clock-cells = <1>;
+ apple,nchannels = <5>;
+ };
+
+ admac: dma-controller@238200000 {
+ compatible = "apple,t8103-admac", "apple,admac";
+ reg = <0x2 0x38200000 0x0 0x34000>;
+ dma-channels = <24>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 626 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ iommus = <&dart_sio 2>;
+ power-domains = <&ps_sio_adma>;
+ apple,internal-irq-destination = <1>;
+ };
+
+ mca: mca@38400000 {
+ compatible = "apple,t8103-mca", "apple,mca";
+ reg = <0x2 0x38400000 0x0 0x18000>,
+ <0x2 0x38300000 0x0 0x30000>;
+ reg-names = "clusters", "switch";
+
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 619 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 620 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 621 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 622 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 623 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 624 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&nco 0>, <&nco 1>, <&nco 2>,
+ <&nco 3>, <&nco 4>, <&nco 4>;
+ power-domains = <&ps_audio_p>, <&ps_mca0>, <&ps_mca1>,
+ <&ps_mca2>, <&ps_mca3>, <&ps_mca4>, <&ps_mca5>;
+ dmas = <&admac 0>, <&admac 1>, <&admac 2>, <&admac 3>,
+ <&admac 4>, <&admac 5>, <&admac 6>, <&admac 7>,
+ <&admac 8>, <&admac 9>, <&admac 10>, <&admac 11>,
+ <&admac 12>, <&admac 13>, <&admac 14>, <&admac 15>,
+ <&admac 16>, <&admac 17>, <&admac 18>, <&admac 19>,
+ <&admac 20>, <&admac 21>, <&admac 22>, <&admac 23>;
+ dma-names = "tx0a", "rx0a", "tx0b", "rx0b",
+ "tx1a", "rx1a", "tx1b", "rx1b",
+ "tx2a", "rx2a", "tx2b", "rx2b",
+ "tx3a", "rx3a", "tx3b", "rx3b",
+ "tx4a", "rx4a", "tx4b", "rx4b",
+ "tx5a", "rx5a", "tx5b", "rx5b";
+
+ #sound-dai-cells = <1>;
+ apple,nclusters = <6>;
+ };
};
};
--
2.34.1

View File

@ -0,0 +1,33 @@
From 461322f8b15d66dc8860c4f940c3f8f4f36bb3a3 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sat, 12 Mar 2022 21:00:22 +0900
Subject: [PATCH 014/171] arm64: dts: apple: t8103-j313: Also disable speakers
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-j313.dts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index ad3a6edeb651..d1f65e48699f 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -112,6 +112,15 @@ sound {
model = "MacBook Air J313 integrated audio";
dai-link@0 {
+ /*
+ * DANGER ZONE: You can blow your speakers!
+ *
+ * The drivers are not ready, and unless you are careful
+ * to attenuate the audio stream, you run the risk of
+ * blowing your speakers.
+ */
+ status = "disabled";
+
link-name = "Speakers";
mclk-fs = <64>;
--
2.34.1

View File

@ -0,0 +1,28 @@
From 79b1406346a1f0bdf8bd326a005e288511ebfaf6 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 17 Mar 2022 23:49:07 +0900
Subject: [PATCH 015/171] arm64: dts: apple: Keep PCIe power domain on
This causes flakiness if shut down; don't do it until we find out
what's going on.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-pmgr.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
index 926b1e54b64b..68ae594bf5e9 100644
--- a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
@@ -717,6 +717,7 @@ ps_apcie_gp: power-controller@3e8 {
#reset-cells = <0>;
label = "apcie_gp";
power-domains = <&ps_apcie>;
+ apple,always-on; /* Breaks things if shut down */
};
ps_ans2: power-controller@3f0 {
--
2.34.1

View File

@ -0,0 +1,250 @@
From ea9e6404ec5b3f1ce636e0ac67293528b87c8578 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Wed, 10 Nov 2021 19:08:25 +0900
Subject: [PATCH 017/171] arm64: dts: apple: Add J314 and J316 devicetrees
These are the 14-inch and 16-inch 2021 MacBooks, in both M1 Pro and M1
Max variants (t6000 and t6001).
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/Makefile | 4 +
arch/arm64/boot/dts/apple/t6000-j314s.dts | 18 +++
arch/arm64/boot/dts/apple/t6000-j316s.dts | 18 +++
arch/arm64/boot/dts/apple/t6001-j314c.dts | 18 +++
arch/arm64/boot/dts/apple/t6001-j316c.dts | 18 +++
.../arm64/boot/dts/apple/t600x-j314-j316.dtsi | 110 ++++++++++++++++++
6 files changed, 186 insertions(+)
create mode 100644 arch/arm64/boot/dts/apple/t6000-j314s.dts
create mode 100644 arch/arm64/boot/dts/apple/t6000-j316s.dts
create mode 100644 arch/arm64/boot/dts/apple/t6001-j314c.dts
create mode 100644 arch/arm64/boot/dts/apple/t6001-j316c.dts
create mode 100644 arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
diff --git a/arch/arm64/boot/dts/apple/Makefile b/arch/arm64/boot/dts/apple/Makefile
index c0510c25ca6a..b021931b0a17 100644
--- a/arch/arm64/boot/dts/apple/Makefile
+++ b/arch/arm64/boot/dts/apple/Makefile
@@ -4,3 +4,7 @@ dtb-$(CONFIG_ARCH_APPLE) += t8103-j293.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j313.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j456.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j457.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6000-j314s.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6001-j314c.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6000-j316s.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6001-j316c.dtb
diff --git a/arch/arm64/boot/dts/apple/t6000-j314s.dts b/arch/arm64/boot/dts/apple/t6000-j314s.dts
new file mode 100644
index 000000000000..c9e192848fe3
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6000-j314s.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (14-inch, M1 Pro, 2021)
+ *
+ * target-type: J314s
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6000.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j314s", "apple,t6000", "apple,arm-platform";
+ model = "Apple MacBook Pro (14-inch, M1 Pro, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6000-j316s.dts b/arch/arm64/boot/dts/apple/t6000-j316s.dts
new file mode 100644
index 000000000000..ff1803ce2300
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6000-j316s.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (16-inch, M1 Pro, 2021)
+ *
+ * target-type: J316s
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6000.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j316s", "apple,t6000", "apple,arm-platform";
+ model = "Apple MacBook Pro (16-inch, M1 Pro, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j314c.dts b/arch/arm64/boot/dts/apple/t6001-j314c.dts
new file mode 100644
index 000000000000..1761d15b98c1
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6001-j314c.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (14-inch, M1 Max, 2021)
+ *
+ * target-type: J314c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6001.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j314c", "apple,t6001", "apple,arm-platform";
+ model = "Apple MacBook Pro (14-inch, M1 Max, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j316c.dts b/arch/arm64/boot/dts/apple/t6001-j316c.dts
new file mode 100644
index 000000000000..750e9beeffc0
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6001-j316c.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (16-inch, M1 Max, 2021)
+ *
+ * target-type: J316c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6001.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j316c", "apple,t6001", "apple,arm-platform";
+ model = "Apple MacBook Pro (16-inch, M1 Max, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
new file mode 100644
index 000000000000..8079200aeb12
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (14/16-inch, 2021)
+ *
+ * This file contains the parts common to J314 and J316 devices with both t6000 and t6001.
+ *
+ * target-type: J314s / J314c / J316s / J316c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ wifi0 = &wifi0;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0";
+
+ framebuffer0: framebuffer@0 {
+ compatible = "apple,simple-framebuffer", "simple-framebuffer";
+ reg = <0 0 0 0>; /* To be filled by loader */
+ /* Format properties will be added by loader */
+ status = "disabled";
+ };
+ };
+
+ memory@10000000000 {
+ device_type = "memory";
+ reg = <0x100 0 0x2 0>; /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
+
+/* USB Type C */
+&i2c0 {
+ hpm0: usb-pd@38 {
+ compatible = "apple,cd321x";
+ reg = <0x38>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm1: usb-pd@3f {
+ compatible = "apple,cd321x";
+ reg = <0x3f>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm2: usb-pd@3b {
+ compatible = "apple,cd321x";
+ reg = <0x3b>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ /* MagSafe port */
+ hpm5: usb-pd@3a {
+ compatible = "apple,cd321x";
+ reg = <0x3a>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+};
+
+/* PCIe devices */
+&port00 {
+ /* WLAN */
+ bus-range = <1 1>;
+ wifi0: wifi@0,0 {
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 10];
+ };
+};
+
+&port01 {
+ /* SD card reader */
+ bus-range = <2 2>;
+ sdhci0: mmc@0,0 {
+ compatible = "pci17a0,9755";
+ reg = <0x20000 0x0 0x0 0x0 0x0>;
+ cd-inverted;
+ wp-inverted;
+ };
+};
+
+&pcie0_dart_2 {
+ status = "disabled";
+};
+
+&pcie0_dart_3 {
+ status = "disabled";
+};
+
+/delete-node/ &port02;
+/delete-node/ &port03;
--
2.34.1

View File

@ -0,0 +1,149 @@
From ab01e260000502f8e1f814e05fcbf35667cc1167 Mon Sep 17 00:00:00 2001
From: Janne Grunau <j@jannau.net>
Date: Tue, 3 May 2022 22:05:25 +0200
Subject: [PATCH 018/171] arm64: dts: apple: Add devicetree for Apple Mac
Studio M1 Max
Signed-off-by: Janne Grunau <j@jannau.net>
---
arch/arm64/boot/dts/apple/Makefile | 1 +
arch/arm64/boot/dts/apple/t6001-j375c.dts | 118 ++++++++++++++++++++++
2 files changed, 119 insertions(+)
create mode 100644 arch/arm64/boot/dts/apple/t6001-j375c.dts
diff --git a/arch/arm64/boot/dts/apple/Makefile b/arch/arm64/boot/dts/apple/Makefile
index b021931b0a17..b3ed42594ecd 100644
--- a/arch/arm64/boot/dts/apple/Makefile
+++ b/arch/arm64/boot/dts/apple/Makefile
@@ -8,3 +8,4 @@ dtb-$(CONFIG_ARCH_APPLE) += t6000-j314s.dtb
dtb-$(CONFIG_ARCH_APPLE) += t6001-j314c.dtb
dtb-$(CONFIG_ARCH_APPLE) += t6000-j316s.dtb
dtb-$(CONFIG_ARCH_APPLE) += t6001-j316c.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6001-j375c.dtb
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
new file mode 100644
index 000000000000..961104d6bd9a
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Mac Studio (M1 Max, 2022)
+ *
+ * target-type: J375c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6001.dtsi"
+
+/ {
+ compatible = "apple,j375c", "apple,t6001", "apple,arm-platform";
+ model = "Apple Mac Studio (M1 Max, 2022)";
+
+ aliases {
+ serial0 = &serial0;
+ wifi0 = &wifi0;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0";
+
+ framebuffer0: framebuffer@0 {
+ compatible = "apple,simple-framebuffer", "simple-framebuffer";
+ reg = <0 0 0 0>; /* To be filled by loader */
+ /* Format properties will be added by loader */
+ status = "disabled";
+ };
+ };
+
+ memory@10000000000 {
+ device_type = "memory";
+ reg = <0x100 0 0x2 0>; /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
+
+/* USB Type C */
+&i2c0 {
+ hpm0: usb-pd@38 {
+ compatible = "apple,cd321x";
+ reg = <0x38>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm1: usb-pd@3f {
+ compatible = "apple,cd321x";
+ reg = <0x3f>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm2: usb-pd@3b {
+ compatible = "apple,cd321x";
+ reg = <0x3b>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm3: usb-pd@3c {
+ compatible = "apple,cd321x";
+ reg = <0x3c>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+};
+
+/* PCIe devices */
+&port00 {
+ /* WLAN */
+ bus-range = <1 1>;
+ wifi0: wifi@0,0 {
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 10];
+ };
+};
+
+&port01 {
+ /* SD card reader */
+ bus-range = <2 2>;
+ sdhci0: mmc@0,0 {
+ compatible = "pci17a0,9755";
+ reg = <0x20000 0x0 0x0 0x0 0x0>;
+ cd-inverted;
+ wp-inverted;
+ };
+};
+
+&port02 {
+ /* 10 Gbit Ethernet */
+ bus-range = <3 3>;
+ ethernet0: ethernet@0,0 {
+ reg = <0x30000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 00];
+ };
+};
+
+&port03 {
+ /* USB xHCI */
+ bus-range = <4 4>;
+};
--
2.34.1

View File

@ -0,0 +1,178 @@
From 973a9df0042bad7ee5fa7534f4d74f6f5d44f1c8 Mon Sep 17 00:00:00 2001
From: Janne Grunau <j@jannau.net>
Date: Thu, 24 Mar 2022 17:04:24 +0100
Subject: [PATCH 019/171] arm64: dts: apple: Add devicetree for Apple Mac
Studio M1 Ultra
Signed-off-by: Janne Grunau <j@jannau.net>
---
arch/arm64/boot/dts/apple/Makefile | 1 +
arch/arm64/boot/dts/apple/t6002-j375d.dts | 147 ++++++++++++++++++++++
2 files changed, 148 insertions(+)
create mode 100644 arch/arm64/boot/dts/apple/t6002-j375d.dts
diff --git a/arch/arm64/boot/dts/apple/Makefile b/arch/arm64/boot/dts/apple/Makefile
index b3ed42594ecd..5a7506ff5ea3 100644
--- a/arch/arm64/boot/dts/apple/Makefile
+++ b/arch/arm64/boot/dts/apple/Makefile
@@ -9,3 +9,4 @@ dtb-$(CONFIG_ARCH_APPLE) += t6001-j314c.dtb
dtb-$(CONFIG_ARCH_APPLE) += t6000-j316s.dtb
dtb-$(CONFIG_ARCH_APPLE) += t6001-j316c.dtb
dtb-$(CONFIG_ARCH_APPLE) += t6001-j375c.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6002-j375d.dtb
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
new file mode 100644
index 000000000000..95e0c3243818
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Mac Studio (M1 Ultra, 2022)
+ *
+ * target-type: J375d
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6002.dtsi"
+
+/ {
+ compatible = "apple,j375d", "apple,t6002", "apple,arm-platform";
+ model = "Apple Mac Studio (M1 Ultra, 2022)";
+
+ aliases {
+ serial0 = &serial0;
+ wifi0 = &wifi0;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0";
+
+ framebuffer0: framebuffer@0 {
+ compatible = "apple,simple-framebuffer", "simple-framebuffer";
+ reg = <0 0 0 0>; /* To be filled by loader */
+ /* Format properties will be added by loader */
+ status = "disabled";
+ };
+ };
+
+ memory@10000000000 {
+ device_type = "memory";
+ reg = <0x100 0 0x2 0>; /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
+
+/* USB Type C */
+&i2c0 {
+ hpm0: usb-pd@38 {
+ compatible = "apple,cd321x";
+ reg = <0x38>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm1: usb-pd@3f {
+ compatible = "apple,cd321x";
+ reg = <0x3f>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm2: usb-pd@3b {
+ compatible = "apple,cd321x";
+ reg = <0x3b>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm3: usb-pd@3c {
+ compatible = "apple,cd321x";
+ reg = <0x3c>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ /* front-right */
+ hpm4: usb-pd@39 {
+ compatible = "apple,cd321x";
+ reg = <0x39>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ /* front-left */
+ hpm5: usb-pd@3a {
+ compatible = "apple,cd321x";
+ reg = <0x3a>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+};
+
+/* PCIe devices */
+&port00 {
+ /* WLAN */
+ bus-range = <1 1>;
+ wifi0: wifi@0,0 {
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 10];
+ };
+};
+
+&port01 {
+ /* SD card reader */
+ bus-range = <2 2>;
+ sdhci0: mmc@0,0 {
+ compatible = "pci17a0,9755";
+ reg = <0x20000 0x0 0x0 0x0 0x0>;
+ cd-inverted;
+ wp-inverted;
+ };
+};
+
+&port02 {
+ /* 10 Gbit Ethernet */
+ bus-range = <3 3>;
+ ethernet0: ethernet@0,0 {
+ reg = <0x30000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 00];
+ };
+};
+
+&port03 {
+ /* USB xHCI */
+ bus-range = <4 4>;
+};
+
+/* delete unused always-on power-domains on die 1 */
+
+/delete-node/ &ps_atc2_usb_aon_die1;
+/delete-node/ &ps_atc2_usb_die1;
+
+/delete-node/ &ps_atc3_usb_aon_die1;
+/delete-node/ &ps_atc3_usb_die1;
+
+/delete-node/ &ps_disp0_cpu0_die1;
+/delete-node/ &ps_disp0_fe_die1;
--
2.34.1

View File

@ -0,0 +1,486 @@
From 0bea0800d5e0e32323bbbe2b2edfe16e08116bc9 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 15 Feb 2022 21:34:10 +0900
Subject: [PATCH 020/171] arm64: dts: apple: Add CPUfreq nodes for t6001
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t6001.dtsi | 7 +
arch/arm64/boot/dts/apple/t6002.dtsi | 81 +++++++++
arch/arm64/boot/dts/apple/t600x-common.dtsi | 188 ++++++++++++++++++++
arch/arm64/boot/dts/apple/t600x-die0.dtsi | 4 +
4 files changed, 280 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6001.dtsi b/arch/arm64/boot/dts/apple/t6001.dtsi
index 620b17e4031f..832e9bedc1fb 100644
--- a/arch/arm64/boot/dts/apple/t6001.dtsi
+++ b/arch/arm64/boot/dts/apple/t6001.dtsi
@@ -47,6 +47,13 @@ soc {
#undef DIE_NO
+&cpufreq_hw {
+ reg = <0x2 0x10e20000 0 0x1000>,
+ <0x2 0x11e20000 0 0x1000>,
+ <0x2 0x12e20000 0 0x1000>;
+ reg-names = "cluster0", "cluster1", "cluster2";
+};
+
&aic {
affinities {
e-core-pmu-affinity {
diff --git a/arch/arm64/boot/dts/apple/t6002.dtsi b/arch/arm64/boot/dts/apple/t6002.dtsi
index 736f16aad70f..f3618df00518 100644
--- a/arch/arm64/boot/dts/apple/t6002.dtsi
+++ b/arch/arm64/boot/dts/apple/t6002.dtsi
@@ -23,12 +23,56 @@ / {
#size-cells = <2>;
cpus {
+ cpu-map {
+ cluster3 {
+ core0 {
+ cpu = <&cpu_e10>;
+ };
+ core1 {
+ cpu = <&cpu_e11>;
+ };
+ };
+
+ cluster4 {
+ core0 {
+ cpu = <&cpu_p20>;
+ };
+ core1 {
+ cpu = <&cpu_p21>;
+ };
+ core2 {
+ cpu = <&cpu_p22>;
+ };
+ core3 {
+ cpu = <&cpu_p23>;
+ };
+ };
+
+ cluster5 {
+ core0 {
+ cpu = <&cpu_p30>;
+ };
+ core1 {
+ cpu = <&cpu_p31>;
+ };
+ core2 {
+ cpu = <&cpu_p32>;
+ };
+ core3 {
+ cpu = <&cpu_p33>;
+ };
+ };
+ };
+
cpu_e10: cpu@800 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x800>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 3>;
};
cpu_e11: cpu@801 {
@@ -37,6 +81,9 @@ cpu_e11: cpu@801 {
reg = <0x0 0x801>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 3>;
};
cpu_p20: cpu@10900 {
@@ -45,6 +92,9 @@ cpu_p20: cpu@10900 {
reg = <0x0 0x10900>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 4>;
};
cpu_p21: cpu@10901 {
@@ -53,6 +103,9 @@ cpu_p21: cpu@10901 {
reg = <0x0 0x10901>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 4>;
};
cpu_p22: cpu@10902 {
@@ -61,6 +114,9 @@ cpu_p22: cpu@10902 {
reg = <0x0 0x10902>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 4>;
};
cpu_p23: cpu@10903 {
@@ -69,6 +125,9 @@ cpu_p23: cpu@10903 {
reg = <0x0 0x10903>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 4>;
};
cpu_p30: cpu@10a00 {
@@ -77,6 +136,9 @@ cpu_p30: cpu@10a00 {
reg = <0x0 0x10a00>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 5>;
};
cpu_p31: cpu@10a01 {
@@ -85,6 +147,9 @@ cpu_p31: cpu@10a01 {
reg = <0x0 0x10a01>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 5>;
};
cpu_p32: cpu@10a02 {
@@ -93,6 +158,9 @@ cpu_p32: cpu@10a02 {
reg = <0x0 0x10a02>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 5>;
};
cpu_p33: cpu@10a03 {
@@ -101,6 +169,9 @@ cpu_p33: cpu@10a03 {
reg = <0x0 0x10a03>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 5>;
};
};
@@ -162,6 +233,16 @@ die1 {
#undef DIE
#undef DIE_NO
+&cpufreq_hw {
+ reg = <0x2 0x10e20000 0 0x1000>,
+ <0x2 0x11e20000 0 0x1000>,
+ <0x2 0x12e20000 0 0x1000>,
+ <0x22 0x10e20000 0 0x1000>,
+ <0x22 0x11e20000 0 0x1000>,
+ <0x22 0x12e20000 0 0x1000>;
+ reg-names = "cluster0", "cluster1", "cluster2",
+ "cluster3", "cluster4", "cluster5";
+};
&aic {
affinities {
diff --git a/arch/arm64/boot/dts/apple/t600x-common.dtsi b/arch/arm64/boot/dts/apple/t600x-common.dtsi
index e29b88e2c853..06e160880407 100644
--- a/arch/arm64/boot/dts/apple/t600x-common.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-common.dtsi
@@ -15,12 +15,56 @@ cpus {
#address-cells = <2>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu_e00>;
+ };
+ core1 {
+ cpu = <&cpu_e01>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu_p00>;
+ };
+ core1 {
+ cpu = <&cpu_p01>;
+ };
+ core2 {
+ cpu = <&cpu_p02>;
+ };
+ core3 {
+ cpu = <&cpu_p03>;
+ };
+ };
+
+ cluster2 {
+ core0 {
+ cpu = <&cpu_p10>;
+ };
+ core1 {
+ cpu = <&cpu_p11>;
+ };
+ core2 {
+ cpu = <&cpu_p12>;
+ };
+ core3 {
+ cpu = <&cpu_p13>;
+ };
+ };
+ };
+
cpu_e00: cpu@0 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x0>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 0>;
};
cpu_e01: cpu@1 {
@@ -29,6 +73,9 @@ cpu_e01: cpu@1 {
reg = <0x0 0x1>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ apple,freq-domain = <&cpufreq_hw 0>;
};
cpu_p00: cpu@10100 {
@@ -37,6 +84,9 @@ cpu_p00: cpu@10100 {
reg = <0x0 0x10100>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
};
cpu_p01: cpu@10101 {
@@ -45,6 +95,9 @@ cpu_p01: cpu@10101 {
reg = <0x0 0x10101>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
};
cpu_p02: cpu@10102 {
@@ -53,6 +106,9 @@ cpu_p02: cpu@10102 {
reg = <0x0 0x10102>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
};
cpu_p03: cpu@10103 {
@@ -61,6 +117,9 @@ cpu_p03: cpu@10103 {
reg = <0x0 0x10103>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 1>;
};
cpu_p10: cpu@10200 {
@@ -69,6 +128,9 @@ cpu_p10: cpu@10200 {
reg = <0x0 0x10200>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 2>;
};
cpu_p11: cpu@10201 {
@@ -77,6 +139,9 @@ cpu_p11: cpu@10201 {
reg = <0x0 0x10201>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 2>;
};
cpu_p12: cpu@10202 {
@@ -85,6 +150,9 @@ cpu_p12: cpu@10202 {
reg = <0x0 0x10202>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 2>;
};
cpu_p13: cpu@10203 {
@@ -93,7 +161,127 @@ cpu_p13: cpu@10203 {
reg = <0x0 0x10203>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ apple,freq-domain = <&cpufreq_hw 2>;
+ };
+ };
+
+ icestorm_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <7500>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <972000000>;
+ opp-level = <2>;
+ clock-latency-ns = <23000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1332000000>;
+ opp-level = <3>;
+ clock-latency-ns = <29000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-level = <4>;
+ clock-latency-ns = <40000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <2064000000>;
+ opp-level = <5>;
+ clock-latency-ns = <50000>;
+ };
+ };
+
+ firestorm_opp: opp-table-1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <8000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <828000000>;
+ opp-level = <2>;
+ clock-latency-ns = <18000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-level = <3>;
+ clock-latency-ns = <19000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1296000000>;
+ opp-level = <4>;
+ clock-latency-ns = <23000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1524000000>;
+ opp-level = <5>;
+ clock-latency-ns = <24000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1752000000>;
+ opp-level = <6>;
+ clock-latency-ns = <28000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1980000000>;
+ opp-level = <7>;
+ clock-latency-ns = <31000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-level = <8>;
+ clock-latency-ns = <45000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <2448000000>;
+ opp-level = <9>;
+ clock-latency-ns = <49000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <2676000000>;
+ opp-level = <10>;
+ clock-latency-ns = <53000>;
+ };
+ opp11 {
+ opp-hz = /bits/ 64 <2904000000>;
+ opp-level = <11>;
+ clock-latency-ns = <56000>;
+ };
+ opp12 {
+ opp-hz = /bits/ 64 <3036000000>;
+ opp-level = <12>;
+ clock-latency-ns = <56000>;
+ };
+ /* Not available until CPU deep sleep is implemented
+ opp13 {
+ opp-hz = /bits/ 64 <3132000000>;
+ opp-level = <13>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+ opp14 {
+ opp-hz = /bits/ 64 <3168000000>;
+ opp-level = <14>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+ opp15 {
+ opp-hz = /bits/ 64 <3228000000>;
+ opp-level = <15>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
};
+ */
};
pmu-e {
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index 8131352e3ccd..129984bd9a8b 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -6,6 +6,10 @@
* Copyright The Asahi Linux Contributors
*/
+ cpufreq_hw: cpufreq@210e20000 {
+ compatible = "apple,t6000-soc-cpufreq", "apple,soc-cpufreq";
+ #freq-domain-cells = <1>;
+ };
aic: interrupt-controller@28e100000 {
compatible = "apple,t6000-aic", "apple,aic2";
--
2.34.1

View File

@ -0,0 +1,50 @@
From 7946dbabbfec3116b542268cbb3dcb6b4a5bd9c2 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Fri, 4 Feb 2022 12:59:39 +0900
Subject: [PATCH 021/171] arm64: dts: apple: Add SMC node to t600x devicetrees
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t600x-die0.dtsi | 26 +++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index 129984bd9a8b..6c9649d5a26c 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -21,6 +21,32 @@ aic: interrupt-controller@28e100000 {
power-domains = <&ps_aic>;
};
+ smc_mbox: mbox@290408000 {
+ compatible = "apple,t6000-asc-mailbox", "apple,asc-mailbox-v4";
+ reg = <0x2 0x90408000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 754 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 755 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 756 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 757 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "send-empty", "send-not-empty",
+ "recv-empty", "recv-not-empty";
+ #mbox-cells = <0>;
+ };
+
+ smc: smc@290400000 {
+ compatible = "apple,t6000-smc", "apple,smc";
+ reg = <0x2 0x90400000 0x0 0x4000>,
+ <0x2 0x91e00000 0x0 0x100000>;
+ reg-names = "smc", "sram";
+ mboxes = <&smc_mbox>;
+
+ smc_gpio: gpio {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
pinctrl_smc: pinctrl@290820000 {
compatible = "apple,t6000-pinctrl", "apple,pinctrl";
reg = <0x2 0x90820000 0x0 0x4000>;
--
2.34.1

View File

@ -0,0 +1,145 @@
From d2759ec3852ae04e5a6a87d78dd5a52e67e36bbf Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 15 Feb 2022 18:54:35 +0900
Subject: [PATCH 022/171] arm64: dts: apple: Add PMU NVMEM and SMC RTC/reboot
nodes
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t6001.dtsi | 1 +
arch/arm64/boot/dts/apple/t6002.dtsi | 1 +
arch/arm64/boot/dts/apple/t600x-die0.dtsi | 87 +++++++++++++++++++++++
3 files changed, 89 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6001.dtsi b/arch/arm64/boot/dts/apple/t6001.dtsi
index 832e9bedc1fb..6b50a9fa68e7 100644
--- a/arch/arm64/boot/dts/apple/t6001.dtsi
+++ b/arch/arm64/boot/dts/apple/t6001.dtsi
@@ -11,6 +11,7 @@
#include <dt-bindings/interrupt-controller/apple-aic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pinctrl/apple.h>
+#include <dt-bindings/spmi/spmi.h>
#include "multi-die-cpp.h"
diff --git a/arch/arm64/boot/dts/apple/t6002.dtsi b/arch/arm64/boot/dts/apple/t6002.dtsi
index f3618df00518..31e2de7fb2ea 100644
--- a/arch/arm64/boot/dts/apple/t6002.dtsi
+++ b/arch/arm64/boot/dts/apple/t6002.dtsi
@@ -11,6 +11,7 @@
#include <dt-bindings/interrupt-controller/apple-aic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pinctrl/apple.h>
+#include <dt-bindings/spmi/spmi.h>
#include "multi-die-cpp.h"
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index 6c9649d5a26c..928da6734371 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -45,6 +45,18 @@ smc_gpio: gpio {
gpio-controller;
#gpio-cells = <2>;
};
+
+ smc_rtc: rtc {
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "rtc_offset";
+ };
+
+ smc_reboot: reboot {
+ nvmem-cells = <&shutdown_flag>, <&boot_stage>,
+ <&boot_error_count>, <&panic_count>, <&pm_setting>;
+ nvmem-cell-names = "shutdown_flag", "boot_stage",
+ "boot_error_count", "panic_count", "pm_setting";
+ };
};
pinctrl_smc: pinctrl@290820000 {
@@ -76,6 +88,81 @@ wdt: watchdog@2922b0000 {
interrupts = <AIC_IRQ 0 631 IRQ_TYPE_LEVEL_HIGH>;
};
+ nub_spmi0: spmi@2920a1300 {
+ compatible = "apple,t6000-spmi", "apple,spmi";
+ reg = <0x2 0x920a1300 0x0 0x100>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ pmu1: pmu@f {
+ compatible = "apple,maverick-pmu", "apple,spmi-pmu";
+ reg = <0xf SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ rtc_nvmem@1400 {
+ compatible = "apple,spmi-pmu-nvmem";
+ reg = <0x1400 0x20>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm_setting: pm-setting@5 {
+ reg = <0x5 0x1>;
+ };
+
+ rtc_offset: rtc-offset@11 {
+ reg = <0x11 0x6>;
+ };
+ };
+
+ legacy_nvmem@6000 {
+ compatible = "apple,spmi-pmu-nvmem";
+ reg = <0x6000 0x20>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot_stage: boot-stage@1 {
+ reg = <0x1 0x1>;
+ };
+
+ boot_error_count: boot-error-count@2 {
+ reg = <0x2 0x1>;
+ bits = <0 4>;
+ };
+
+ panic_count: panic-count@2 {
+ reg = <0x2 0x1>;
+ bits = <4 4>;
+ };
+
+ boot_error_stage: boot-error-stage@3 {
+ reg = <0x3 0x1>;
+ };
+
+ shutdown_flag: shutdown-flag@f {
+ reg = <0xf 0x1>;
+ bits = <3 1>;
+ };
+ };
+
+ scrpad_nvmem@8000 {
+ compatible = "apple,spmi-pmu-nvmem";
+ reg = <0x8000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ fault_shadow: fault-shadow@67b {
+ reg = <0x67b 0x10>;
+ };
+
+ socd: socd@b00 {
+ reg = <0xb00 0x400>;
+ };
+ };
+
+ };
+ };
+
i2c0: i2c@39b040000 {
compatible = "apple,t6000-i2c", "apple,i2c";
reg = <0x3 0x9b040000 0x0 0x4000>;
--
2.34.1

View File

@ -0,0 +1,74 @@
From b04e8cf77375704a101a7bcaa485973702cbbc92 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 9 Dec 2021 21:58:10 +0900
Subject: [PATCH 023/171] arm64: dts: apple: t6000: Add spi1 node
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t600x-common.dtsi | 7 +++++++
arch/arm64/boot/dts/apple/t600x-die0.dtsi | 14 ++++++++++++++
arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi | 7 +++++++
3 files changed, 28 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-common.dtsi b/arch/arm64/boot/dts/apple/t600x-common.dtsi
index 06e160880407..c5ee0c2da778 100644
--- a/arch/arm64/boot/dts/apple/t600x-common.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-common.dtsi
@@ -313,4 +313,11 @@ clkref: clock-ref {
clock-output-names = "clkref";
};
+ clk_200m: clock-200m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <200000000>;
+ clock-output-names = "clk_200m";
+ };
+
};
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index 928da6734371..96f8c2189f03 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -246,6 +246,20 @@ i2c5: i2c@39b054000 {
status = "disabled";
};
+ spi1: spi@39b104000 {
+ compatible = "apple,t6000-spi", "apple,spi";
+ reg = <0x3 0x9b104000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1107 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clk_200m>;
+ pinctrl-0 = <&spi1_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_spi1>;
+ status = "disabled";
+ };
+
serial0: serial@39b200000 {
compatible = "apple,s5l-uart";
reg = <0x3 0x9b200000 0x0 0x1000>;
diff --git a/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi b/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
index b31f1a7a2b3f..855dcf30a502 100644
--- a/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
@@ -36,6 +36,13 @@ i2c5_pins: i2c5-pins {
<APPLE_PINMUX(101, 1)>;
};
+ spi1_pins: spi1-pins {
+ pinmux = <APPLE_PINMUX(10, 1)>,
+ <APPLE_PINMUX(11, 1)>,
+ <APPLE_PINMUX(32, 1)>,
+ <APPLE_PINMUX(33, 1)>;
+ };
+
pcie_pins: pcie-pins {
pinmux = <APPLE_PINMUX(0, 1)>,
<APPLE_PINMUX(1, 1)>,
--
2.34.1

View File

@ -0,0 +1,37 @@
From e2a083f709ff6669836587d592b313d7349d0525 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 9 Dec 2021 21:58:29 +0900
Subject: [PATCH 024/171] arm64: dts: apple: t600x-j314-j316: Add NOR flash
node
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index 8079200aeb12..55457892c38e 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -76,6 +76,18 @@ hpm5: usb-pd@3a {
};
};
+&spi1 {
+ status = "disabled";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <25000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
/* PCIe devices */
&port00 {
/* WLAN */
--
2.34.1

View File

@ -0,0 +1,60 @@
From 2beaa67dcf1275232f6f52f104d321818289c159 Mon Sep 17 00:00:00 2001
From: Janne Grunau <j@jannau.net>
Date: Thu, 11 Nov 2021 21:31:21 +0100
Subject: [PATCH 025/171] arm64: dts: apple: t600x: Add spi3 node
Used for keyboard and touchpad input on MacBook Pro (14/16-inch,
M1 Pro/Max, 2021).
Signed-off-by: Janne Grunau <j@jannau.net>
---
arch/arm64/boot/dts/apple/t600x-die0.dtsi | 14 ++++++++++++++
arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi | 7 +++++++
2 files changed, 21 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index 96f8c2189f03..b549059a3320 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -260,6 +260,20 @@ spi1: spi@39b104000 {
status = "disabled";
};
+ spi3: spi@39b10c000 {
+ compatible = "apple,t6000-spi", "apple,spi";
+ reg = <0x3 0x9b10c000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1109 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkref>;
+ pinctrl-0 = <&spi3_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_spi3>;
+ status = "disabled";
+ };
+
serial0: serial@39b200000 {
compatible = "apple,s5l-uart";
reg = <0x3 0x9b200000 0x0 0x1000>;
diff --git a/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi b/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
index 855dcf30a502..1a994c3c1b79 100644
--- a/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
@@ -43,6 +43,13 @@ spi1_pins: spi1-pins {
<APPLE_PINMUX(33, 1)>;
};
+ spi3_pins: spi3-pins {
+ pinmux = <APPLE_PINMUX(52, 1)>,
+ <APPLE_PINMUX(53, 1)>,
+ <APPLE_PINMUX(54, 1)>,
+ <APPLE_PINMUX(55, 1)>;
+ };
+
pcie_pins: pcie-pins {
pinmux = <APPLE_PINMUX(0, 1)>,
<APPLE_PINMUX(1, 1)>,
--
2.34.1

View File

@ -0,0 +1,47 @@
From aec68ba09ead15a0b2b0fc47809146e2fa28ccf5 Mon Sep 17 00:00:00 2001
From: Janne Grunau <j@jannau.net>
Date: Thu, 11 Nov 2021 21:31:21 +0100
Subject: [PATCH 026/171] arm64: dts: apple: j31[46]: Add keyboard nodes
Enables keyboard and touchpad input on MacBook Pro (14/16-inch,
M1 Pro/Max, 2021).
Signed-off-by: Janne Grunau <j@jannau.net>
---
.../arm64/boot/dts/apple/t600x-j314-j316.dtsi | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index 55457892c38e..64280ed76feb 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -88,6 +88,26 @@ flash@0 {
};
};
+&spi3 {
+ status = "okay";
+
+ hid-transport@0 {
+ compatible = "apple,spi-hid-transport";
+ reg = <0>;
+ spi-max-frequency = <8000000>;
+ /*
+ * cs-setup and cs-hold delays are derived from Apple's ADT
+ * Mac OS driver meta data secify 45 us for 'cs to clock' and
+ * 'clock to cs' delays.
+ */
+ spi-cs-setup-delay-ns = <20000>;
+ spi-cs-hold-delay-ns = <20000>;
+ spi-cs-inactive-delay-ns = <250000>;
+ spien-gpios = <&pinctrl_ap 194 0>;
+ interrupts-extended = <&pinctrl_nub 6 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
/* PCIe devices */
&port00 {
/* WLAN */
--
2.34.1

View File

@ -0,0 +1,631 @@
From e000de0d79a99fe707b8c86b8ae4f19b6e6cc78e Mon Sep 17 00:00:00 2001
From: Janne Grunau <j@jannau.net>
Date: Tue, 17 May 2022 23:54:26 +0200
Subject: [PATCH 027/171] arm64: dts: apple: t600x: Add dwc3 nodes
Signed-off-by: Janne Grunau <j@jannau.net>
---
arch/arm64/boot/dts/apple/t6001-j375c.dts | 105 +++++++++++
arch/arm64/boot/dts/apple/t6002-j375d.dts | 168 ++++++++++++++++++
arch/arm64/boot/dts/apple/t600x-dieX.dtsi | 124 +++++++++++++
.../arm64/boot/dts/apple/t600x-j314-j316.dtsi | 92 ++++++++++
4 files changed, 489 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
index 961104d6bd9a..7ab07808a5e9 100644
--- a/arch/arm64/boot/dts/apple/t6001-j375c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -53,6 +53,24 @@ hpm0: usb-pd@38 {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec0: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Left";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec0_con_hs: endpoint {
+ remote-endpoint = <&typec0_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm1: usb-pd@3f {
@@ -61,6 +79,24 @@ hpm1: usb-pd@3f {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec1: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Left Middle";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec1_con_hs: endpoint {
+ remote-endpoint = <&typec1_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm2: usb-pd@3b {
@@ -69,6 +105,24 @@ hpm2: usb-pd@3b {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec2: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Right Middle";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec2_con_hs: endpoint {
+ remote-endpoint = <&typec2_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm3: usb-pd@3c {
@@ -77,6 +131,24 @@ hpm3: usb-pd@3c {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec3: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Right";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec3_con_hs: endpoint {
+ remote-endpoint = <&typec3_usb_hs>;
+ };
+ };
+ };
+ };
};
};
@@ -116,3 +188,36 @@ &port03 {
/* USB xHCI */
bus-range = <4 4>;
};
+
+/* USB controllers */
+&dwc3_0 {
+ port {
+ typec0_usb_hs: endpoint {
+ remote-endpoint = <&typec0_con_hs>;
+ };
+ };
+};
+
+&dwc3_1 {
+ port {
+ typec1_usb_hs: endpoint {
+ remote-endpoint = <&typec1_con_hs>;
+ };
+ };
+};
+
+&dwc3_2 {
+ port {
+ typec2_usb_hs: endpoint {
+ remote-endpoint = <&typec2_con_hs>;
+ };
+ };
+};
+
+&dwc3_3 {
+ port {
+ typec3_usb_hs: endpoint {
+ remote-endpoint = <&typec3_con_hs>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
index 95e0c3243818..ed88e1eaf7bb 100644
--- a/arch/arm64/boot/dts/apple/t6002-j375d.dts
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -53,6 +53,24 @@ hpm0: usb-pd@38 {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec0: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Left";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec0_con_hs: endpoint {
+ remote-endpoint = <&typec0_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm1: usb-pd@3f {
@@ -61,6 +79,24 @@ hpm1: usb-pd@3f {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec1: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Left Middle";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec1_con_hs: endpoint {
+ remote-endpoint = <&typec1_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm2: usb-pd@3b {
@@ -69,6 +105,24 @@ hpm2: usb-pd@3b {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec2: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Right Middle";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec2_con_hs: endpoint {
+ remote-endpoint = <&typec2_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm3: usb-pd@3c {
@@ -77,6 +131,24 @@ hpm3: usb-pd@3c {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec3: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Back Right";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec3_con_hs: endpoint {
+ remote-endpoint = <&typec3_usb_hs>;
+ };
+ };
+ };
+ };
};
/* front-right */
@@ -86,6 +158,24 @@ hpm4: usb-pd@39 {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec4: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Front Right";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec4_con_hs: endpoint {
+ remote-endpoint = <&typec4_usb_hs>;
+ };
+ };
+ };
+ };
};
/* front-left */
@@ -95,6 +185,24 @@ hpm5: usb-pd@3a {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec5: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Front Left";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec5_con_hs: endpoint {
+ remote-endpoint = <&typec5_usb_hs>;
+ };
+ };
+ };
+ };
};
};
@@ -135,6 +243,66 @@ &port03 {
bus-range = <4 4>;
};
+/* USB controllers */
+&dwc3_0 {
+ port {
+ typec0_usb_hs: endpoint {
+ remote-endpoint = <&typec0_con_hs>;
+ };
+ };
+};
+
+&dwc3_1 {
+ port {
+ typec1_usb_hs: endpoint {
+ remote-endpoint = <&typec1_con_hs>;
+ };
+ };
+};
+
+&dwc3_2 {
+ port {
+ typec2_usb_hs: endpoint {
+ remote-endpoint = <&typec2_con_hs>;
+ };
+ };
+};
+
+&dwc3_3 {
+ port {
+ typec3_usb_hs: endpoint {
+ remote-endpoint = <&typec3_con_hs>;
+ };
+ };
+};
+
+&dwc3_0_die1 {
+ port {
+ typec4_usb_hs: endpoint {
+ remote-endpoint = <&typec4_con_hs>;
+ };
+ };
+};
+
+&dwc3_1_die1 {
+ port {
+ typec5_usb_hs: endpoint {
+ remote-endpoint = <&typec5_con_hs>;
+ };
+ };
+};
+
+/* delete unused USB nodes on die 1 */
+
+/delete-node/ &dwc3_2_dart_0_die1;
+/delete-node/ &dwc3_2_dart_1_die1;
+/delete-node/ &dwc3_2_die1;
+
+/delete-node/ &dwc3_3_dart_0_die1;
+/delete-node/ &dwc3_3_dart_1_die1;
+/delete-node/ &dwc3_3_die1;
+
+
/* delete unused always-on power-domains on die 1 */
/delete-node/ &ps_atc2_usb_aon_die1;
diff --git a/arch/arm64/boot/dts/apple/t600x-dieX.dtsi b/arch/arm64/boot/dts/apple/t600x-dieX.dtsi
index 0a437b68e86c..6ada6c7f50fa 100644
--- a/arch/arm64/boot/dts/apple/t600x-dieX.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-dieX.dtsi
@@ -101,3 +101,127 @@ DIE_NODE(pinctrl_ap): pinctrl@39b028000 {
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ DIE_NODE(dwc3_0_dart_0): iommu@702f00000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x7 0x02f00000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1194 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc0_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_0_dart_1): iommu@702f80000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x7 0x02f80000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1194 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc0_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_0): usb@702280000 {
+ compatible = "apple,t6000-dwc3", "apple,dwc3", "snps,dwc3";
+ reg = <0x7 0x02280000 0x0 0x100000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1190 IRQ_TYPE_LEVEL_HIGH>;
+ /* dr_mode = "otg"; */
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ iommus = <&DIE_NODE(dwc3_0_dart_0) 0>,
+ <&DIE_NODE(dwc3_0_dart_1) 1>;
+ power-domains = <&DIE_NODE(ps_atc0_usb)>;
+ };
+
+ DIE_NODE(dwc3_1_dart_0): iommu@b02f00000 {
+ compatible = "apple,t6000-dart";
+ reg = <0xb 0x02f00000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1211 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc1_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_1_dart_1): iommu@b02f80000 {
+ compatible = "apple,t6000-dart";
+ reg = <0xb 0x02f80000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1211 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc1_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_1): usb@b02280000 {
+ compatible = "apple,t6000-dwc3", "apple,dwc3", "snps,dwc3";
+ reg = <0xb 0x02280000 0x0 0x100000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1207 IRQ_TYPE_LEVEL_HIGH>;
+ /* dr_mode = "otg"; */
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ iommus = <&DIE_NODE(dwc3_1_dart_0) 0>,
+ <&DIE_NODE(dwc3_1_dart_1) 1>;
+ power-domains = <&DIE_NODE(ps_atc1_usb)>;
+ };
+
+ DIE_NODE(dwc3_2_dart_0): iommu@f02f00000 {
+ compatible = "apple,t6000-dart";
+ reg = <0xf 0x02f00000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1228 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc2_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_2_dart_1): iommu@f02f80000 {
+ compatible = "apple,t6000-dart";
+ reg = <0xf 0x02f80000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1228 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc2_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_2): usb@f02280000 {
+ compatible = "apple,t6000-dwc3", "apple,dwc3", "snps,dwc3";
+ reg = <0xf 0x02280000 0x0 0x100000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1224 IRQ_TYPE_LEVEL_HIGH>;
+ /* dr_mode = "otg"; */
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ iommus = <&DIE_NODE(dwc3_2_dart_0) 0>,
+ <&DIE_NODE(dwc3_2_dart_1) 1>;
+ power-domains = <&DIE_NODE(ps_atc2_usb)>;
+ };
+
+ DIE_NODE(dwc3_3_dart_0): iommu@1302f00000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x13 0x02f00000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1245 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc3_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_3_dart_1): iommu@1302f80000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x13 0x02f80000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1245 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&DIE_NODE(ps_atc3_usb)>;
+ #iommu-cells = <1>;
+ };
+
+ DIE_NODE(dwc3_3): usb@1302280000 {
+ compatible = "apple,t6000-dwc3", "apple,dwc3", "snps,dwc3";
+ reg = <0x13 0x02280000 0x0 0x100000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1241 IRQ_TYPE_LEVEL_HIGH>;
+ /* dr_mode = "otg"; */
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ iommus = <&DIE_NODE(dwc3_3_dart_0) 0>,
+ <&DIE_NODE(dwc3_3_dart_1) 1>;
+ power-domains = <&DIE_NODE(ps_atc3_usb)>;
+ };
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index 64280ed76feb..1582a4caccdb 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -48,6 +48,24 @@ hpm0: usb-pd@38 {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec0: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Left Rear";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec0_con_hs: endpoint {
+ remote-endpoint = <&typec0_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm1: usb-pd@3f {
@@ -56,6 +74,24 @@ hpm1: usb-pd@3f {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec1: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Left Front";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec1_con_hs: endpoint {
+ remote-endpoint = <&typec1_usb_hs>;
+ };
+ };
+ };
+ };
};
hpm2: usb-pd@3b {
@@ -64,6 +100,24 @@ hpm2: usb-pd@3b {
interrupt-parent = <&pinctrl_ap>;
interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
+
+ typec2: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C Right";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ typec2_con_hs: endpoint {
+ remote-endpoint = <&typec2_usb_hs>;
+ };
+ };
+ };
+ };
};
/* MagSafe port */
@@ -140,3 +194,41 @@ &pcie0_dart_3 {
/delete-node/ &port02;
/delete-node/ &port03;
+
+/* USB controllers */
+&dwc3_0 {
+ port {
+ typec0_usb_hs: endpoint {
+ remote-endpoint = <&typec0_con_hs>;
+ };
+ };
+};
+
+&dwc3_1 {
+ port {
+ typec1_usb_hs: endpoint {
+ remote-endpoint = <&typec1_con_hs>;
+ };
+ };
+};
+
+&dwc3_2 {
+ port {
+ typec2_usb_hs: endpoint {
+ remote-endpoint = <&typec2_con_hs>;
+ };
+ };
+};
+
+/* ATC3 is used for DisplayPort -> HDMI only */
+&dwc3_3_dart_0 {
+ status = "disabled";
+};
+
+&dwc3_3_dart_1 {
+ status = "disabled";
+};
+
+&dwc3_3 {
+ status = "disabled";
+};
--
2.34.1

View File

@ -0,0 +1,141 @@
From 114701eecdf46c638d373e6cd3c7af3a6f61dbfe Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:07:17 +0900
Subject: [PATCH 028/171] arm64: dts: apple: Add WiFi module and antenna
properties
Add the new module-instance/antenna-sku properties required to select
WiFi firmwares properly to all board device trees.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t6000-j314s.dts | 4 ++++
arch/arm64/boot/dts/apple/t6000-j316s.dts | 4 ++++
arch/arm64/boot/dts/apple/t6001-j314c.dts | 4 ++++
arch/arm64/boot/dts/apple/t6001-j316c.dts | 4 ++++
arch/arm64/boot/dts/apple/t6001-j375c.dts | 6 ++++++
arch/arm64/boot/dts/apple/t6002-j375d.dts | 6 ++++++
arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi | 2 ++
7 files changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6000-j314s.dts b/arch/arm64/boot/dts/apple/t6000-j314s.dts
index c9e192848fe3..ac35870ca129 100644
--- a/arch/arm64/boot/dts/apple/t6000-j314s.dts
+++ b/arch/arm64/boot/dts/apple/t6000-j314s.dts
@@ -16,3 +16,7 @@ / {
compatible = "apple,j314s", "apple,t6000", "apple,arm-platform";
model = "Apple MacBook Pro (14-inch, M1 Pro, 2021)";
};
+
+&wifi0 {
+ brcm,board-type = "apple,maldives";
+};
diff --git a/arch/arm64/boot/dts/apple/t6000-j316s.dts b/arch/arm64/boot/dts/apple/t6000-j316s.dts
index ff1803ce2300..77d6d8c14d74 100644
--- a/arch/arm64/boot/dts/apple/t6000-j316s.dts
+++ b/arch/arm64/boot/dts/apple/t6000-j316s.dts
@@ -16,3 +16,7 @@ / {
compatible = "apple,j316s", "apple,t6000", "apple,arm-platform";
model = "Apple MacBook Pro (16-inch, M1 Pro, 2021)";
};
+
+&wifi0 {
+ brcm,board-type = "apple,madagascar";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j314c.dts b/arch/arm64/boot/dts/apple/t6001-j314c.dts
index 1761d15b98c1..0a5655792a8f 100644
--- a/arch/arm64/boot/dts/apple/t6001-j314c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j314c.dts
@@ -16,3 +16,7 @@ / {
compatible = "apple,j314c", "apple,t6001", "apple,arm-platform";
model = "Apple MacBook Pro (14-inch, M1 Max, 2021)";
};
+
+&wifi0 {
+ brcm,board-type = "apple,maldives";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j316c.dts b/arch/arm64/boot/dts/apple/t6001-j316c.dts
index 750e9beeffc0..9c215531ea54 100644
--- a/arch/arm64/boot/dts/apple/t6001-j316c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j316c.dts
@@ -16,3 +16,7 @@ / {
compatible = "apple,j316c", "apple,t6001", "apple,arm-platform";
model = "Apple MacBook Pro (16-inch, M1 Max, 2021)";
};
+
+&wifi0 {
+ brcm,board-type = "apple,madagascar";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
index 7ab07808a5e9..15d26674a310 100644
--- a/arch/arm64/boot/dts/apple/t6001-j375c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -157,9 +157,11 @@ &port00 {
/* WLAN */
bus-range = <1 1>;
wifi0: wifi@0,0 {
+ compatible = "pci14e4,4433";
reg = <0x10000 0x0 0x0 0x0 0x0>;
/* To be filled by the loader */
local-mac-address = [00 10 18 00 00 10];
+ apple,antenna-sku = "XX";
};
};
@@ -189,6 +191,10 @@ &port03 {
bus-range = <4 4>;
};
+&wifi0 {
+ brcm,board-type = "apple,okinawa";
+};
+
/* USB controllers */
&dwc3_0 {
port {
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
index ed88e1eaf7bb..4b84652e0334 100644
--- a/arch/arm64/boot/dts/apple/t6002-j375d.dts
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -211,9 +211,11 @@ &port00 {
/* WLAN */
bus-range = <1 1>;
wifi0: wifi@0,0 {
+ compatible = "pci14e4,4433";
reg = <0x10000 0x0 0x0 0x0 0x0>;
/* To be filled by the loader */
local-mac-address = [00 10 18 00 00 10];
+ apple,antenna-sku = "XX";
};
};
@@ -243,6 +245,10 @@ &port03 {
bus-range = <4 4>;
};
+&wifi0 {
+ brcm,board-type = "apple,okinawa";
+};
+
/* USB controllers */
&dwc3_0 {
port {
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index 1582a4caccdb..0296506c043b 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -167,9 +167,11 @@ &port00 {
/* WLAN */
bus-range = <1 1>;
wifi0: wifi@0,0 {
+ compatible = "pci14e4,4433";
reg = <0x10000 0x0 0x0 0x0 0x0>;
/* To be filled by the loader */
local-mac-address = [00 10 18 00 00 10];
+ apple,antenna-sku = "XX";
};
};
--
2.34.1

View File

@ -0,0 +1,97 @@
From e1a42fe74f4db0536b104053abc6e28097803873 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 6 Feb 2022 21:22:29 +0900
Subject: [PATCH 029/171] arm64: dts: apple: Add PCI power enable GPIOs
t8103:
- WLAN (SMC PMU GPIO #13)
t600x:
- WLAN (SMC PMU GPIO #13)
- SD (SMC PMU GPIO #26)
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t6001-j375c.dts | 3 +++
arch/arm64/boot/dts/apple/t6002-j375d.dts | 3 +++
arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi | 2 ++
3 files changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
index 15d26674a310..561a9a4c2bc1 100644
--- a/arch/arm64/boot/dts/apple/t6001-j375c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -156,6 +156,7 @@ typec3_con_hs: endpoint {
&port00 {
/* WLAN */
bus-range = <1 1>;
+ pwren-gpios = <&smc_gpio 13 GPIO_ACTIVE_HIGH>;
wifi0: wifi@0,0 {
compatible = "pci14e4,4433";
reg = <0x10000 0x0 0x0 0x0 0x0>;
@@ -168,6 +169,7 @@ wifi0: wifi@0,0 {
&port01 {
/* SD card reader */
bus-range = <2 2>;
+ pwren-gpios = <&smc_gpio 26 GPIO_ACTIVE_HIGH>;
sdhci0: mmc@0,0 {
compatible = "pci17a0,9755";
reg = <0x20000 0x0 0x0 0x0 0x0>;
@@ -189,6 +191,7 @@ ethernet0: ethernet@0,0 {
&port03 {
/* USB xHCI */
bus-range = <4 4>;
+ pwren-gpios = <&smc_gpio 20 GPIO_ACTIVE_HIGH>;
};
&wifi0 {
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
index 4b84652e0334..72070e9a3277 100644
--- a/arch/arm64/boot/dts/apple/t6002-j375d.dts
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -210,6 +210,7 @@ typec5_con_hs: endpoint {
&port00 {
/* WLAN */
bus-range = <1 1>;
+ pwren-gpios = <&smc_gpio 13 GPIO_ACTIVE_HIGH>;
wifi0: wifi@0,0 {
compatible = "pci14e4,4433";
reg = <0x10000 0x0 0x0 0x0 0x0>;
@@ -222,6 +223,7 @@ wifi0: wifi@0,0 {
&port01 {
/* SD card reader */
bus-range = <2 2>;
+ pwren-gpios = <&smc_gpio 26 GPIO_ACTIVE_HIGH>;
sdhci0: mmc@0,0 {
compatible = "pci17a0,9755";
reg = <0x20000 0x0 0x0 0x0 0x0>;
@@ -243,6 +245,7 @@ ethernet0: ethernet@0,0 {
&port03 {
/* USB xHCI */
bus-range = <4 4>;
+ pwren-gpios = <&smc_gpio 20 GPIO_ACTIVE_HIGH>;
};
&wifi0 {
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index 0296506c043b..21608ca46a55 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -166,6 +166,7 @@ hid-transport@0 {
&port00 {
/* WLAN */
bus-range = <1 1>;
+ pwren-gpios = <&smc_gpio 13 GPIO_ACTIVE_HIGH>;
wifi0: wifi@0,0 {
compatible = "pci14e4,4433";
reg = <0x10000 0x0 0x0 0x0 0x0>;
@@ -178,6 +179,7 @@ wifi0: wifi@0,0 {
&port01 {
/* SD card reader */
bus-range = <2 2>;
+ pwren-gpios = <&smc_gpio 26 GPIO_ACTIVE_HIGH>;
sdhci0: mmc@0,0 {
compatible = "pci17a0,9755";
reg = <0x20000 0x0 0x0 0x0 0x0>;
--
2.34.1

View File

@ -0,0 +1,37 @@
From fa4bcbf275b4c864bdf5506e44369e9a982d8bc4 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 3 Mar 2022 03:24:36 +0900
Subject: [PATCH 030/171] arm64: dts: apple: Add backlight node to j314/j316
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index 21608ca46a55..c5241d5515cf 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -26,6 +26,7 @@ framebuffer0: framebuffer@0 {
compatible = "apple,simple-framebuffer", "simple-framebuffer";
reg = <0 0 0 0>; /* To be filled by loader */
/* Format properties will be added by loader */
+ backlight = <&backlight>;
status = "disabled";
};
};
@@ -236,3 +237,11 @@ &dwc3_3_dart_1 {
&dwc3_3 {
status = "disabled";
};
+
+/ {
+ backlight: gpio-bl {
+ compatible = "gpio-backlight";
+ gpios = <&smc_gpio 19 GPIO_ACTIVE_HIGH>;
+ default-on;
+ };
+};
--
2.34.1

View File

@ -0,0 +1,96 @@
From c0ab64753e9a149b5c97f42110b5ff21d0d6322f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Fri, 11 Mar 2022 22:16:25 +0100
Subject: [PATCH 031/171] arm64: dts: apple: t600*: Put in audio nodes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
arch/arm64/boot/dts/apple/t600x-die0.dtsi | 72 +++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index b549059a3320..b24dd6ed0a37 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -441,3 +441,75 @@ port03: pci@3,0 {
<0 0 0 4 &port03 0 0 0 3>;
};
};
+
+ dart_sio_0: iommu@39b004000 {
+ compatible = "apple,t6000-dart", "apple,dart";
+ reg = <0x3 0x9b004000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1130 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_sio_cpu>;
+ };
+
+ dart_sio_1: iommu@39b008000 {
+ compatible = "apple,t6000-dart", "apple,dart";
+ reg = <0x3 0x9b008000 0x0 0x8000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1130 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_sio_cpu>;
+ };
+
+ nco_clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1068000000>;
+ clock-output-names = "nco_ref";
+ };
+
+ nco: nco@28e03c000 {
+ compatible = "apple,t6000-nco", "apple,nco";
+ reg = <0x2 0x8e03c000 0x0 0x14000>;
+ clocks = <&nco_clkref>;
+ #clock-cells = <1>;
+ };
+
+ admac: dma-controller@39b400000 {
+ compatible = "apple,t6000-admac", "apple,admac";
+ reg = <0x3 0x9b400000 0x0 0x34000>;
+ dma-channels = <16>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1118 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ iommus = <&dart_sio_0 2>, <&dart_sio_1 2>;
+ power-domains = <&ps_sio_adma>;
+ apple,internal-irq-destination = <1>;
+ };
+
+ mca: mca@9b600000 {
+ compatible = "apple,t6000-mca", "apple,mca";
+ reg = <0x3 0x9b600000 0x0 0x10000>,
+ <0x3 0x9b500000 0x0 0x20000>;
+ reg-names = "clusters", "switch";
+
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 1112 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 1113 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 1114 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 1115 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&nco 0>, <&nco 1>, <&nco 2>, <&nco 3>;
+ power-domains = <&ps_audio_p>, <&ps_mca0>, <&ps_mca1>,
+ <&ps_mca2>, <&ps_mca3>;
+ dmas = <&admac 0>, <&admac 1>, <&admac 2>, <&admac 3>,
+ <&admac 4>, <&admac 5>, <&admac 6>, <&admac 7>,
+ <&admac 8>, <&admac 9>, <&admac 10>, <&admac 11>,
+ <&admac 12>, <&admac 13>, <&admac 14>, <&admac 15>;
+ dma-names = "tx0a", "rx0a", "tx0b", "rx0b",
+ "tx1a", "rx1a", "tx1b", "rx1b",
+ "tx2a", "rx2a", "tx2b", "rx2b",
+ "tx3a", "rx3a", "tx3b", "rx3b";
+
+ #sound-dai-cells = <1>;
+ apple,nclusters = <4>;
+ };
--
2.34.1

View File

@ -0,0 +1,231 @@
From c390136c1f033e36969ea59352034603aca42071 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Fri, 11 Mar 2022 22:16:25 +0100
Subject: [PATCH 032/171] arm64: dts: apple: t600*: Put in audio nodes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
arch/arm64/boot/dts/apple/t6001-j375c.dts | 40 +++++++++
arch/arm64/boot/dts/apple/t6002-j375d.dts | 40 +++++++++
.../arm64/boot/dts/apple/t600x-j314-j316.dtsi | 87 +++++++++++++++++++
3 files changed, 167 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
index 561a9a4c2bc1..84be4c83f4d4 100644
--- a/arch/arm64/boot/dts/apple/t6001-j375c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -152,6 +152,18 @@ typec3_con_hs: endpoint {
};
};
+/* Audio */
+&i2c1 {
+ status = "okay";
+
+ speaker: codec@38 {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x38>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ };
+};
+
/* PCIe devices */
&port00 {
/* WLAN */
@@ -230,3 +242,31 @@ typec3_usb_hs: endpoint {
};
};
};
+
+/ {
+ sound {
+ compatible = "apple,j375-macaudio", "apple,macaudio";
+ model = "Mac Studio J375 integrated audio";
+
+ /*
+ * DANGER ZONE: You can blow your speakers!
+ *
+ * The drivers are not ready, and unless you are careful
+ * to attenuate the audio stream, you run the risk of
+ * blowing your speakers.
+ */
+ status = "disabled";
+
+ dai-link@0 {
+ link-name = "Speaker";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 0>;
+ };
+ codec {
+ sound-dai = <&speaker>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
index 72070e9a3277..58463d957d09 100644
--- a/arch/arm64/boot/dts/apple/t6002-j375d.dts
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -206,6 +206,18 @@ typec5_con_hs: endpoint {
};
};
+/* Audio */
+&i2c1 {
+ status = "okay";
+
+ speaker: codec@38 {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x38>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ };
+};
+
/* PCIe devices */
&port00 {
/* WLAN */
@@ -322,3 +334,31 @@ typec5_usb_hs: endpoint {
/delete-node/ &ps_disp0_cpu0_die1;
/delete-node/ &ps_disp0_fe_die1;
+
+/ {
+ sound {
+ compatible = "apple,j375-macaudio", "apple,macaudio";
+ model = "Mac Studio J375 integrated audio";
+
+ /*
+ * DANGER ZONE: You can blow your speakers!
+ *
+ * The drivers are not ready, and unless you are careful
+ * to attenuate the audio stream, you run the risk of
+ * blowing your speakers.
+ */
+ status = "disabled";
+
+ dai-link@0 {
+ link-name = "Speaker";
+ mclk-fs = <64>;
+
+ cpu {
+ sound-dai = <&mca 0>;
+ };
+ codec {
+ sound-dai = <&speaker>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index c5241d5515cf..666183f385b5 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -131,6 +131,62 @@ hpm5: usb-pd@3a {
};
};
+&i2c1 {
+ status = "okay";
+
+ speaker_left_tweet: codec@3a {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x3a>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Left Tweeter";
+ };
+
+ speaker_left_woof1: codec@38 {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x38>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Left Woofer 1";
+ };
+
+ speaker_left_woof2: codec@39 {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x39>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Left Woofer 2";
+ };
+};
+
+&i2c3 {
+ status = "okay";
+
+ speaker_right_tweet: codec@3d {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x3d>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Right Tweeter";
+ };
+
+ speaker_right_woof1: codec@3b {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x3b>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Right Woofer 1";
+ };
+
+ speaker_right_woof2: codec@3c {
+ compatible = "ti,sn012776", "ti,tas2764";
+ reg = <0x3c>;
+ shutdown-gpios = <&pinctrl_ap 178 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "Right Woofer 2";
+ };
+};
+
&spi1 {
status = "disabled";
@@ -244,4 +300,35 @@ backlight: gpio-bl {
gpios = <&smc_gpio 19 GPIO_ACTIVE_HIGH>;
default-on;
};
+
+ sound {
+ compatible = "apple,j314-macaudio", "apple,macaudio";
+ model = "MacBook Pro J314/6 integrated audio";
+
+ /*
+ * DANGER ZONE: You can blow your speakers!
+ *
+ * The drivers are not ready, and unless you are careful
+ * to attenuate the audio stream, you run the risk of
+ * blowing your speakers.
+ */
+ status = "disabled";
+
+ dai-link@0 {
+ link-name = "Speakers";
+ mclk-fs = <256>;
+
+ cpu {
+ sound-dai = <&mca 0>, <&mca 1>;
+ };
+ codec {
+ sound-dai = <&speaker_left_woof1>,
+ <&speaker_right_woof1>,
+ <&speaker_left_tweet>,
+ <&speaker_right_tweet>,
+ <&speaker_left_woof2>,
+ <&speaker_right_woof2>;
+ };
+ };
+ };
};
--
2.34.1

View File

@ -0,0 +1,32 @@
From 0672eebb472aaef8449aec4cb064acc86e3aae37 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 30 Jun 2022 21:48:46 +0900
Subject: [PATCH 033/171] arm64: dts: apple: t600*: Add t8103 compat to cpufreq
node
t600x seems to be fully compatible with t8103, but t8112 introduced
minor changes which means we can't provide full functionality with the
common compatible. Let t600x claim t8103 compatibility, treating the
latter as the common baseline for this SoC family.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t600x-die0.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index b24dd6ed0a37..4c203778aa89 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -7,7 +7,7 @@
*/
cpufreq_hw: cpufreq@210e20000 {
- compatible = "apple,t6000-soc-cpufreq", "apple,soc-cpufreq";
+ compatible = "apple,t6000-soc-cpufreq", "apple,t8103-soc-cpufreq", "apple,soc-cpufreq";
#freq-domain-cells = <1>;
};
--
2.34.1

View File

@ -0,0 +1,50 @@
From 6b11a54eb684f097803307b96eb5681c9168b506 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Mon, 27 Jun 2022 22:21:34 +0900
Subject: [PATCH 034/171] arm64: dts: apple: t8103: Fix spi4 power domain sort
order
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8103-pmgr.dtsi | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
index 68ae594bf5e9..df7f56483ee8 100644
--- a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
@@ -387,6 +387,15 @@ ps_spi3: power-controller@258 {
power-domains = <&ps_sio>, <&ps_spi_p>;
};
+ ps_spi4: power-controller@260 {
+ compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x260 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = "spi4";
+ power-domains = <&ps_sio>, <&ps_spi_p>;
+ };
+
ps_uart_n: power-controller@268 {
compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
reg = <0x268 4>;
@@ -558,15 +567,6 @@ ps_mcc: power-controller@2f8 {
apple,always-on; /* Memory controller */
};
- ps_spi4: power-controller@260 {
- compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
- reg = <0x260 4>;
- #power-domain-cells = <0>;
- #reset-cells = <0>;
- label = "spi4";
- power-domains = <&ps_sio>, <&ps_spi_p>;
- };
-
ps_dcs0: power-controller@300 {
compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
reg = <0x300 4>;
--
2.34.1

View File

@ -0,0 +1,117 @@
From 3b6593525fd6fe8d09e46e8543fcce20088de1e0 Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Wed, 6 Jul 2022 20:04:20 +0200
Subject: [PATCH 035/171] arm64: dts: apple: t8103: Add bluetooth device trees
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
arch/arm64/boot/dts/apple/t8103-j274.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j293.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j313.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j456.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-j457.dts | 4 ++++
arch/arm64/boot/dts/apple/t8103-jxxx.dtsi | 8 ++++++++
6 files changed, 28 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t8103-j274.dts b/arch/arm64/boot/dts/apple/t8103-j274.dts
index 811008bd73f3..4efbb085e407 100644
--- a/arch/arm64/boot/dts/apple/t8103-j274.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j274.dts
@@ -25,6 +25,10 @@ &wifi0 {
brcm,board-type = "apple,atlantisb";
};
+&bluetooth0 {
+ brcm,board-type = "apple,atlantisb";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 7eb98e6b947c..3a5ae54f0b9f 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -21,6 +21,10 @@ &wifi0 {
brcm,board-type = "apple,honshu";
};
+&bluetooth0 {
+ brcm,board-type = "apple,honshu";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index d1f65e48699f..b51f651d2326 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -21,6 +21,10 @@ &wifi0 {
brcm,board-type = "apple,shikoku";
};
+&bluetooth0 {
+ brcm,board-type = "apple,shikoku";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index e65053f3bd2c..5e098e8056e1 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -25,6 +25,10 @@ &wifi0 {
brcm,board-type = "apple,capri";
};
+&bluetooth0 {
+ brcm,board-type = "apple,capri";
+};
+
&i2c0 {
hpm2: usb-pd@3b {
compatible = "apple,cd321x";
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index 925fe4058055..f67c0b52075a 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -25,6 +25,10 @@ &wifi0 {
brcm,board-type = "apple,santorini";
};
+&bluetooth0 {
+ brcm,board-type = "apple,santorini";
+};
+
/*
* Provide labels for the USB type C ports.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
index e62664b6e450..7a814c7abe0c 100644
--- a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
@@ -11,6 +11,7 @@
/ {
aliases {
+ bluetooth0 = &bluetooth0;
serial0 = &serial0;
serial2 = &serial2;
wifi0 = &wifi0;
@@ -129,4 +130,11 @@ wifi0: network@0,0 {
local-mac-address = [00 00 00 00 00 00];
apple,antenna-sku = "XX";
};
+
+ bluetooth0: network@0,1 {
+ compatible = "pci14e4,5f69";
+ reg = <0x10100 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-bd-address = [00 00 00 00 00 00];
+ };
};
--
2.34.1

View File

@ -0,0 +1,167 @@
From 14fa82e8f1e6e379983d8222ed3214552c4b5c48 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Mon, 11 Jul 2022 20:05:02 +0900
Subject: [PATCH 036/171] arm64: dts: apple: t600x: Add bluetooth device trees
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t6000-j314s.dts | 4 ++++
arch/arm64/boot/dts/apple/t6000-j316s.dts | 4 ++++
arch/arm64/boot/dts/apple/t6001-j314c.dts | 4 ++++
arch/arm64/boot/dts/apple/t6001-j316c.dts | 4 ++++
arch/arm64/boot/dts/apple/t6001-j375c.dts | 12 ++++++++++++
arch/arm64/boot/dts/apple/t6002-j375d.dts | 12 ++++++++++++
arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi | 8 ++++++++
7 files changed, 48 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6000-j314s.dts b/arch/arm64/boot/dts/apple/t6000-j314s.dts
index ac35870ca129..1430b91ff1b1 100644
--- a/arch/arm64/boot/dts/apple/t6000-j314s.dts
+++ b/arch/arm64/boot/dts/apple/t6000-j314s.dts
@@ -20,3 +20,7 @@ / {
&wifi0 {
brcm,board-type = "apple,maldives";
};
+
+&bluetooth0 {
+ brcm,board-type = "apple,maldives";
+};
diff --git a/arch/arm64/boot/dts/apple/t6000-j316s.dts b/arch/arm64/boot/dts/apple/t6000-j316s.dts
index 77d6d8c14d74..da0cbe7d9673 100644
--- a/arch/arm64/boot/dts/apple/t6000-j316s.dts
+++ b/arch/arm64/boot/dts/apple/t6000-j316s.dts
@@ -20,3 +20,7 @@ / {
&wifi0 {
brcm,board-type = "apple,madagascar";
};
+
+&bluetooth0 {
+ brcm,board-type = "apple,madagascar";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j314c.dts b/arch/arm64/boot/dts/apple/t6001-j314c.dts
index 0a5655792a8f..c37097dcfdb3 100644
--- a/arch/arm64/boot/dts/apple/t6001-j314c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j314c.dts
@@ -20,3 +20,7 @@ / {
&wifi0 {
brcm,board-type = "apple,maldives";
};
+
+&bluetooth0 {
+ brcm,board-type = "apple,maldives";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j316c.dts b/arch/arm64/boot/dts/apple/t6001-j316c.dts
index 9c215531ea54..3bc6e0c3294c 100644
--- a/arch/arm64/boot/dts/apple/t6001-j316c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j316c.dts
@@ -20,3 +20,7 @@ / {
&wifi0 {
brcm,board-type = "apple,madagascar";
};
+
+&bluetooth0 {
+ brcm,board-type = "apple,madagascar";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
index 84be4c83f4d4..0f278170bd7a 100644
--- a/arch/arm64/boot/dts/apple/t6001-j375c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -18,6 +18,7 @@ / {
aliases {
serial0 = &serial0;
wifi0 = &wifi0;
+ bluetooth0 = &bluetooth0;
};
chosen {
@@ -176,6 +177,13 @@ wifi0: wifi@0,0 {
local-mac-address = [00 10 18 00 00 10];
apple,antenna-sku = "XX";
};
+
+ bluetooth0: network@0,1 {
+ compatible = "pci14e4,5f71";
+ reg = <0x10100 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-bd-address = [00 00 00 00 00 00];
+ };
};
&port01 {
@@ -210,6 +218,10 @@ &wifi0 {
brcm,board-type = "apple,okinawa";
};
+&bluetooth0 {
+ brcm,board-type = "apple,okinawa";
+};
+
/* USB controllers */
&dwc3_0 {
port {
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
index 58463d957d09..e3a554c6aa5e 100644
--- a/arch/arm64/boot/dts/apple/t6002-j375d.dts
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -18,6 +18,7 @@ / {
aliases {
serial0 = &serial0;
wifi0 = &wifi0;
+ bluetooth0 = &bluetooth0;
};
chosen {
@@ -230,6 +231,13 @@ wifi0: wifi@0,0 {
local-mac-address = [00 10 18 00 00 10];
apple,antenna-sku = "XX";
};
+
+ bluetooth0: network@0,1 {
+ compatible = "pci14e4,5f71";
+ reg = <0x10100 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-bd-address = [00 00 00 00 00 00];
+ };
};
&port01 {
@@ -264,6 +272,10 @@ &wifi0 {
brcm,board-type = "apple,okinawa";
};
+&bluetooth0 {
+ brcm,board-type = "apple,okinawa";
+};
+
/* USB controllers */
&dwc3_0 {
port {
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index 666183f385b5..bbe66ea64f09 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -13,6 +13,7 @@ / {
aliases {
serial0 = &serial0;
wifi0 = &wifi0;
+ bluetooth0 = &bluetooth0;
};
chosen {
@@ -231,6 +232,13 @@ wifi0: wifi@0,0 {
local-mac-address = [00 10 18 00 00 10];
apple,antenna-sku = "XX";
};
+
+ bluetooth0: network@0,1 {
+ compatible = "pci14e4,5f71";
+ reg = <0x10100 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-bd-address = [00 00 00 00 00 00];
+ };
};
&port01 {
--
2.34.1

View File

@ -0,0 +1,26 @@
From 792f2972bf4474af46468ab83cc7e0ab91469f2c Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 24 Jul 2022 00:11:49 +0900
Subject: [PATCH 038/171] arm64: dts: apple: t8112-j413: Fix IRQ for hpm5
Signed-off-by: Hector Martin <marcan@marcan.st>
---
arch/arm64/boot/dts/apple/t8112-j413.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/apple/t8112-j413.dts b/arch/arm64/boot/dts/apple/t8112-j413.dts
index 0cc993c0a5b4..0d4306a39fe8 100644
--- a/arch/arm64/boot/dts/apple/t8112-j413.dts
+++ b/arch/arm64/boot/dts/apple/t8112-j413.dts
@@ -74,7 +74,7 @@ hpm5: usb-pd@3a {
compatible = "apple,cd321x";
reg = <0x3a>;
interrupt-parent = <&pinctrl_ap>;
- interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "irq";
};
};
--
2.34.1

View File

@ -0,0 +1,30 @@
From aa4f300d5409c9a3d21787d170755ed417f95157 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 12 Dec 2021 12:28:41 +0900
Subject: [PATCH 039/171] MAINTAINERS: Add Apple dwc3 bindings to ARM/APPLE
This Apple dwc3 controller variance is present on Apple ARM SoCs (t8103/t600x).
Splitting this change from the binding/driver commits to avoid merge
conflicts with other things touching this section, as usual.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 64379c699903..b346659f9562 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1843,6 +1843,7 @@ F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: Documentation/devicetree/bindings/power/apple*
+F: Documentation/devicetree/bindings/usb/apple,dwc3.yaml
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
F: arch/arm64/boot/dts/apple/
F: drivers/clk/clk-apple-nco.c
--
2.34.1

View File

@ -0,0 +1,38 @@
From fa0ce4da1a4d60e003f808c21c008fb19ee31152 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 12 Dec 2021 12:28:41 +0900
Subject: [PATCH 040/171] MAINTAINERS: Add apple-spi driver & binding files
This Apple SPI controller is present on Apple ARM SoCs (t8103/t6000).
Splitting this change from the binding/driver commits to avoid merge
conflicts with other things touching this section, as usual.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
MAINTAINERS | 2 ++
1 file changed, 2 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index b346659f9562..629c1a177d3f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1843,6 +1843,7 @@ F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: Documentation/devicetree/bindings/power/apple*
+F: Documentation/devicetree/bindings/spi/apple,spi.yaml
F: Documentation/devicetree/bindings/usb/apple,dwc3.yaml
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
F: arch/arm64/boot/dts/apple/
@@ -1856,6 +1857,7 @@ F: drivers/nvme/host/apple.c
F: drivers/nvmem/apple-efuses.c
F: drivers/pinctrl/pinctrl-apple-gpio.c
F: drivers/soc/apple/*
+F: drivers/spi/spi-apple.c
F: drivers/watchdog/apple_wdt.c
F: include/dt-bindings/interrupt-controller/apple-aic.h
F: include/dt-bindings/pinctrl/apple.h
--
2.34.1

View File

@ -0,0 +1,74 @@
From 8a4bb71a27420d66c52e0b0347dddb5853c69a15 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 8 Feb 2022 16:57:47 +0900
Subject: [PATCH 041/171] mailbox: apple: Implement flush() operation
This allows clients to use the atomic-safe mailbox API style.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/mailbox/apple-mailbox.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/mailbox/apple-mailbox.c b/drivers/mailbox/apple-mailbox.c
index 496c4951ccb1..33e7acf71e3e 100644
--- a/drivers/mailbox/apple-mailbox.c
+++ b/drivers/mailbox/apple-mailbox.c
@@ -17,6 +17,7 @@
*/
#include <linux/apple-mailbox.h>
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gfp.h>
#include <linux/interrupt.h>
@@ -112,6 +113,14 @@ static bool apple_mbox_hw_can_send(struct apple_mbox *apple_mbox)
return !(mbox_ctrl & apple_mbox->hw->control_full);
}
+static bool apple_mbox_hw_send_empty(struct apple_mbox *apple_mbox)
+{
+ u32 mbox_ctrl =
+ readl_relaxed(apple_mbox->regs + apple_mbox->hw->a2i_control);
+
+ return mbox_ctrl & apple_mbox->hw->control_empty;
+}
+
static int apple_mbox_hw_send(struct apple_mbox *apple_mbox,
struct apple_mbox_msg *msg)
{
@@ -219,6 +228,23 @@ static irqreturn_t apple_mbox_recv_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static int apple_mbox_chan_flush(struct mbox_chan *chan, unsigned long timeout)
+{
+ struct apple_mbox *apple_mbox = chan->con_priv;
+ unsigned long deadline = jiffies + msecs_to_jiffies(timeout);
+
+ while (time_before(jiffies, deadline)) {
+ if (apple_mbox_hw_send_empty(apple_mbox)) {
+ mbox_chan_txdone(&apple_mbox->chan, 0);
+ return 0;
+ }
+
+ udelay(1);
+ }
+
+ return -ETIME;
+}
+
static int apple_mbox_chan_startup(struct mbox_chan *chan)
{
struct apple_mbox *apple_mbox = chan->con_priv;
@@ -250,6 +276,7 @@ static void apple_mbox_chan_shutdown(struct mbox_chan *chan)
static const struct mbox_chan_ops apple_mbox_ops = {
.send_data = apple_mbox_chan_send_data,
+ .flush = apple_mbox_chan_flush,
.startup = apple_mbox_chan_startup,
.shutdown = apple_mbox_chan_shutdown,
};
--
2.34.1

View File

@ -0,0 +1,106 @@
From fa28fb2edcc310f9038538b2f1d27998b01c7db7 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 8 Feb 2022 19:16:08 +0900
Subject: [PATCH 042/171] mailbox: apple: Implement poll_data() operation
This allows clients running in atomic context to poll for messages to
arrive.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/mailbox/apple-mailbox.c | 37 ++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/drivers/mailbox/apple-mailbox.c b/drivers/mailbox/apple-mailbox.c
index 33e7acf71e3e..1c14ff63f3d3 100644
--- a/drivers/mailbox/apple-mailbox.c
+++ b/drivers/mailbox/apple-mailbox.c
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/spinlock.h>
#include <linux/types.h>
#define APPLE_ASC_MBOX_CONTROL_FULL BIT(16)
@@ -101,6 +102,7 @@ struct apple_mbox {
struct device *dev;
struct mbox_controller controller;
+ spinlock_t rx_lock;
};
static const struct of_device_id apple_mbox_of_match[];
@@ -204,13 +206,16 @@ static irqreturn_t apple_mbox_send_empty_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t apple_mbox_recv_irq(int irq, void *data)
+static int apple_mbox_poll(struct apple_mbox *apple_mbox)
{
- struct apple_mbox *apple_mbox = data;
+
struct apple_mbox_msg msg;
+ int ret = 0;
- while (apple_mbox_hw_recv(apple_mbox, &msg) == 0)
+ while (apple_mbox_hw_recv(apple_mbox, &msg) == 0) {
mbox_chan_received_data(&apple_mbox->chan, (void *)&msg);
+ ret++;
+ }
/*
* The interrupt will keep firing even if there are no more messages
@@ -225,9 +230,33 @@ static irqreturn_t apple_mbox_recv_irq(int irq, void *data)
apple_mbox->regs + apple_mbox->hw->irq_ack);
}
+ return ret;
+}
+
+static irqreturn_t apple_mbox_recv_irq(int irq, void *data)
+{
+ struct apple_mbox *apple_mbox = data;
+
+ spin_lock(&apple_mbox->rx_lock);
+ apple_mbox_poll(apple_mbox);
+ spin_unlock(&apple_mbox->rx_lock);
+
return IRQ_HANDLED;
}
+static bool apple_mbox_chan_peek_data(struct mbox_chan *chan)
+{
+ struct apple_mbox *apple_mbox = chan->con_priv;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&apple_mbox->rx_lock, flags);
+ ret = apple_mbox_poll(apple_mbox);
+ spin_unlock_irqrestore(&apple_mbox->rx_lock, flags);
+
+ return ret > 0;
+}
+
static int apple_mbox_chan_flush(struct mbox_chan *chan, unsigned long timeout)
{
struct apple_mbox *apple_mbox = chan->con_priv;
@@ -276,6 +305,7 @@ static void apple_mbox_chan_shutdown(struct mbox_chan *chan)
static const struct mbox_chan_ops apple_mbox_ops = {
.send_data = apple_mbox_chan_send_data,
+ .peek_data = apple_mbox_chan_peek_data,
.flush = apple_mbox_chan_flush,
.startup = apple_mbox_chan_startup,
.shutdown = apple_mbox_chan_shutdown,
@@ -331,6 +361,7 @@ static int apple_mbox_probe(struct platform_device *pdev)
mbox->controller.txdone_irq = true;
mbox->controller.of_xlate = apple_mbox_of_xlate;
mbox->chan.con_priv = mbox;
+ spin_lock_init(&mbox->rx_lock);
irqname = devm_kasprintf(dev, GFP_KERNEL, "%s-recv", dev_name(dev));
if (!irqname)
--
2.34.1

View File

@ -0,0 +1,45 @@
From 9a204cb4333ca42ebc6401f8c782f99c82f3a75d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sat, 5 Mar 2022 01:08:33 +0900
Subject: [PATCH 043/171] mailbox: apple: Keep IRQs active in suspend
Some consumers (notably SMC) need to be wakeup sources for s2idle,
so the IRQs need to stay enabled during suspend. We expect
consumers to properly suspend coprocessors such that no IRQs would
be triggered where not necessary, so this can be done unconditionally.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/mailbox/apple-mailbox.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/mailbox/apple-mailbox.c b/drivers/mailbox/apple-mailbox.c
index 1c14ff63f3d3..4b34b4d11bd6 100644
--- a/drivers/mailbox/apple-mailbox.c
+++ b/drivers/mailbox/apple-mailbox.c
@@ -369,8 +369,8 @@ static int apple_mbox_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(dev, mbox->irq_recv_not_empty, NULL,
apple_mbox_recv_irq,
- IRQF_NO_AUTOEN | IRQF_ONESHOT, irqname,
- mbox);
+ IRQF_NO_AUTOEN | IRQF_ONESHOT | IRQF_NO_SUSPEND,
+ irqname, mbox);
if (ret)
return ret;
@@ -378,9 +378,8 @@ static int apple_mbox_probe(struct platform_device *pdev)
if (!irqname)
return -ENOMEM;
- ret = devm_request_irq(dev, mbox->irq_send_empty,
- apple_mbox_send_empty_irq, IRQF_NO_AUTOEN,
- irqname, mbox);
+ ret = devm_request_irq(dev, mbox->irq_send_empty, apple_mbox_send_empty_irq,
+ IRQF_NO_AUTOEN | IRQF_NO_SUSPEND, irqname, mbox);
if (ret)
return ret;
--
2.34.1

View File

@ -0,0 +1,101 @@
From f30928052eeecd551f0d3bbf5a7ac63913cbf6ae Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 5 May 2022 01:36:27 +0900
Subject: [PATCH 044/171] mailbox: apple: Fix races around poll/tx
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/mailbox/apple-mailbox.c | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/mailbox/apple-mailbox.c b/drivers/mailbox/apple-mailbox.c
index 4b34b4d11bd6..06c7ad3b1c03 100644
--- a/drivers/mailbox/apple-mailbox.c
+++ b/drivers/mailbox/apple-mailbox.c
@@ -103,6 +103,8 @@ struct apple_mbox {
struct device *dev;
struct mbox_controller controller;
spinlock_t rx_lock;
+ spinlock_t tx_lock;
+ bool tx_pending;
};
static const struct of_device_id apple_mbox_of_match[];
@@ -166,11 +168,15 @@ static int apple_mbox_chan_send_data(struct mbox_chan *chan, void *data)
{
struct apple_mbox *apple_mbox = chan->con_priv;
struct apple_mbox_msg *msg = data;
+ unsigned long flags;
int ret;
+ spin_lock_irqsave(&apple_mbox->tx_lock, flags);
+ WARN_ON(apple_mbox->tx_pending);
+
ret = apple_mbox_hw_send(apple_mbox, msg);
if (ret)
- return ret;
+ goto err_unlock;
/*
* The interrupt is level triggered and will keep firing as long as the
@@ -185,9 +191,13 @@ static int apple_mbox_chan_send_data(struct mbox_chan *chan, void *data)
writel_relaxed(apple_mbox->hw->irq_bit_send_empty,
apple_mbox->regs + apple_mbox->hw->irq_ack);
}
+ apple_mbox->tx_pending = true;
enable_irq(apple_mbox->irq_send_empty);
- return 0;
+err_unlock:
+ spin_unlock_irqrestore(&apple_mbox->tx_lock, flags);
+
+ return ret;
}
static irqreturn_t apple_mbox_send_empty_irq(int irq, void *data)
@@ -202,7 +212,14 @@ static irqreturn_t apple_mbox_send_empty_irq(int irq, void *data)
* it at the main controller again.
*/
disable_irq_nosync(apple_mbox->irq_send_empty);
- mbox_chan_txdone(&apple_mbox->chan, 0);
+ spin_lock(&apple_mbox->tx_lock);
+ if (apple_mbox->tx_pending) {
+ apple_mbox->tx_pending = false;
+ spin_unlock(&apple_mbox->tx_lock);
+ mbox_chan_txdone(&apple_mbox->chan, 0);
+ } else {
+ spin_unlock(&apple_mbox->tx_lock);
+ }
return IRQ_HANDLED;
}
@@ -261,10 +278,17 @@ static int apple_mbox_chan_flush(struct mbox_chan *chan, unsigned long timeout)
{
struct apple_mbox *apple_mbox = chan->con_priv;
unsigned long deadline = jiffies + msecs_to_jiffies(timeout);
+ unsigned long flags;
while (time_before(jiffies, deadline)) {
if (apple_mbox_hw_send_empty(apple_mbox)) {
- mbox_chan_txdone(&apple_mbox->chan, 0);
+ spin_lock_irqsave(&apple_mbox->tx_lock, flags);
+ if (apple_mbox->tx_pending) {
+ apple_mbox->tx_pending = false;
+ disable_irq_nosync(apple_mbox->irq_send_empty);
+ }
+ /* Mailbox subsystem will call txdone for us */
+ spin_unlock_irqrestore(&apple_mbox->tx_lock, flags);
return 0;
}
@@ -362,6 +386,7 @@ static int apple_mbox_probe(struct platform_device *pdev)
mbox->controller.of_xlate = apple_mbox_of_xlate;
mbox->chan.con_priv = mbox;
spin_lock_init(&mbox->rx_lock);
+ spin_lock_init(&mbox->tx_lock);
irqname = devm_kasprintf(dev, GFP_KERNEL, "%s-recv", dev_name(dev));
if (!irqname)
--
2.34.1

View File

@ -0,0 +1,26 @@
From 34019420175a9edf6d35b567815757eee727f078 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 5 May 2022 01:37:01 +0900
Subject: [PATCH 045/171] WIP: mailbox: fix poll
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/mailbox/mailbox.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index 4229b9b5da98..e27500e8cba9 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -310,7 +310,7 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
return -ENOTSUPP;
ret = chan->mbox->ops->flush(chan, timeout);
- if (ret < 0)
+ if (ret >= 0)
tx_tick(chan, ret);
return ret;
--
2.34.1

View File

@ -0,0 +1,37 @@
From 88e0c4540822cbd63ec7618eaed2279126bdd042 Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Tue, 2 Nov 2021 18:10:51 +0100
Subject: [PATCH 046/171] dt-bindings: iommu: dart: add t6000 compatible
The M1 Max/Pro SoCs come with a new DART variant that is incompatible with
the previous one. Add a new compatible for those.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
Acked-by: Rob Herring <robh@kernel.org>
Series-changes: 2
- added Rob's Acked-by:
Patch-cc: Mark Kettenis <mark.kettenis@xs4all.nl>
---
Documentation/devicetree/bindings/iommu/apple,dart.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/iommu/apple,dart.yaml b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
index 82ad669feef7..06af2bacbe97 100644
--- a/Documentation/devicetree/bindings/iommu/apple,dart.yaml
+++ b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
@@ -22,7 +22,9 @@ description: |+
properties:
compatible:
- const: apple,t8103-dart
+ enum:
+ - apple,t8103-dart
+ - apple,t6000-dart
reg:
maxItems: 1
--
2.34.1

View File

@ -0,0 +1,825 @@
From 799fd906a17a263eaad29e3246dc4b468bb1edc6 Mon Sep 17 00:00:00 2001
From: Janne Grunau <j@jannau.net>
Date: Wed, 8 Jun 2022 19:07:49 +0200
Subject: [PATCH 047/171] iommu/io-pgtable: Move Apple DART support to its own
file
The pte format used by the DARTs found in the Apple M1 (t8103) is not
fully compatible with io-pgtable-arm. The 24 MSB are used for subpage
protection (mapping only parts of page) and conflict with the address
mask. In addition bit 1 is not available for tagging entries but disables
subpage protection. Subpage protection could be useful to support a CPU
granule of 4k with the fixed IOMMU page size of 16k.
The DARTs found on Apple M1 Pro/Max/Ultra use another different pte
format which is even less compatible. To support an output address size
of 42 bit the address is shifted down by 4. Subpage protection is
mandatory and bit 1 signifies uncached mappings used by the display
controller.
It would be advantageous to share code for all known Apple DART
variants to support common features. The page table allocator for DARTs
is less complex since it uses a two levels of translation table without
support for huge pages.
Signed-off-by: Janne Grunau <j@jannau.net>
Series-changes: 2
- add APPLE_DART2 io-pgtable format
Series-changes: 3
- move APPLE_DART to its own io-pgtable implementation, copied from
io-pgtable-arm and simplified
Series-version: 3
Cover-letter:
iommu: M1 Pro/Max DART support
Hej,
this is the next attempt adding support for the DART found in Apple's
M1 Pro/Max/Ultra. This adds a separate io-pgtable implementation for
DART. As already mentioned in v2 the pte format is not fully compatible
with io-pgtable-arm. Especially the 2nd least significant bit is used
and is not available to tag tables/pages.
io-pgtable-dart.c is copied from io-pgtable-arm.c and support for
unused features is removed. Support for 4k IO pages is left for A7 to
A11 SoCs as there's work underway to run Linux on them.
The incompatibilities between both Apple DART pte seems manageable in
their own io-pgtable implementation. A short list of the known
differences:
- the physical addresses are shifted left by 4 bits and and have 2 more
bits inside the PTE entries
- the read/write protection flags are at a different position
- the subpage protection feature is now mandatory. For Linux we can
just configure it to always allow access to the entire page.
- BIT(1) tags "uncached" mappings (used for the display controller)
There is second type of DART (t8110) present on M1 Pro/Max SoCs which
uses the same PTE format as t6000.
END
Series-to: iommu@lists.linux-foundation.org
Series-cc: asahi@lists.linux.dev
Series-cc: Konrad Dybcio <konrad.dybcio@somainline.org>
---
MAINTAINERS | 1 +
drivers/iommu/Kconfig | 11 +-
drivers/iommu/Makefile | 1 +
drivers/iommu/io-pgtable-arm.c | 63 ----
drivers/iommu/io-pgtable-dart.c | 580 ++++++++++++++++++++++++++++++++
drivers/iommu/io-pgtable.c | 2 +
6 files changed, 594 insertions(+), 64 deletions(-)
create mode 100644 drivers/iommu/io-pgtable-dart.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 64379c699903..cb0ceb0b2cfc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1849,6 +1849,7 @@ F: drivers/clk/clk-apple-nco.c
F: drivers/i2c/busses/i2c-pasemi-core.c
F: drivers/i2c/busses/i2c-pasemi-platform.c
F: drivers/iommu/apple-dart.c
+F: drivers/iommu/io-pgtable-dart.c
F: drivers/irqchip/irq-apple-aic.c
F: drivers/mailbox/apple-mailbox.c
F: drivers/nvme/host/apple.c
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index c79a0df090c0..58603124dd42 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -67,6 +67,15 @@ config IOMMU_IO_PGTABLE_ARMV7S_SELFTEST
If unsure, say N here.
+config IOMMU_IO_PGTABLE_DART
+ bool "Apple DART Formats"
+ select IOMMU_IO_PGTABLE
+ depends on ARM64 || (COMPILE_TEST && !GENERIC_ATOMIC64)
+ help
+ Enable support for the Apple DART pagetable formats. These include
+ the t8020 and t6000/t8110 DART formats used in Apple M1/M2 family
+ SoCs.
+
endmenu
config IOMMU_DEBUGFS
@@ -294,7 +303,7 @@ config APPLE_DART
tristate "Apple DART IOMMU Support"
depends on ARCH_APPLE || (COMPILE_TEST && !GENERIC_ATOMIC64)
select IOMMU_API
- select IOMMU_IO_PGTABLE_LPAE
+ select IOMMU_IO_PGTABLE_DART
default ARCH_APPLE
help
Support for Apple DART (Device Address Resolution Table) IOMMUs
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 44475a9b3eea..cc9f381013c3 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
+obj-$(CONFIG_IOMMU_IO_PGTABLE_DART) += io-pgtable-dart.o
obj-$(CONFIG_IOASID) += ioasid.o
obj-$(CONFIG_IOMMU_IOVA) += iova.o
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 94ff319ae8ac..d7f5e23da643 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -130,9 +130,6 @@
#define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL
#define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL
-#define APPLE_DART_PTE_PROT_NO_WRITE (1<<7)
-#define APPLE_DART_PTE_PROT_NO_READ (1<<8)
-
/* IOPTE accessors */
#define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))
@@ -406,15 +403,6 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
{
arm_lpae_iopte pte;
- if (data->iop.fmt == APPLE_DART) {
- pte = 0;
- if (!(prot & IOMMU_WRITE))
- pte |= APPLE_DART_PTE_PROT_NO_WRITE;
- if (!(prot & IOMMU_READ))
- pte |= APPLE_DART_PTE_PROT_NO_READ;
- return pte;
- }
-
if (data->iop.fmt == ARM_64_LPAE_S1 ||
data->iop.fmt == ARM_32_LPAE_S1) {
pte = ARM_LPAE_PTE_nG;
@@ -1107,52 +1095,6 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
return NULL;
}
-static struct io_pgtable *
-apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
-{
- struct arm_lpae_io_pgtable *data;
- int i;
-
- if (cfg->oas > 36)
- return NULL;
-
- data = arm_lpae_alloc_pgtable(cfg);
- if (!data)
- return NULL;
-
- /*
- * The table format itself always uses two levels, but the total VA
- * space is mapped by four separate tables, making the MMIO registers
- * an effective "level 1". For simplicity, though, we treat this
- * equivalently to LPAE stage 2 concatenation at level 2, with the
- * additional TTBRs each just pointing at consecutive pages.
- */
- if (data->start_level < 1)
- goto out_free_data;
- if (data->start_level == 1 && data->pgd_bits > 2)
- goto out_free_data;
- if (data->start_level > 1)
- data->pgd_bits = 0;
- data->start_level = 2;
- cfg->apple_dart_cfg.n_ttbrs = 1 << data->pgd_bits;
- data->pgd_bits += data->bits_per_level;
-
- data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data), GFP_KERNEL,
- cfg);
- if (!data->pgd)
- goto out_free_data;
-
- for (i = 0; i < cfg->apple_dart_cfg.n_ttbrs; ++i)
- cfg->apple_dart_cfg.ttbr[i] =
- virt_to_phys(data->pgd + i * ARM_LPAE_GRANULE(data));
-
- return &data->iop;
-
-out_free_data:
- kfree(data);
- return NULL;
-}
-
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = {
.alloc = arm_64_lpae_alloc_pgtable_s1,
.free = arm_lpae_free_pgtable,
@@ -1178,11 +1120,6 @@ struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = {
.free = arm_lpae_free_pgtable,
};
-struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns = {
- .alloc = apple_dart_alloc_pgtable,
- .free = arm_lpae_free_pgtable,
-};
-
#ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST
static struct io_pgtable_cfg *cfg_cookie __initdata;
diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
new file mode 100644
index 000000000000..0c5222942c65
--- /dev/null
+++ b/drivers/iommu/io-pgtable-dart.c
@@ -0,0 +1,580 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Apple DART page table allocator.
+ *
+ * Copyright (C) 2022 The Asahi Linux Contributors
+ *
+ * Based on io-pgtable-arm.
+ *
+ * Copyright (C) 2014 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#define pr_fmt(fmt) "dart io-pgtable: " fmt
+
+#include <linux/atomic.h>
+#include <linux/bitops.h>
+#include <linux/io-pgtable.h>
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <asm/barrier.h>
+
+#define DART_MAX_ADDR_BITS 52
+#define DART_MAX_LEVELS 3
+
+/* Struct accessors */
+#define io_pgtable_to_data(x) \
+ container_of((x), struct dart_io_pgtable, iop)
+
+#define io_pgtable_ops_to_data(x) \
+ io_pgtable_to_data(io_pgtable_ops_to_pgtable(x))
+
+/*
+ * Calculate the right shift amount to get to the portion describing level l
+ * in a virtual address mapped by the pagetable in d.
+ */
+#define DART_LVL_SHIFT(l, d) \
+ (((DART_MAX_LEVELS - (l)) * (d)->bits_per_level) + \
+ ilog2(sizeof(dart_iopte)))
+
+#define DART_GRANULE(d) \
+ (sizeof(dart_iopte) << (d)->bits_per_level)
+#define DART_PGD_SIZE(d) \
+ (sizeof(dart_iopte) << (d)->pgd_bits)
+
+#define DART_PTES_PER_TABLE(d) \
+ (DART_GRANULE(d) >> ilog2(sizeof(dart_iopte)))
+
+/*
+ * Calculate the index at level l used to map virtual address a using the
+ * pagetable in d.
+ */
+#define DART_PGD_IDX(l, d) \
+ ((l) == (d)->start_level ? (d)->pgd_bits - (d)->bits_per_level : 0)
+
+#define DART_LVL_IDX(a, l, d) \
+ (((u64)(a) >> DART_LVL_SHIFT(l, d)) & \
+ ((1 << ((d)->bits_per_level + DART_PGD_IDX(l, d))) - 1))
+
+/* Calculate the block/page mapping size at level l for pagetable in d. */
+#define DART_BLOCK_SIZE(l, d) (1ULL << DART_LVL_SHIFT(l, d))
+
+#define APPLE_DART1_PADDR_MASK GENMASK_ULL(35, 12)
+
+/* Apple DART1 protection bits */
+#define APPLE_DART1_PTE_PROT_NO_READ BIT(8)
+#define APPLE_DART1_PTE_PROT_NO_WRITE BIT(7)
+#define APPLE_DART1_PTE_PROT_SP_DIS BIT(1)
+
+/* marks PTE as valid */
+#define APPLE_DART_PTE_VALID BIT(0)
+
+/* IOPTE accessors */
+#define iopte_deref(pte, d) __va(iopte_to_paddr(pte, d))
+
+struct dart_io_pgtable {
+ struct io_pgtable iop;
+
+ int pgd_bits;
+ int start_level;
+ int bits_per_level;
+
+ void *pgd;
+};
+
+typedef u64 dart_iopte;
+
+static inline bool iopte_leaf(dart_iopte pte, int lvl,
+ enum io_pgtable_fmt fmt)
+{
+ return (lvl == (DART_MAX_LEVELS - 1)) && (pte & APPLE_DART_PTE_VALID);
+}
+
+static dart_iopte paddr_to_iopte(phys_addr_t paddr,
+ struct dart_io_pgtable *data)
+{
+ return paddr & APPLE_DART1_PADDR_MASK;
+}
+
+static phys_addr_t iopte_to_paddr(dart_iopte pte,
+ struct dart_io_pgtable *data)
+{
+ return pte & APPLE_DART1_PADDR_MASK;
+}
+
+static void *__dart_alloc_pages(size_t size, gfp_t gfp,
+ struct io_pgtable_cfg *cfg)
+{
+ struct device *dev = cfg->iommu_dev;
+ int order = get_order(size);
+ struct page *p;
+
+ VM_BUG_ON((gfp & __GFP_HIGHMEM));
+ p = alloc_pages_node(dev ? dev_to_node(dev) : NUMA_NO_NODE,
+ gfp | __GFP_ZERO, order);
+ if (!p)
+ return NULL;
+
+ return page_address(p);
+}
+
+static void __dart_free_pages(void *pages, size_t size)
+{
+ free_pages((unsigned long)pages, get_order(size));
+}
+
+static void __dart_init_pte(struct dart_io_pgtable *data,
+ phys_addr_t paddr, dart_iopte prot,
+ int lvl, int num_entries, dart_iopte *ptep)
+{
+ dart_iopte pte = prot;
+ size_t sz = DART_BLOCK_SIZE(lvl, data);
+ int i;
+
+ if (lvl == DART_MAX_LEVELS - 1)
+ pte |= APPLE_DART1_PTE_PROT_SP_DIS;
+
+ pte |= APPLE_DART_PTE_VALID;
+
+ for (i = 0; i < num_entries; i++)
+ ptep[i] = pte | paddr_to_iopte(paddr + i * sz, data);
+}
+
+static int dart_init_pte(struct dart_io_pgtable *data,
+ unsigned long iova, phys_addr_t paddr,
+ dart_iopte prot, int lvl, int num_entries,
+ dart_iopte *ptep)
+{
+ int i;
+
+ for (i = 0; i < num_entries; i++)
+ if (iopte_leaf(ptep[i], lvl, data->iop.fmt)) {
+ /* We require an unmap first */
+ WARN_ON(iopte_leaf(ptep[i], lvl, data->iop.fmt));
+ return -EEXIST;
+ }
+
+ __dart_init_pte(data, paddr, prot, lvl, num_entries, ptep);
+ return 0;
+}
+
+static dart_iopte dart_install_table(dart_iopte *table,
+ dart_iopte *ptep,
+ dart_iopte curr,
+ struct dart_io_pgtable *data)
+{
+ dart_iopte old, new;
+
+ new = paddr_to_iopte(__pa(table), data) | APPLE_DART_PTE_VALID;
+
+ /*
+ * Ensure the table itself is visible before its PTE can be.
+ * Whilst we could get away with cmpxchg64_release below, this
+ * doesn't have any ordering semantics when !CONFIG_SMP.
+ */
+ dma_wmb();
+
+ old = cmpxchg64_relaxed(ptep, curr, new);
+
+ return old;
+}
+
+static int __dart_map(struct dart_io_pgtable *data, unsigned long iova,
+ phys_addr_t paddr, size_t size, size_t pgcount,
+ dart_iopte prot, int lvl, dart_iopte *ptep,
+ gfp_t gfp, size_t *mapped)
+{
+ dart_iopte *cptep, pte;
+ size_t block_size = DART_BLOCK_SIZE(lvl, data);
+ size_t tblsz = DART_GRANULE(data);
+ struct io_pgtable_cfg *cfg = &data->iop.cfg;
+ int ret = 0, num_entries, max_entries, map_idx_start;
+
+ /* Find our entry at the current level */
+ map_idx_start = DART_LVL_IDX(iova, lvl, data);
+ ptep += map_idx_start;
+
+ /* If we can install a leaf entry at this level, then do so */
+ if (size == block_size) {
+ max_entries = DART_PTES_PER_TABLE(data) - map_idx_start;
+ num_entries = min_t(int, pgcount, max_entries);
+ ret = dart_init_pte(data, iova, paddr, prot, lvl, num_entries, ptep);
+ if (!ret && mapped)
+ *mapped += num_entries * size;
+
+ return ret;
+ }
+
+ /* We can't allocate tables at the final level */
+ if (WARN_ON(lvl >= DART_MAX_LEVELS - 1))
+ return -EINVAL;
+
+ /* Grab a pointer to the next level */
+ pte = READ_ONCE(*ptep);
+ if (!pte) {
+ cptep = __dart_alloc_pages(tblsz, gfp, cfg);
+ if (!cptep)
+ return -ENOMEM;
+
+ pte = dart_install_table(cptep, ptep, 0, data);
+ if (pte)
+ __dart_free_pages(cptep, tblsz);
+ }
+
+ if (pte && !iopte_leaf(pte, lvl, data->iop.fmt)) {
+ cptep = iopte_deref(pte, data);
+ } else if (pte) {
+ /* We require an unmap first */
+ WARN_ON(pte);
+ return -EEXIST;
+ }
+
+ /* Rinse, repeat */
+ return __dart_map(data, iova, paddr, size, pgcount, prot, lvl + 1,
+ cptep, gfp, mapped);
+}
+
+static dart_iopte dart_prot_to_pte(struct dart_io_pgtable *data,
+ int prot)
+{
+ dart_iopte pte = 0;
+
+ if (!(prot & IOMMU_WRITE))
+ pte |= APPLE_DART1_PTE_PROT_NO_WRITE;
+ if (!(prot & IOMMU_READ))
+ pte |= APPLE_DART1_PTE_PROT_NO_READ;
+
+ return pte;
+}
+
+static int dart_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize, size_t pgcount,
+ int iommu_prot, gfp_t gfp, size_t *mapped)
+{
+ struct dart_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ struct io_pgtable_cfg *cfg = &data->iop.cfg;
+ dart_iopte *ptep = data->pgd;
+ int ret, lvl = data->start_level;
+ dart_iopte prot;
+ long iaext = (s64)iova >> cfg->ias;
+
+ if (WARN_ON(!pgsize || (pgsize & cfg->pgsize_bitmap) != pgsize))
+ return -EINVAL;
+
+ if (WARN_ON(iaext || paddr >> cfg->oas))
+ return -ERANGE;
+
+ /* If no access, then nothing to do */
+ if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
+ return 0;
+
+ prot = dart_prot_to_pte(data, iommu_prot);
+ ret = __dart_map(data, iova, paddr, pgsize, pgcount, prot, lvl,
+ ptep, gfp, mapped);
+ /*
+ * Synchronise all PTE updates for the new mapping before there's
+ * a chance for anything to kick off a table walk for the new iova.
+ */
+ wmb();
+
+ return ret;
+}
+
+static int dart_map(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t size, int iommu_prot, gfp_t gfp)
+{
+ return dart_map_pages(ops, iova, paddr, size, 1, iommu_prot, gfp,
+ NULL);
+}
+
+static void __dart_free_pgtable(struct dart_io_pgtable *data, int lvl,
+ dart_iopte *ptep)
+{
+ dart_iopte *start, *end;
+ unsigned long table_size;
+
+ if (lvl == data->start_level)
+ table_size = DART_PGD_SIZE(data);
+ else
+ table_size = DART_GRANULE(data);
+
+ start = ptep;
+
+ /* Only leaf entries at the last level */
+ if (lvl == DART_MAX_LEVELS - 1)
+ end = ptep;
+ else
+ end = (void *)ptep + table_size;
+
+ while (ptep != end) {
+ dart_iopte pte = *ptep++;
+
+ if (!pte || iopte_leaf(pte, lvl, data->iop.fmt))
+ continue;
+
+ __dart_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
+ }
+
+ __dart_free_pages(start, table_size);
+}
+
+static size_t __dart_unmap(struct dart_io_pgtable *data,
+ struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t size, size_t pgcount,
+ int lvl, dart_iopte *ptep)
+{
+ dart_iopte pte;
+ struct io_pgtable *iop = &data->iop;
+ int i = 0, num_entries, max_entries, unmap_idx_start;
+
+ /* Something went horribly wrong and we ran out of page table */
+ if (WARN_ON(lvl == DART_MAX_LEVELS))
+ return 0;
+
+ unmap_idx_start = DART_LVL_IDX(iova, lvl, data);
+ ptep += unmap_idx_start;
+ pte = READ_ONCE(*ptep);
+ if (WARN_ON(!pte))
+ return 0;
+
+ /* If the size matches this level, we're in the right place */
+ if (size == DART_BLOCK_SIZE(lvl, data)) {
+ max_entries = DART_PTES_PER_TABLE(data) - unmap_idx_start;
+ num_entries = min_t(int, pgcount, max_entries);
+
+ while (i < num_entries) {
+ pte = READ_ONCE(*ptep);
+ if (WARN_ON(!pte))
+ break;
+
+ /* clear pte */
+ *ptep = 0;
+
+ if (!iopte_leaf(pte, lvl, iop->fmt)) {
+ /* Also flush any partial walks */
+ io_pgtable_tlb_flush_walk(iop, iova + i * size, size,
+ DART_GRANULE(data));
+ __dart_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
+ } else if (!iommu_iotlb_gather_queued(gather)) {
+ io_pgtable_tlb_add_page(iop, gather, iova + i * size, size);
+ }
+
+ ptep++;
+ i++;
+ }
+
+ return i * size;
+ }
+
+ /* Keep on walkin' */
+ ptep = iopte_deref(pte, data);
+ return __dart_unmap(data, gather, iova, size, pgcount, lvl + 1, ptep);
+}
+
+static size_t dart_unmap_pages(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *gather)
+{
+ struct dart_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ struct io_pgtable_cfg *cfg = &data->iop.cfg;
+ dart_iopte *ptep = data->pgd;
+ long iaext = (s64)iova >> cfg->ias;
+
+ if (WARN_ON(!pgsize || (pgsize & cfg->pgsize_bitmap) != pgsize || !pgcount))
+ return 0;
+
+ if (WARN_ON(iaext))
+ return 0;
+
+ return __dart_unmap(data, gather, iova, pgsize, pgcount,
+ data->start_level, ptep);
+}
+
+static size_t dart_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t size, struct iommu_iotlb_gather *gather)
+{
+ return dart_unmap_pages(ops, iova, size, 1, gather);
+}
+
+static phys_addr_t dart_iova_to_phys(struct io_pgtable_ops *ops,
+ unsigned long iova)
+{
+ struct dart_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ dart_iopte pte, *ptep = data->pgd;
+ int lvl = data->start_level;
+
+ do {
+ /* Valid IOPTE pointer? */
+ if (!ptep)
+ return 0;
+
+ /* Grab the IOPTE we're interested in */
+ ptep += DART_LVL_IDX(iova, lvl, data);
+ pte = READ_ONCE(*ptep);
+
+ /* Valid entry? */
+ if (!pte)
+ return 0;
+
+ /* Leaf entry? */
+ if (iopte_leaf(pte, lvl, data->iop.fmt))
+ goto found_translation;
+
+ /* Take it to the next level */
+ ptep = iopte_deref(pte, data);
+ } while (++lvl < DART_MAX_LEVELS);
+
+ /* Ran out of page tables to walk */
+ return 0;
+
+found_translation:
+ iova &= (DART_BLOCK_SIZE(lvl, data) - 1);
+ return iopte_to_paddr(pte, data) | iova;
+}
+
+static void dart_restrict_pgsizes(struct io_pgtable_cfg *cfg)
+{
+ unsigned long granule, page_sizes;
+ unsigned int max_addr_bits = 48;
+
+ /*
+ * We need to restrict the supported page sizes to match the
+ * translation regime for a particular granule. Aim to match
+ * the CPU page size if possible, otherwise prefer smaller sizes.
+ * While we're at it, restrict the block sizes to match the
+ * chosen granule.
+ */
+ if (cfg->pgsize_bitmap & PAGE_SIZE)
+ granule = PAGE_SIZE;
+ else if (cfg->pgsize_bitmap & ~PAGE_MASK)
+ granule = 1UL << __fls(cfg->pgsize_bitmap & ~PAGE_MASK);
+ else if (cfg->pgsize_bitmap & PAGE_MASK)
+ granule = 1UL << __ffs(cfg->pgsize_bitmap & PAGE_MASK);
+ else
+ granule = 0;
+
+ switch (granule) {
+ case SZ_4K:
+ page_sizes = (SZ_4K | SZ_2M | SZ_1G);
+ break;
+ case SZ_16K:
+ page_sizes = (SZ_16K | SZ_32M);
+ break;
+ default:
+ page_sizes = 0;
+ }
+
+ cfg->pgsize_bitmap &= page_sizes;
+ cfg->ias = min(cfg->ias, max_addr_bits);
+ cfg->oas = min(cfg->oas, max_addr_bits);
+}
+
+static struct dart_io_pgtable *
+dart_alloc_pgtable(struct io_pgtable_cfg *cfg)
+{
+ struct dart_io_pgtable *data;
+ int bits_per_level, levels, va_bits, pg_shift;
+
+ dart_restrict_pgsizes(cfg);
+
+ if (!(cfg->pgsize_bitmap & (SZ_4K | SZ_16K)))
+ return NULL;
+
+ if (cfg->ias > DART_MAX_ADDR_BITS)
+ return NULL;
+
+ if (cfg->oas > DART_MAX_ADDR_BITS)
+ return NULL;
+
+ pg_shift = __ffs(cfg->pgsize_bitmap);
+ bits_per_level = pg_shift - ilog2(sizeof(dart_iopte));
+
+ va_bits = cfg->ias - pg_shift;
+ levels = DIV_ROUND_UP(va_bits, bits_per_level);
+ if (levels > DART_MAX_LEVELS)
+ return NULL;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ data->bits_per_level = bits_per_level;
+ data->start_level = DART_MAX_LEVELS - levels;
+
+ /* Calculate the actual size of our pgd (without concatenation) */
+ data->pgd_bits = va_bits - (data->bits_per_level * (levels - 1));
+
+ data->iop.ops = (struct io_pgtable_ops) {
+ .map = dart_map,
+ .map_pages = dart_map_pages,
+ .unmap = dart_unmap,
+ .unmap_pages = dart_unmap_pages,
+ .iova_to_phys = dart_iova_to_phys,
+ };
+
+ return data;
+}
+
+static struct io_pgtable *
+apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
+{
+ struct dart_io_pgtable *data;
+ int i;
+
+ if (!cfg->coherent_walk)
+ return NULL;
+
+ if (cfg->oas > 36)
+ return NULL;
+
+ data = dart_alloc_pgtable(cfg);
+ if (!data)
+ return NULL;
+
+ /*
+ * The table format itself always uses two levels, but the total VA
+ * space is mapped by four separate tables, making the MMIO registers
+ * an effective "level 1". For simplicity, though, we treat this
+ * equivalently to LPAE stage 2 concatenation at level 2, with the
+ * additional TTBRs each just pointing at consecutive pages.
+ */
+ if (data->start_level == 0 && data->pgd_bits > 2)
+ goto out_free_data;
+ if (data->start_level > 0)
+ data->pgd_bits = 0;
+ data->start_level = 1;
+ cfg->apple_dart_cfg.n_ttbrs = 1 << data->pgd_bits;
+ data->pgd_bits += data->bits_per_level;
+
+ data->pgd = __dart_alloc_pages(DART_PGD_SIZE(data), GFP_KERNEL,
+ cfg);
+ if (!data->pgd)
+ goto out_free_data;
+
+ for (i = 0; i < cfg->apple_dart_cfg.n_ttbrs; ++i)
+ cfg->apple_dart_cfg.ttbr[i] =
+ virt_to_phys(data->pgd + i * DART_GRANULE(data));
+
+ return &data->iop;
+
+out_free_data:
+ kfree(data);
+ return NULL;
+}
+
+static void apple_dart_free_pgtable(struct io_pgtable *iop)
+{
+ struct dart_io_pgtable *data = io_pgtable_to_data(iop);
+
+ __dart_free_pgtable(data, data->start_level, data->pgd);
+ kfree(data);
+}
+
+struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns = {
+ .alloc = apple_dart_alloc_pgtable,
+ .free = apple_dart_free_pgtable,
+};
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index f4bfcef98297..16205ea9272c 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -20,6 +20,8 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
[ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns,
[ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns,
[ARM_MALI_LPAE] = &io_pgtable_arm_mali_lpae_init_fns,
+#endif
+#ifdef CONFIG_IOMMU_IO_PGTABLE_DART
[APPLE_DART] = &io_pgtable_apple_dart_init_fns,
#endif
#ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S
--
2.34.1

View File

@ -0,0 +1,54 @@
From cd16901670e12ae1185f2488e74f50ce5d72c5fb Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Wed, 17 Nov 2021 19:40:16 +0100
Subject: [PATCH 048/171] iommu/io-pgtable: Add DART subpage protection support
DART allows to only expose a subpage to the device. While this is an
optional feature on the M1 DARTs the new ones present on the Pro/Max
models require this field in every PTE.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
Signed-off-by: Janne Grunau <j@jannau.net>
Commit-changes: 3
- apply change to io-pgtable-dart.c
---
drivers/iommu/io-pgtable-dart.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
index 0c5222942c65..fa8025c03bb5 100644
--- a/drivers/iommu/io-pgtable-dart.c
+++ b/drivers/iommu/io-pgtable-dart.c
@@ -14,6 +14,7 @@
#define pr_fmt(fmt) "dart io-pgtable: " fmt
#include <linux/atomic.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/io-pgtable.h>
#include <linux/kernel.h>
@@ -63,6 +64,9 @@
/* Calculate the block/page mapping size at level l for pagetable in d. */
#define DART_BLOCK_SIZE(l, d) (1ULL << DART_LVL_SHIFT(l, d))
+#define APPLE_DART_PTE_SUBPAGE_START GENMASK_ULL(63, 52)
+#define APPLE_DART_PTE_SUBPAGE_END GENMASK_ULL(51, 40)
+
#define APPLE_DART1_PADDR_MASK GENMASK_ULL(35, 12)
/* Apple DART1 protection bits */
@@ -140,6 +144,10 @@ static void __dart_init_pte(struct dart_io_pgtable *data,
pte |= APPLE_DART_PTE_VALID;
+ /* subpage protection: always allow access to the entire page */
+ pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_START, 0);
+ pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_END, 0xfff);
+
for (i = 0; i < num_entries; i++)
ptep[i] = pte | paddr_to_iopte(paddr + i * sz, data);
}
--
2.34.1

View File

@ -0,0 +1,158 @@
From 318506bc8e5c558c1df0a964ce2fe112681d3452 Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Tue, 2 Nov 2021 18:10:53 +0100
Subject: [PATCH 049/171] iommu/io-pgtable-dart: Add DART PTE support for t6000
The DARTs present in the M1 Pro/Max/Ultra SoC use a diffent PTE format.
They support a 42bit physical address space by shifting the paddr and
extending its mask inside the PTE.
They also come with mandatory sub-page protection now which we just
configure to always allow access to the entire page. This feature is
already present but optional on the previous DARTs which allows to
unconditionally configure it.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
Co-developed-by: Janne Grunau <j@jannau.net>
Signed-off-by: Janne Grunau <j@jannau.net>
Commit-changes: 2
- add APPLE_DART2 PTE format
Commit-changes: 3
- apply change to io-pgtable-dart.c
- handle pte <> paddr conversion based on the pte format instead of
the output address size
---
drivers/iommu/io-pgtable-dart.c | 51 +++++++++++++++++++++++++++------
drivers/iommu/io-pgtable.c | 1 +
include/linux/io-pgtable.h | 1 +
3 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
index fa8025c03bb5..9c3c2505f3dc 100644
--- a/drivers/iommu/io-pgtable-dart.c
+++ b/drivers/iommu/io-pgtable-dart.c
@@ -68,12 +68,19 @@
#define APPLE_DART_PTE_SUBPAGE_END GENMASK_ULL(51, 40)
#define APPLE_DART1_PADDR_MASK GENMASK_ULL(35, 12)
+#define APPLE_DART2_PADDR_MASK GENMASK_ULL(37, 10)
+#define APPLE_DART2_PADDR_SHIFT (4)
/* Apple DART1 protection bits */
#define APPLE_DART1_PTE_PROT_NO_READ BIT(8)
#define APPLE_DART1_PTE_PROT_NO_WRITE BIT(7)
#define APPLE_DART1_PTE_PROT_SP_DIS BIT(1)
+/* Apple DART2 protection bits */
+#define APPLE_DART2_PTE_PROT_NO_READ BIT(3)
+#define APPLE_DART2_PTE_PROT_NO_WRITE BIT(2)
+#define APPLE_DART2_PTE_PROT_NO_CACHE BIT(1)
+
/* marks PTE as valid */
#define APPLE_DART_PTE_VALID BIT(0)
@@ -101,13 +108,31 @@ static inline bool iopte_leaf(dart_iopte pte, int lvl,
static dart_iopte paddr_to_iopte(phys_addr_t paddr,
struct dart_io_pgtable *data)
{
- return paddr & APPLE_DART1_PADDR_MASK;
+ dart_iopte pte;
+
+ if (data->iop.fmt == APPLE_DART)
+ return paddr & APPLE_DART1_PADDR_MASK;
+
+ /* format is APPLE_DART2 */
+ pte = paddr >> APPLE_DART2_PADDR_SHIFT;
+ pte &= APPLE_DART2_PADDR_MASK;
+
+ return pte;
}
static phys_addr_t iopte_to_paddr(dart_iopte pte,
struct dart_io_pgtable *data)
{
- return pte & APPLE_DART1_PADDR_MASK;
+ u64 paddr;
+
+ if (data->iop.fmt == APPLE_DART)
+ return pte & APPLE_DART1_PADDR_MASK;
+
+ /* format is APPLE_DART2 */
+ paddr = pte & APPLE_DART2_PADDR_MASK;
+ paddr <<= APPLE_DART2_PADDR_SHIFT;
+
+ return paddr;
}
static void *__dart_alloc_pages(size_t size, gfp_t gfp,
@@ -139,7 +164,7 @@ static void __dart_init_pte(struct dart_io_pgtable *data,
size_t sz = DART_BLOCK_SIZE(lvl, data);
int i;
- if (lvl == DART_MAX_LEVELS - 1)
+ if (lvl == DART_MAX_LEVELS - 1 && data->iop.fmt == APPLE_DART)
pte |= APPLE_DART1_PTE_PROT_SP_DIS;
pte |= APPLE_DART_PTE_VALID;
@@ -251,10 +276,20 @@ static dart_iopte dart_prot_to_pte(struct dart_io_pgtable *data,
{
dart_iopte pte = 0;
- if (!(prot & IOMMU_WRITE))
- pte |= APPLE_DART1_PTE_PROT_NO_WRITE;
- if (!(prot & IOMMU_READ))
- pte |= APPLE_DART1_PTE_PROT_NO_READ;
+ if (data->iop.fmt == APPLE_DART) {
+ if (!(prot & IOMMU_WRITE))
+ pte |= APPLE_DART1_PTE_PROT_NO_WRITE;
+ if (!(prot & IOMMU_READ))
+ pte |= APPLE_DART1_PTE_PROT_NO_READ;
+ }
+ if (data->iop.fmt == APPLE_DART2) {
+ if (!(prot & IOMMU_WRITE))
+ pte |= APPLE_DART2_PTE_PROT_NO_WRITE;
+ if (!(prot & IOMMU_READ))
+ pte |= APPLE_DART2_PTE_PROT_NO_READ;
+ if (!(prot & IOMMU_CACHE))
+ pte |= APPLE_DART2_PTE_PROT_NO_CACHE;
+ }
return pte;
}
@@ -536,7 +571,7 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
if (!cfg->coherent_walk)
return NULL;
- if (cfg->oas > 36)
+ if (cfg->oas != 36 && cfg->oas != 42)
return NULL;
data = dart_alloc_pgtable(cfg);
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index 16205ea9272c..49f46e1eabf7 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -23,6 +23,7 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
#endif
#ifdef CONFIG_IOMMU_IO_PGTABLE_DART
[APPLE_DART] = &io_pgtable_apple_dart_init_fns,
+ [APPLE_DART2] = &io_pgtable_apple_dart_init_fns,
#endif
#ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S
[ARM_V7S] = &io_pgtable_arm_v7s_init_fns,
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index 86af6f0a00a2..76b98511cbc8 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -17,6 +17,7 @@ enum io_pgtable_fmt {
ARM_MALI_LPAE,
AMD_IOMMU_V1,
APPLE_DART,
+ APPLE_DART2,
IO_PGTABLE_NUM_FMTS,
};
--
2.34.1

View File

@ -0,0 +1,99 @@
From 69d73a2d8f767b1e1d4ea00fcd8be33f5fc8b7c0 Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Tue, 2 Nov 2021 18:10:52 +0100
Subject: [PATCH 050/171] iommu: dart: Support t6000 variant
The M1 Pro/Max/Ultra SoCs come with a new variant of DART which
supports a larger physical address space with a different PTE format.
Pass through the correct paddr address space size and the PTE format
to the io-pgtable code which will take care of the rest.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
Co-developed-by: Janne Grunau <j@jannau.net>
Signed-off-by: Janne Grunau <j@jannau.net>
Commit-changes: 2
- use APPLE_DART2 PTE format for dart-t6000
Commit-changes: 3
- apply change to io-pgtable-dart.c
---
drivers/iommu/apple-dart.c | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 8af0242a90d9..e5793c0d08b4 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -81,10 +81,16 @@
#define DART_TTBR_VALID BIT(31)
#define DART_TTBR_SHIFT 12
+struct apple_dart_hw {
+ u32 oas;
+ enum io_pgtable_fmt fmt;
+};
+
/*
* Private structure associated with each DART device.
*
* @dev: device struct
+ * @hw: SoC-specific hardware data
* @regs: mapped MMIO region
* @irq: interrupt number, can be shared with other DARTs
* @clks: clocks associated with this DART
@@ -98,6 +104,7 @@
*/
struct apple_dart {
struct device *dev;
+ const struct apple_dart_hw *hw;
void __iomem *regs;
@@ -421,13 +428,13 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
pgtbl_cfg = (struct io_pgtable_cfg){
.pgsize_bitmap = dart->pgsize,
.ias = 32,
- .oas = 36,
+ .oas = dart->hw->oas,
.coherent_walk = 1,
.iommu_dev = dart->dev,
};
dart_domain->pgtbl_ops =
- alloc_io_pgtable_ops(APPLE_DART, &pgtbl_cfg, domain);
+ alloc_io_pgtable_ops(dart->hw->fmt, &pgtbl_cfg, domain);
if (!dart_domain->pgtbl_ops) {
ret = -ENOMEM;
goto done;
@@ -858,6 +865,7 @@ static int apple_dart_probe(struct platform_device *pdev)
return -ENOMEM;
dart->dev = dev;
+ dart->hw = of_device_get_match_data(dev);
spin_lock_init(&dart->lock);
dart->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
@@ -946,8 +954,18 @@ static int apple_dart_remove(struct platform_device *pdev)
return 0;
}
+static const struct apple_dart_hw apple_dart_hw_t8103 = {
+ .oas = 36,
+ .fmt = APPLE_DART,
+};
+static const struct apple_dart_hw apple_dart_hw_t6000 = {
+ .oas = 42,
+ .fmt = APPLE_DART2,
+};
+
static const struct of_device_id apple_dart_of_match[] = {
- { .compatible = "apple,t8103-dart", .data = NULL },
+ { .compatible = "apple,t8103-dart", .data = &apple_dart_hw_t8103 },
+ { .compatible = "apple,t6000-dart", .data = &apple_dart_hw_t6000 },
{},
};
MODULE_DEVICE_TABLE(of, apple_dart_of_match);
--
2.34.1

View File

@ -0,0 +1,91 @@
From 6b1080a482294824b6dfb65501de061a86a1939d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sat, 5 Mar 2022 21:17:10 +0900
Subject: [PATCH 051/171] iommu: dart: Add suspend/resume support
We need to save/restore the TCR/TTBR registers, since they are lost
on power gate.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/iommu/apple-dart.c | 50 ++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index e5793c0d08b4..90aceb6ac774 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -120,6 +120,9 @@ struct apple_dart {
struct iommu_group *sid2group[DART_MAX_STREAMS];
struct iommu_device iommu;
+
+ u32 save_tcr[DART_MAX_STREAMS];
+ u32 save_ttbr[DART_MAX_STREAMS][DART_MAX_TTBR];
};
/*
@@ -963,6 +966,50 @@ static const struct apple_dart_hw apple_dart_hw_t6000 = {
.fmt = APPLE_DART2,
};
+#ifdef CONFIG_PM_SLEEP
+static int apple_dart_suspend(struct device *dev)
+{
+ struct apple_dart *dart = dev_get_drvdata(dev);
+ unsigned int sid, idx;
+
+ for (sid = 0; sid < DART_MAX_STREAMS; sid++) {
+ dart->save_tcr[sid] = readl_relaxed(dart->regs + DART_TCR(sid));
+ for (idx = 0; idx < DART_MAX_TTBR; idx++)
+ dart->save_ttbr[sid][idx] =
+ readl_relaxed(dart->regs + DART_TTBR(sid, idx));
+ }
+
+ return 0;
+}
+
+static int apple_dart_resume(struct device *dev)
+{
+ struct apple_dart *dart = dev_get_drvdata(dev);
+ unsigned int sid, idx;
+ int ret;
+
+ ret = apple_dart_hw_reset(dart);
+ if (ret) {
+ dev_err(dev, "Failed to reset DART on resume\n");
+ return ret;
+ }
+
+ for (sid = 0; sid < DART_MAX_STREAMS; sid++) {
+ for (idx = 0; idx < DART_MAX_TTBR; idx++)
+ writel_relaxed(dart->save_ttbr[sid][idx],
+ dart->regs + DART_TTBR(sid, idx));
+ writel_relaxed(dart->save_tcr[sid], dart->regs + DART_TCR(sid));
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops apple_dart_pm_ops = {
+ .suspend = apple_dart_suspend,
+ .resume = apple_dart_resume,
+};
+#endif
+
static const struct of_device_id apple_dart_of_match[] = {
{ .compatible = "apple,t8103-dart", .data = &apple_dart_hw_t8103 },
{ .compatible = "apple,t6000-dart", .data = &apple_dart_hw_t6000 },
@@ -975,6 +1022,9 @@ static struct platform_driver apple_dart_driver = {
.name = "apple-dart",
.of_match_table = apple_dart_of_match,
.suppress_bind_attrs = true,
+#ifdef CONFIG_PM_SLEEP
+ .pm = &apple_dart_pm_ops,
+#endif
},
.probe = apple_dart_probe,
.remove = apple_dart_remove,
--
2.34.1

View File

@ -0,0 +1,359 @@
From 82d7ff6fe9af1e8cd39bce1d46a679074b8d7749 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 28 Jun 2022 01:07:20 +0900
Subject: [PATCH 052/171] iommu: dart: Support >64 stream IDs
T8110 DARTs have up to 256 SIDs, so we need to switch to a bitmap to
handle them properly.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/iommu/apple-dart.c | 113 +++++++++++++++++++++++--------------
1 file changed, 70 insertions(+), 43 deletions(-)
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 90aceb6ac774..39e6f86dd525 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -33,11 +33,10 @@
#include <linux/swab.h>
#include <linux/types.h>
-#define DART_MAX_STREAMS 16
+#define DART_MAX_STREAMS 256
#define DART_MAX_TTBR 4
#define MAX_DARTS_PER_DEVICE 2
-#define DART_STREAM_ALL 0xffff
#define DART_PARAMS1 0x00
#define DART_PARAMS_PAGE_SHIFT GENMASK(27, 24)
@@ -84,6 +83,8 @@
struct apple_dart_hw {
u32 oas;
enum io_pgtable_fmt fmt;
+
+ int max_sid_count;
};
/*
@@ -115,6 +116,7 @@ struct apple_dart {
spinlock_t lock;
u32 pgsize;
+ u32 num_streams;
u32 supports_bypass : 1;
u32 force_bypass : 1;
@@ -142,11 +144,11 @@ struct apple_dart {
*/
struct apple_dart_stream_map {
struct apple_dart *dart;
- unsigned long sidmap;
+ DECLARE_BITMAP(sidmap, DART_MAX_STREAMS);
};
struct apple_dart_atomic_stream_map {
struct apple_dart *dart;
- atomic64_t sidmap;
+ atomic_long_t sidmap[BITS_TO_LONGS(DART_MAX_STREAMS)];
};
/*
@@ -204,50 +206,55 @@ static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom)
static void
apple_dart_hw_enable_translation(struct apple_dart_stream_map *stream_map)
{
+ struct apple_dart *dart = stream_map->dart;
int sid;
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
writel(DART_TCR_TRANSLATE_ENABLE,
- stream_map->dart->regs + DART_TCR(sid));
+ dart->regs + DART_TCR(sid));
}
static void apple_dart_hw_disable_dma(struct apple_dart_stream_map *stream_map)
{
+ struct apple_dart *dart = stream_map->dart;
int sid;
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
- writel(0, stream_map->dart->regs + DART_TCR(sid));
+ for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
+ writel(0, dart->regs + DART_TCR(sid));
}
static void
apple_dart_hw_enable_bypass(struct apple_dart_stream_map *stream_map)
{
+ struct apple_dart *dart = stream_map->dart;
int sid;
WARN_ON(!stream_map->dart->supports_bypass);
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
writel(DART_TCR_BYPASS0_ENABLE | DART_TCR_BYPASS1_ENABLE,
- stream_map->dart->regs + DART_TCR(sid));
+ dart->regs + DART_TCR(sid));
}
static void apple_dart_hw_set_ttbr(struct apple_dart_stream_map *stream_map,
u8 idx, phys_addr_t paddr)
{
+ struct apple_dart *dart = stream_map->dart;
int sid;
WARN_ON(paddr & ((1 << DART_TTBR_SHIFT) - 1));
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
writel(DART_TTBR_VALID | (paddr >> DART_TTBR_SHIFT),
- stream_map->dart->regs + DART_TTBR(sid, idx));
+ dart->regs + DART_TTBR(sid, idx));
}
static void apple_dart_hw_clear_ttbr(struct apple_dart_stream_map *stream_map,
u8 idx)
{
+ struct apple_dart *dart = stream_map->dart;
int sid;
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
- writel(0, stream_map->dart->regs + DART_TTBR(sid, idx));
+ for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
+ writel(0, dart->regs + DART_TTBR(sid, idx));
}
static void
@@ -269,7 +276,7 @@ apple_dart_hw_stream_command(struct apple_dart_stream_map *stream_map,
spin_lock_irqsave(&stream_map->dart->lock, flags);
- writel(stream_map->sidmap, stream_map->dart->regs + DART_STREAM_SELECT);
+ writel(stream_map->sidmap[0], stream_map->dart->regs + DART_STREAM_SELECT);
writel(command, stream_map->dart->regs + DART_STREAM_COMMAND);
ret = readl_poll_timeout_atomic(
@@ -282,7 +289,7 @@ apple_dart_hw_stream_command(struct apple_dart_stream_map *stream_map,
if (ret) {
dev_err(stream_map->dart->dev,
"busy bit did not clear after command %x for streams %lx\n",
- command, stream_map->sidmap);
+ command, stream_map->sidmap[0]);
return ret;
}
@@ -300,6 +307,7 @@ static int apple_dart_hw_reset(struct apple_dart *dart)
{
u32 config;
struct apple_dart_stream_map stream_map;
+ int i;
config = readl(dart->regs + DART_CONFIG);
if (config & DART_CONFIG_LOCK) {
@@ -309,12 +317,14 @@ static int apple_dart_hw_reset(struct apple_dart *dart)
}
stream_map.dart = dart;
- stream_map.sidmap = DART_STREAM_ALL;
+ bitmap_zero(stream_map.sidmap, DART_MAX_STREAMS);
+ bitmap_set(stream_map.sidmap, 0, dart->num_streams);
apple_dart_hw_disable_dma(&stream_map);
apple_dart_hw_clear_all_ttbrs(&stream_map);
/* enable all streams globally since TCR is used to control isolation */
- writel(DART_STREAM_ALL, dart->regs + DART_STREAMS_ENABLE);
+ for (i = 0; i < BITS_TO_U32(dart->num_streams); i++)
+ writel(U32_MAX, dart->regs + DART_STREAMS_ENABLE);
/* clear any pending errors before the interrupt is unmasked */
writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR);
@@ -324,13 +334,16 @@ static int apple_dart_hw_reset(struct apple_dart *dart)
static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
{
- int i;
+ int i, j;
struct apple_dart_atomic_stream_map *domain_stream_map;
struct apple_dart_stream_map stream_map;
for_each_stream_map(i, domain, domain_stream_map) {
stream_map.dart = domain_stream_map->dart;
- stream_map.sidmap = atomic64_read(&domain_stream_map->sidmap);
+
+ for (j = 0; j < BITS_TO_LONGS(stream_map.dart->num_streams); j++)
+ stream_map.sidmap[j] = atomic64_read(&domain_stream_map->sidmap[j]);
+
apple_dart_hw_invalidate_tlb(&stream_map);
}
}
@@ -415,7 +428,7 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
struct apple_dart *dart = cfg->stream_maps[0].dart;
struct io_pgtable_cfg pgtbl_cfg;
int ret = 0;
- int i;
+ int i, j;
mutex_lock(&dart_domain->init_lock);
@@ -424,8 +437,9 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
dart_domain->stream_maps[i].dart = cfg->stream_maps[i].dart;
- atomic64_set(&dart_domain->stream_maps[i].sidmap,
- cfg->stream_maps[i].sidmap);
+ for (j = 0; j < BITS_TO_LONGS(dart->num_streams); j++)
+ atomic64_set(&dart_domain->stream_maps[i].sidmap[j],
+ cfg->stream_maps[i].sidmap[j]);
}
pgtbl_cfg = (struct io_pgtable_cfg){
@@ -460,7 +474,7 @@ apple_dart_mod_streams(struct apple_dart_atomic_stream_map *domain_maps,
struct apple_dart_stream_map *master_maps,
bool add_streams)
{
- int i;
+ int i, j;
for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
if (domain_maps[i].dart != master_maps[i].dart)
@@ -470,12 +484,14 @@ apple_dart_mod_streams(struct apple_dart_atomic_stream_map *domain_maps,
for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
if (!domain_maps[i].dart)
break;
- if (add_streams)
- atomic64_or(master_maps[i].sidmap,
- &domain_maps[i].sidmap);
- else
- atomic64_and(~master_maps[i].sidmap,
- &domain_maps[i].sidmap);
+ for (j = 0; j < BITS_TO_LONGS(domain_maps[i].dart->num_streams); j++) {
+ if (add_streams)
+ atomic64_or(master_maps[i].sidmap[j],
+ &domain_maps[i].sidmap[j]);
+ else
+ atomic64_and(~master_maps[i].sidmap[j],
+ &domain_maps[i].sidmap[j]);
+ }
}
return 0;
@@ -642,14 +658,14 @@ static int apple_dart_of_xlate(struct device *dev, struct of_phandle_args *args)
for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
if (cfg->stream_maps[i].dart == dart) {
- cfg->stream_maps[i].sidmap |= 1 << sid;
+ set_bit(sid, cfg->stream_maps[i].sidmap);
return 0;
}
}
for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
if (!cfg->stream_maps[i].dart) {
cfg->stream_maps[i].dart = dart;
- cfg->stream_maps[i].sidmap = 1 << sid;
+ set_bit(sid, cfg->stream_maps[i].sidmap);
return 0;
}
}
@@ -668,7 +684,7 @@ static void apple_dart_release_group(void *iommu_data)
mutex_lock(&apple_dart_groups_lock);
for_each_stream_map(i, group_master_cfg, stream_map)
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ for_each_set_bit(sid, stream_map->sidmap, stream_map->dart->num_streams)
stream_map->dart->sid2group[sid] = NULL;
kfree(iommu_data);
@@ -687,7 +703,7 @@ static struct iommu_group *apple_dart_device_group(struct device *dev)
mutex_lock(&apple_dart_groups_lock);
for_each_stream_map(i, cfg, stream_map) {
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS) {
+ for_each_set_bit(sid, stream_map->sidmap, stream_map->dart->num_streams) {
struct iommu_group *stream_group =
stream_map->dart->sid2group[sid];
@@ -726,7 +742,7 @@ static struct iommu_group *apple_dart_device_group(struct device *dev)
apple_dart_release_group);
for_each_stream_map(i, cfg, stream_map)
- for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ for_each_set_bit(sid, stream_map->sidmap, stream_map->dart->num_streams)
stream_map->dart->sid2group[sid] = group;
res = group;
@@ -893,16 +909,25 @@ static int apple_dart_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = apple_dart_hw_reset(dart);
- if (ret)
- goto err_clk_disable;
-
dart_params[0] = readl(dart->regs + DART_PARAMS1);
dart_params[1] = readl(dart->regs + DART_PARAMS2);
dart->pgsize = 1 << FIELD_GET(DART_PARAMS_PAGE_SHIFT, dart_params[0]);
dart->supports_bypass = dart_params[1] & DART_PARAMS_BYPASS_SUPPORT;
+
+ dart->num_streams = dart->hw->max_sid_count;
+
+ if (dart->num_streams > DART_MAX_STREAMS) {
+ dev_err(&pdev->dev, "Too many streams (%d > %d)\n",
+ dart->num_streams, DART_MAX_STREAMS);
+ goto err_clk_disable;
+ }
+
dart->force_bypass = dart->pgsize > PAGE_SIZE;
+ ret = apple_dart_hw_reset(dart);
+ if (ret)
+ goto err_clk_disable;
+
ret = request_irq(dart->irq, apple_dart_irq, IRQF_SHARED,
"apple-dart fault handler", dart);
if (ret)
@@ -925,8 +950,8 @@ static int apple_dart_probe(struct platform_device *pdev)
dev_info(
&pdev->dev,
- "DART [pagesize %x, bypass support: %d, bypass forced: %d] initialized\n",
- dart->pgsize, dart->supports_bypass, dart->force_bypass);
+ "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d] initialized\n",
+ dart->pgsize, dart->num_streams, dart->supports_bypass, dart->force_bypass);
return 0;
err_sysfs_remove:
@@ -960,10 +985,12 @@ static int apple_dart_remove(struct platform_device *pdev)
static const struct apple_dart_hw apple_dart_hw_t8103 = {
.oas = 36,
.fmt = APPLE_DART,
+ .max_sid_count = 16,
};
static const struct apple_dart_hw apple_dart_hw_t6000 = {
.oas = 42,
.fmt = APPLE_DART2,
+ .max_sid_count = 16,
};
#ifdef CONFIG_PM_SLEEP
@@ -972,7 +999,7 @@ static int apple_dart_suspend(struct device *dev)
struct apple_dart *dart = dev_get_drvdata(dev);
unsigned int sid, idx;
- for (sid = 0; sid < DART_MAX_STREAMS; sid++) {
+ for (sid = 0; sid < dart->num_streams; sid++) {
dart->save_tcr[sid] = readl_relaxed(dart->regs + DART_TCR(sid));
for (idx = 0; idx < DART_MAX_TTBR; idx++)
dart->save_ttbr[sid][idx] =
@@ -994,7 +1021,7 @@ static int apple_dart_resume(struct device *dev)
return ret;
}
- for (sid = 0; sid < DART_MAX_STREAMS; sid++) {
+ for (sid = 0; sid < dart->num_streams; sid++) {
for (idx = 0; idx < DART_MAX_TTBR; idx++)
writel_relaxed(dart->save_ttbr[sid][idx],
dart->regs + DART_TTBR(sid, idx));
--
2.34.1

View File

@ -0,0 +1,119 @@
From 180390038e38222406314cb6eea2182a7817b459 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 28 Jun 2022 01:16:28 +0900
Subject: [PATCH 053/171] iommu: dart: Support a variable number of TTBRs per
stream
T8110 only has one TTBR per stream, so un-hardcode that.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/iommu/apple-dart.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 39e6f86dd525..9f2751c12070 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -76,15 +76,21 @@
#define DART_TCR_BYPASS0_ENABLE BIT(8)
#define DART_TCR_BYPASS1_ENABLE BIT(12)
-#define DART_TTBR(sid, idx) (0x200 + 16 * (sid) + 4 * (idx))
#define DART_TTBR_VALID BIT(31)
#define DART_TTBR_SHIFT 12
+#define DART_TTBR(dart, sid, idx) (0x200 + \
+ (((dart)->hw->ttbr_count * (sid)) << 2) + \
+ ((idx) << 2))
+
+
struct apple_dart_hw {
u32 oas;
enum io_pgtable_fmt fmt;
int max_sid_count;
+
+ int ttbr_count;
};
/*
@@ -244,7 +250,7 @@ static void apple_dart_hw_set_ttbr(struct apple_dart_stream_map *stream_map,
WARN_ON(paddr & ((1 << DART_TTBR_SHIFT) - 1));
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
writel(DART_TTBR_VALID | (paddr >> DART_TTBR_SHIFT),
- dart->regs + DART_TTBR(sid, idx));
+ dart->regs + DART_TTBR(dart, sid, idx));
}
static void apple_dart_hw_clear_ttbr(struct apple_dart_stream_map *stream_map,
@@ -254,7 +260,7 @@ static void apple_dart_hw_clear_ttbr(struct apple_dart_stream_map *stream_map,
int sid;
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
- writel(0, dart->regs + DART_TTBR(sid, idx));
+ writel(0, dart->regs + DART_TTBR(dart, sid, idx));
}
static void
@@ -262,7 +268,7 @@ apple_dart_hw_clear_all_ttbrs(struct apple_dart_stream_map *stream_map)
{
int i;
- for (i = 0; i < DART_MAX_TTBR; ++i)
+ for (i = 0; i < stream_map->dart->hw->ttbr_count; ++i)
apple_dart_hw_clear_ttbr(stream_map, i);
}
@@ -414,7 +420,7 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
for (i = 0; i < pgtbl_cfg->apple_dart_cfg.n_ttbrs; ++i)
apple_dart_hw_set_ttbr(stream_map, i,
pgtbl_cfg->apple_dart_cfg.ttbr[i]);
- for (; i < DART_MAX_TTBR; ++i)
+ for (; i < stream_map->dart->hw->ttbr_count; ++i)
apple_dart_hw_clear_ttbr(stream_map, i);
apple_dart_hw_enable_translation(stream_map);
@@ -986,11 +992,15 @@ static const struct apple_dart_hw apple_dart_hw_t8103 = {
.oas = 36,
.fmt = APPLE_DART,
.max_sid_count = 16,
+
+ .ttbr_count = 4,
};
static const struct apple_dart_hw apple_dart_hw_t6000 = {
.oas = 42,
.fmt = APPLE_DART2,
.max_sid_count = 16,
+
+ .ttbr_count = 4,
};
#ifdef CONFIG_PM_SLEEP
@@ -1001,9 +1011,9 @@ static int apple_dart_suspend(struct device *dev)
for (sid = 0; sid < dart->num_streams; sid++) {
dart->save_tcr[sid] = readl_relaxed(dart->regs + DART_TCR(sid));
- for (idx = 0; idx < DART_MAX_TTBR; idx++)
+ for (idx = 0; idx < dart->hw->ttbr_count; idx++)
dart->save_ttbr[sid][idx] =
- readl_relaxed(dart->regs + DART_TTBR(sid, idx));
+ readl_relaxed(dart->regs + DART_TTBR(dart, sid, idx));
}
return 0;
@@ -1022,9 +1032,9 @@ static int apple_dart_resume(struct device *dev)
}
for (sid = 0; sid < dart->num_streams; sid++) {
- for (idx = 0; idx < DART_MAX_TTBR; idx++)
+ for (idx = 0; idx < dart->hw->ttbr_count; idx++)
writel_relaxed(dart->save_ttbr[sid][idx],
- dart->regs + DART_TTBR(sid, idx));
+ dart->regs + DART_TTBR(dart, sid, idx));
writel_relaxed(dart->save_tcr[sid], dart->regs + DART_TCR(sid));
}
--
2.34.1

View File

@ -0,0 +1,43 @@
From 85ab83f3cc7a4f0bfff8edd1662c2d98cda766a1 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 28 Jun 2022 01:20:52 +0900
Subject: [PATCH 054/171] iommu: dart: Fix DART_PARAMS1/2 bit define names
They didn't have the PARAMS reg index in them, but they should.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/iommu/apple-dart.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 9f2751c12070..e6b641037429 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -39,10 +39,10 @@
#define DART_PARAMS1 0x00
-#define DART_PARAMS_PAGE_SHIFT GENMASK(27, 24)
+#define DART_PARAMS1_PAGE_SHIFT GENMASK(27, 24)
#define DART_PARAMS2 0x04
-#define DART_PARAMS_BYPASS_SUPPORT BIT(0)
+#define DART_PARAMS2_BYPASS_SUPPORT BIT(0)
#define DART_STREAM_COMMAND 0x20
#define DART_STREAM_COMMAND_BUSY BIT(2)
@@ -917,8 +917,8 @@ static int apple_dart_probe(struct platform_device *pdev)
dart_params[0] = readl(dart->regs + DART_PARAMS1);
dart_params[1] = readl(dart->regs + DART_PARAMS2);
- dart->pgsize = 1 << FIELD_GET(DART_PARAMS_PAGE_SHIFT, dart_params[0]);
- dart->supports_bypass = dart_params[1] & DART_PARAMS_BYPASS_SUPPORT;
+ dart->pgsize = 1 << FIELD_GET(DART_PARAMS1_PAGE_SHIFT, dart_params[0]);
+ dart->supports_bypass = dart_params[1] & DART_PARAMS2_BYPASS_SUPPORT;
dart->num_streams = dart->hw->max_sid_count;
--
2.34.1

View File

@ -0,0 +1,394 @@
From fbe7133a9b1e71ee18185dd7c67712c909515bfd Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 28 Jun 2022 01:27:28 +0900
Subject: [PATCH 055/171] iommu: dart: Support different variants with
different registers
T8110 has a new register layout. To accomodate this, first move all the
register offsets to the hw structure, and rename all the existing
registers to DART_T8020_*.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/iommu/apple-dart.c | 188 ++++++++++++++++++++++++-------------
1 file changed, 125 insertions(+), 63 deletions(-)
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index e6b641037429..3f89db3f8e99 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -37,6 +37,7 @@
#define DART_MAX_TTBR 4
#define MAX_DARTS_PER_DEVICE 2
+/* Common registers */
#define DART_PARAMS1 0x00
#define DART_PARAMS1_PAGE_SHIFT GENMASK(27, 24)
@@ -44,52 +45,79 @@
#define DART_PARAMS2 0x04
#define DART_PARAMS2_BYPASS_SUPPORT BIT(0)
-#define DART_STREAM_COMMAND 0x20
-#define DART_STREAM_COMMAND_BUSY BIT(2)
-#define DART_STREAM_COMMAND_INVALIDATE BIT(20)
+/* T8020/T6000 registers */
-#define DART_STREAM_SELECT 0x34
+#define DART_T8020_STREAM_COMMAND 0x20
+#define DART_T8020_STREAM_COMMAND_BUSY BIT(2)
+#define DART_T8020_STREAM_COMMAND_INVALIDATE BIT(20)
-#define DART_ERROR 0x40
-#define DART_ERROR_STREAM GENMASK(27, 24)
-#define DART_ERROR_CODE GENMASK(11, 0)
-#define DART_ERROR_FLAG BIT(31)
+#define DART_T8020_STREAM_SELECT 0x34
-#define DART_ERROR_READ_FAULT BIT(4)
-#define DART_ERROR_WRITE_FAULT BIT(3)
-#define DART_ERROR_NO_PTE BIT(2)
-#define DART_ERROR_NO_PMD BIT(1)
-#define DART_ERROR_NO_TTBR BIT(0)
+#define DART_T8020_ERROR 0x40
+#define DART_T8020_ERROR_STREAM GENMASK(27, 24)
+#define DART_T8020_ERROR_CODE GENMASK(11, 0)
+#define DART_T8020_ERROR_FLAG BIT(31)
-#define DART_CONFIG 0x60
-#define DART_CONFIG_LOCK BIT(15)
+#define DART_T8020_ERROR_READ_FAULT BIT(4)
+#define DART_T8020_ERROR_WRITE_FAULT BIT(3)
+#define DART_T8020_ERROR_NO_PTE BIT(2)
+#define DART_T8020_ERROR_NO_PMD BIT(1)
+#define DART_T8020_ERROR_NO_TTBR BIT(0)
+
+#define DART_T8020_CONFIG 0x60
+#define DART_T8020_CONFIG_LOCK BIT(15)
#define DART_STREAM_COMMAND_BUSY_TIMEOUT 100
-#define DART_ERROR_ADDR_HI 0x54
-#define DART_ERROR_ADDR_LO 0x50
+#define DART_T8020_ERROR_ADDR_HI 0x54
+#define DART_T8020_ERROR_ADDR_LO 0x50
+
+#define DART_T8020_STREAMS_ENABLE 0xfc
-#define DART_STREAMS_ENABLE 0xfc
+#define DART_T8020_TCR 0x100
+#define DART_T8020_TCR_TRANSLATE_ENABLE BIT(7)
+#define DART_T8020_TCR_BYPASS_DART BIT(8)
+#define DART_T8020_TCR_BYPASS_DAPF BIT(12)
-#define DART_TCR(sid) (0x100 + 4 * (sid))
-#define DART_TCR_TRANSLATE_ENABLE BIT(7)
-#define DART_TCR_BYPASS0_ENABLE BIT(8)
-#define DART_TCR_BYPASS1_ENABLE BIT(12)
+#define DART_T8020_TTBR 0x200
+#define DART_T8020_TTBR_VALID BIT(31)
+#define DART_T8020_TTBR_ADDR_OFF 0
+#define DART_T8020_TTBR_SHIFT 12
-#define DART_TTBR_VALID BIT(31)
-#define DART_TTBR_SHIFT 12
+#define DART_TCR(dart, sid) ((dart)->hw->tcr + ((sid) << 2))
-#define DART_TTBR(dart, sid, idx) (0x200 + \
+#define DART_TTBR(dart, sid, idx) ((dart)->hw->ttbr + \
(((dart)->hw->ttbr_count * (sid)) << 2) + \
((idx) << 2))
+struct apple_dart_stream_map;
struct apple_dart_hw {
+ irqreturn_t (*irq_handler)(int irq, void *dev);
+ int (*invalidate_tlb)(struct apple_dart_stream_map *stream_map);
+
u32 oas;
enum io_pgtable_fmt fmt;
int max_sid_count;
+ u64 lock;
+ u64 lock_bit;
+
+ u64 error;
+
+ u64 enable_streams;
+ u64 disable_streams;
+
+ u64 tcr;
+ u64 tcr_enabled;
+ u64 tcr_disabled;
+ u64 tcr_bypass;
+
+ u64 ttbr;
+ u64 ttbr_valid;
+ u64 ttbr_addr_off;
+ u64 ttbr_shift;
int ttbr_count;
};
@@ -216,8 +244,7 @@ apple_dart_hw_enable_translation(struct apple_dart_stream_map *stream_map)
int sid;
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
- writel(DART_TCR_TRANSLATE_ENABLE,
- dart->regs + DART_TCR(sid));
+ writel(dart->hw->tcr_enabled, dart->regs + DART_TCR(dart, sid));
}
static void apple_dart_hw_disable_dma(struct apple_dart_stream_map *stream_map)
@@ -226,7 +253,7 @@ static void apple_dart_hw_disable_dma(struct apple_dart_stream_map *stream_map)
int sid;
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
- writel(0, dart->regs + DART_TCR(sid));
+ writel(dart->hw->tcr_disabled, dart->regs + DART_TCR(dart, sid));
}
static void
@@ -237,8 +264,8 @@ apple_dart_hw_enable_bypass(struct apple_dart_stream_map *stream_map)
WARN_ON(!stream_map->dart->supports_bypass);
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
- writel(DART_TCR_BYPASS0_ENABLE | DART_TCR_BYPASS1_ENABLE,
- dart->regs + DART_TCR(sid));
+ writel(dart->hw->tcr_bypass,
+ dart->regs + DART_TCR(dart, sid));
}
static void apple_dart_hw_set_ttbr(struct apple_dart_stream_map *stream_map,
@@ -247,9 +274,10 @@ static void apple_dart_hw_set_ttbr(struct apple_dart_stream_map *stream_map,
struct apple_dart *dart = stream_map->dart;
int sid;
- WARN_ON(paddr & ((1 << DART_TTBR_SHIFT) - 1));
+ WARN_ON(paddr & ((1 << dart->hw->ttbr_shift) - 1));
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
- writel(DART_TTBR_VALID | (paddr >> DART_TTBR_SHIFT),
+ writel(dart->hw->ttbr_valid |
+ (paddr >> dart->hw->ttbr_shift) << dart->hw->ttbr_addr_off,
dart->regs + DART_TTBR(dart, sid, idx));
}
@@ -273,7 +301,7 @@ apple_dart_hw_clear_all_ttbrs(struct apple_dart_stream_map *stream_map)
}
static int
-apple_dart_hw_stream_command(struct apple_dart_stream_map *stream_map,
+apple_dart_t8020_hw_stream_command(struct apple_dart_stream_map *stream_map,
u32 command)
{
unsigned long flags;
@@ -282,12 +310,12 @@ apple_dart_hw_stream_command(struct apple_dart_stream_map *stream_map,
spin_lock_irqsave(&stream_map->dart->lock, flags);
- writel(stream_map->sidmap[0], stream_map->dart->regs + DART_STREAM_SELECT);
- writel(command, stream_map->dart->regs + DART_STREAM_COMMAND);
+ writel(stream_map->sidmap[0], stream_map->dart->regs + DART_T8020_STREAM_SELECT);
+ writel(command, stream_map->dart->regs + DART_T8020_STREAM_COMMAND);
ret = readl_poll_timeout_atomic(
- stream_map->dart->regs + DART_STREAM_COMMAND, command_reg,
- !(command_reg & DART_STREAM_COMMAND_BUSY), 1,
+ stream_map->dart->regs + DART_T8020_STREAM_COMMAND, command_reg,
+ !(command_reg & DART_T8020_STREAM_COMMAND_BUSY), 1,
DART_STREAM_COMMAND_BUSY_TIMEOUT);
spin_unlock_irqrestore(&stream_map->dart->lock, flags);
@@ -303,10 +331,10 @@ apple_dart_hw_stream_command(struct apple_dart_stream_map *stream_map,
}
static int
-apple_dart_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
+apple_dart_t8020_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
{
- return apple_dart_hw_stream_command(stream_map,
- DART_STREAM_COMMAND_INVALIDATE);
+ return apple_dart_t8020_hw_stream_command(
+ stream_map, DART_T8020_STREAM_COMMAND_INVALIDATE);
}
static int apple_dart_hw_reset(struct apple_dart *dart)
@@ -315,8 +343,8 @@ static int apple_dart_hw_reset(struct apple_dart *dart)
struct apple_dart_stream_map stream_map;
int i;
- config = readl(dart->regs + DART_CONFIG);
- if (config & DART_CONFIG_LOCK) {
+ config = readl(dart->regs + dart->hw->lock);
+ if (config & dart->hw->lock_bit) {
dev_err(dart->dev, "DART is locked down until reboot: %08x\n",
config);
return -EINVAL;
@@ -330,12 +358,12 @@ static int apple_dart_hw_reset(struct apple_dart *dart)
/* enable all streams globally since TCR is used to control isolation */
for (i = 0; i < BITS_TO_U32(dart->num_streams); i++)
- writel(U32_MAX, dart->regs + DART_STREAMS_ENABLE);
+ writel(U32_MAX, dart->regs + dart->hw->enable_streams);
/* clear any pending errors before the interrupt is unmasked */
- writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR);
+ writel(readl(dart->regs + dart->hw->error), dart->regs + dart->hw->error);
- return apple_dart_hw_invalidate_tlb(&stream_map);
+ return dart->hw->invalidate_tlb(&stream_map);
}
static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
@@ -350,7 +378,7 @@ static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
for (j = 0; j < BITS_TO_LONGS(stream_map.dart->num_streams); j++)
stream_map.sidmap[j] = atomic64_read(&domain_stream_map->sidmap[j]);
- apple_dart_hw_invalidate_tlb(&stream_map);
+ stream_map.dart->hw->invalidate_tlb(&stream_map);
}
}
@@ -424,7 +452,7 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
apple_dart_hw_clear_ttbr(stream_map, i);
apple_dart_hw_enable_translation(stream_map);
- apple_dart_hw_invalidate_tlb(stream_map);
+ stream_map->dart->hw->invalidate_tlb(stream_map);
}
static int apple_dart_finalize_domain(struct iommu_domain *domain,
@@ -819,30 +847,30 @@ static const struct iommu_ops apple_dart_iommu_ops = {
}
};
-static irqreturn_t apple_dart_irq(int irq, void *dev)
+static irqreturn_t apple_dart_t8020_irq(int irq, void *dev)
{
struct apple_dart *dart = dev;
const char *fault_name = NULL;
- u32 error = readl(dart->regs + DART_ERROR);
- u32 error_code = FIELD_GET(DART_ERROR_CODE, error);
- u32 addr_lo = readl(dart->regs + DART_ERROR_ADDR_LO);
- u32 addr_hi = readl(dart->regs + DART_ERROR_ADDR_HI);
+ u32 error = readl(dart->regs + DART_T8020_ERROR);
+ u32 error_code = FIELD_GET(DART_T8020_ERROR_CODE, error);
+ u32 addr_lo = readl(dart->regs + DART_T8020_ERROR_ADDR_LO);
+ u32 addr_hi = readl(dart->regs + DART_T8020_ERROR_ADDR_HI);
u64 addr = addr_lo | (((u64)addr_hi) << 32);
- u8 stream_idx = FIELD_GET(DART_ERROR_STREAM, error);
+ u8 stream_idx = FIELD_GET(DART_T8020_ERROR_STREAM, error);
- if (!(error & DART_ERROR_FLAG))
+ if (!(error & DART_T8020_ERROR_FLAG))
return IRQ_NONE;
/* there should only be a single bit set but let's use == to be sure */
- if (error_code == DART_ERROR_READ_FAULT)
+ if (error_code == DART_T8020_ERROR_READ_FAULT)
fault_name = "READ FAULT";
- else if (error_code == DART_ERROR_WRITE_FAULT)
+ else if (error_code == DART_T8020_ERROR_WRITE_FAULT)
fault_name = "WRITE FAULT";
- else if (error_code == DART_ERROR_NO_PTE)
+ else if (error_code == DART_T8020_ERROR_NO_PTE)
fault_name = "NO PTE FOR IOVA";
- else if (error_code == DART_ERROR_NO_PMD)
+ else if (error_code == DART_T8020_ERROR_NO_PMD)
fault_name = "NO PMD FOR IOVA";
- else if (error_code == DART_ERROR_NO_TTBR)
+ else if (error_code == DART_T8020_ERROR_NO_TTBR)
fault_name = "NO TTBR FOR IOVA";
else
fault_name = "unknown";
@@ -852,7 +880,7 @@ static irqreturn_t apple_dart_irq(int irq, void *dev)
"translation fault: status:0x%x stream:%d code:0x%x (%s) at 0x%llx",
error, stream_idx, error_code, fault_name, addr);
- writel(error, dart->regs + DART_ERROR);
+ writel(error, dart->regs + DART_T8020_ERROR);
return IRQ_HANDLED;
}
@@ -934,7 +962,7 @@ static int apple_dart_probe(struct platform_device *pdev)
if (ret)
goto err_clk_disable;
- ret = request_irq(dart->irq, apple_dart_irq, IRQF_SHARED,
+ ret = request_irq(dart->irq, dart->hw->irq_handler, IRQF_SHARED,
"apple-dart fault handler", dart);
if (ret)
goto err_clk_disable;
@@ -989,17 +1017,51 @@ static int apple_dart_remove(struct platform_device *pdev)
}
static const struct apple_dart_hw apple_dart_hw_t8103 = {
+ .irq_handler = apple_dart_t8020_irq,
+ .invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
.oas = 36,
.fmt = APPLE_DART,
.max_sid_count = 16,
+ .enable_streams = DART_T8020_STREAMS_ENABLE,
+ .lock = DART_T8020_CONFIG,
+ .lock_bit = DART_T8020_CONFIG_LOCK,
+
+ .error = DART_T8020_ERROR,
+
+ .tcr = DART_T8020_TCR,
+ .tcr_enabled = DART_T8020_TCR_TRANSLATE_ENABLE,
+ .tcr_disabled = 0,
+ .tcr_bypass = DART_T8020_TCR_BYPASS_DAPF | DART_T8020_TCR_BYPASS_DART,
+
+ .ttbr = DART_T8020_TTBR,
+ .ttbr_valid = DART_T8020_TTBR_VALID,
+ .ttbr_addr_off = DART_T8020_TTBR_ADDR_OFF,
+ .ttbr_shift = DART_T8020_TTBR_SHIFT,
.ttbr_count = 4,
};
static const struct apple_dart_hw apple_dart_hw_t6000 = {
+ .irq_handler = apple_dart_t8020_irq,
+ .invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
.oas = 42,
.fmt = APPLE_DART2,
.max_sid_count = 16,
+ .enable_streams = DART_T8020_STREAMS_ENABLE,
+ .lock = DART_T8020_CONFIG,
+ .lock_bit = DART_T8020_CONFIG_LOCK,
+
+ .error = DART_T8020_ERROR,
+
+ .tcr = DART_T8020_TCR,
+ .tcr_enabled = DART_T8020_TCR_TRANSLATE_ENABLE,
+ .tcr_disabled = 0,
+ .tcr_bypass = DART_T8020_TCR_BYPASS_DAPF | DART_T8020_TCR_BYPASS_DART,
+
+ .ttbr = DART_T8020_TTBR,
+ .ttbr_valid = DART_T8020_TTBR_VALID,
+ .ttbr_addr_off = DART_T8020_TTBR_ADDR_OFF,
+ .ttbr_shift = DART_T8020_TTBR_SHIFT,
.ttbr_count = 4,
};
@@ -1010,7 +1072,7 @@ static int apple_dart_suspend(struct device *dev)
unsigned int sid, idx;
for (sid = 0; sid < dart->num_streams; sid++) {
- dart->save_tcr[sid] = readl_relaxed(dart->regs + DART_TCR(sid));
+ dart->save_tcr[sid] = readl_relaxed(dart->regs + DART_TCR(dart, sid));
for (idx = 0; idx < dart->hw->ttbr_count; idx++)
dart->save_ttbr[sid][idx] =
readl_relaxed(dart->regs + DART_TTBR(dart, sid, idx));
@@ -1035,7 +1097,7 @@ static int apple_dart_resume(struct device *dev)
for (idx = 0; idx < dart->hw->ttbr_count; idx++)
writel_relaxed(dart->save_ttbr[sid][idx],
dart->regs + DART_TTBR(dart, sid, idx));
- writel_relaxed(dart->save_tcr[sid], dart->regs + DART_TCR(sid));
+ writel_relaxed(dart->save_tcr[sid], dart->regs + DART_TCR(dart, sid));
}
return 0;
--
2.34.1

View File

@ -0,0 +1,316 @@
From 50f73e1258c60ccd081a09339f77176f0f9bc49c Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 28 Jun 2022 01:33:40 +0900
Subject: [PATCH 056/171] iommu: dart: Add t8110 support
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/iommu/apple-dart.c | 200 ++++++++++++++++++++++++++++++++++++-
1 file changed, 197 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 3f89db3f8e99..249798e26e5d 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -84,6 +84,62 @@
#define DART_T8020_TTBR_ADDR_OFF 0
#define DART_T8020_TTBR_SHIFT 12
+/* T8110 registers */
+
+#define DART_T8110_PARAMS3 0x08
+#define DART_T8110_PARAMS3_PA_WIDTH GENMASK(29, 24)
+#define DART_T8110_PARAMS3_VA_WIDTH GENMASK(21, 16)
+#define DART_T8110_PARAMS3_VER_MAJ GENMASK(15, 8)
+#define DART_T8110_PARAMS3_VER_MIN GENMASK(7, 0)
+
+#define DART_T8110_PARAMS4 0x0c
+#define DART_T8110_PARAMS4_NUM_CLIENTS GENMASK(24, 16)
+#define DART_T8110_PARAMS4_NUM_SIDS GENMASK(8, 0)
+
+#define DART_T8110_TLB_CMD 0x80
+#define DART_T8110_TLB_CMD_BUSY BIT(31)
+#define DART_T8110_TLB_CMD_OP GENMASK(10, 8)
+#define DART_T8110_TLB_CMD_OP_FLUSH_ALL 0
+#define DART_T8110_TLB_CMD_OP_FLUSH_SID 1
+#define DART_T8110_TLB_CMD_STREAM GENMASK(7, 0)
+
+#define DART_T8110_ERROR 0x100
+#define DART_T8110_ERROR_STREAM GENMASK(27, 20)
+#define DART_T8110_ERROR_CODE GENMASK(14, 0)
+#define DART_T8110_ERROR_FLAG BIT(31)
+
+#define DART_T8110_ERROR_MASK 0x104
+
+#define DART_T8110_ERROR_READ_FAULT BIT(4)
+#define DART_T8110_ERROR_WRITE_FAULT BIT(3)
+#define DART_T8110_ERROR_NO_PTE BIT(3)
+#define DART_T8110_ERROR_NO_PMD BIT(2)
+#define DART_T8110_ERROR_NO_PGD BIT(1)
+#define DART_T8110_ERROR_NO_TTBR BIT(0)
+
+#define DART_T8110_ERROR_ADDR_LO 0x170
+#define DART_T8110_ERROR_ADDR_HI 0x174
+
+#define DART_T8110_PROTECT 0x200
+#define DART_T8110_UNPROTECT 0x204
+#define DART_T8110_PROTECT_LOCK 0x208
+#define DART_T8110_PROTECT_TTBR_TCR BIT(0)
+
+#define DART_T8110_ENABLE_STREAMS 0xc00
+#define DART_T8110_DISABLE_STREAMS 0xc20
+
+#define DART_T8110_TCR 0x1000
+#define DART_T8110_TCR_REMAP GENMASK(11, 8)
+#define DART_T8110_TCR_REMAP_EN BIT(7)
+#define DART_T8110_TCR_BYPASS_DAPF BIT(2)
+#define DART_T8110_TCR_BYPASS_DART BIT(1)
+#define DART_T8110_TCR_TRANSLATE_ENABLE BIT(0)
+
+#define DART_T8110_TTBR 0x1400
+#define DART_T8110_TTBR_VALID BIT(0)
+#define DART_T8110_TTBR_ADDR_OFF 2
+#define DART_T8110_TTBR_SHIFT 14
+
#define DART_TCR(dart, sid) ((dart)->hw->tcr + ((sid) << 2))
#define DART_TTBR(dart, sid, idx) ((dart)->hw->ttbr + \
@@ -92,7 +148,14 @@
struct apple_dart_stream_map;
+enum dart_type {
+ DART_T8020,
+ DART_T6000,
+ DART_T8110,
+};
+
struct apple_dart_hw {
+ enum dart_type type;
irqreturn_t (*irq_handler)(int irq, void *dev);
int (*invalidate_tlb)(struct apple_dart_stream_map *stream_map);
@@ -149,6 +212,7 @@ struct apple_dart {
spinlock_t lock;
+ u32 oas;
u32 pgsize;
u32 num_streams;
u32 supports_bypass : 1;
@@ -330,6 +394,44 @@ apple_dart_t8020_hw_stream_command(struct apple_dart_stream_map *stream_map,
return 0;
}
+static int
+apple_dart_t8110_hw_tlb_command(struct apple_dart_stream_map *stream_map,
+ u32 command)
+{
+ struct apple_dart *dart = stream_map->dart;
+ unsigned long flags;
+ int ret = 0;
+ int sid;
+
+ spin_lock_irqsave(&dart->lock, flags);
+
+ for_each_set_bit(sid, stream_map->sidmap, dart->num_streams) {
+ u32 val = FIELD_PREP(DART_T8110_TLB_CMD_OP, command) |
+ FIELD_PREP(DART_T8110_TLB_CMD_STREAM, sid);
+ writel(val, dart->regs + DART_T8110_TLB_CMD);
+
+ ret = readl_poll_timeout_atomic(
+ dart->regs + DART_T8110_TLB_CMD, val,
+ !(val & DART_T8110_TLB_CMD_BUSY), 1,
+ DART_STREAM_COMMAND_BUSY_TIMEOUT);
+
+ if (ret)
+ break;
+
+ }
+
+ spin_unlock_irqrestore(&dart->lock, flags);
+
+ if (ret) {
+ dev_err(stream_map->dart->dev,
+ "busy bit did not clear after command %x for stream %d\n",
+ command, sid);
+ return ret;
+ }
+
+ return 0;
+}
+
static int
apple_dart_t8020_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
{
@@ -337,6 +439,13 @@ apple_dart_t8020_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
stream_map, DART_T8020_STREAM_COMMAND_INVALIDATE);
}
+static int
+apple_dart_t8110_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
+{
+ return apple_dart_t8110_hw_tlb_command(
+ stream_map, DART_T8110_TLB_CMD_OP_FLUSH_SID);
+}
+
static int apple_dart_hw_reset(struct apple_dart *dart)
{
u32 config;
@@ -363,6 +472,9 @@ static int apple_dart_hw_reset(struct apple_dart *dart)
/* clear any pending errors before the interrupt is unmasked */
writel(readl(dart->regs + dart->hw->error), dart->regs + dart->hw->error);
+ if (dart->hw->type == DART_T8110)
+ writel(0, dart->regs + DART_T8110_ERROR_MASK);
+
return dart->hw->invalidate_tlb(&stream_map);
}
@@ -479,7 +591,7 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
pgtbl_cfg = (struct io_pgtable_cfg){
.pgsize_bitmap = dart->pgsize,
.ias = 32,
- .oas = dart->hw->oas,
+ .oas = dart->oas,
.coherent_walk = 1,
.iommu_dev = dart->dev,
};
@@ -884,6 +996,46 @@ static irqreturn_t apple_dart_t8020_irq(int irq, void *dev)
return IRQ_HANDLED;
}
+
+static irqreturn_t apple_dart_t8110_irq(int irq, void *dev)
+{
+ struct apple_dart *dart = dev;
+ const char *fault_name = NULL;
+ u32 error = readl(dart->regs + DART_T8110_ERROR);
+ u32 error_code = FIELD_GET(DART_T8110_ERROR_CODE, error);
+ u32 addr_lo = readl(dart->regs + DART_T8110_ERROR_ADDR_LO);
+ u32 addr_hi = readl(dart->regs + DART_T8110_ERROR_ADDR_HI);
+ u64 addr = addr_lo | (((u64)addr_hi) << 32);
+ u8 stream_idx = FIELD_GET(DART_T8110_ERROR_STREAM, error);
+
+ if (!(error & DART_T8110_ERROR_FLAG))
+ return IRQ_NONE;
+
+ /* there should only be a single bit set but let's use == to be sure */
+ if (error_code == DART_T8110_ERROR_READ_FAULT)
+ fault_name = "READ FAULT";
+ else if (error_code == DART_T8110_ERROR_WRITE_FAULT)
+ fault_name = "WRITE FAULT";
+ else if (error_code == DART_T8110_ERROR_NO_PTE)
+ fault_name = "NO PTE FOR IOVA";
+ else if (error_code == DART_T8110_ERROR_NO_PMD)
+ fault_name = "NO PMD FOR IOVA";
+ else if (error_code == DART_T8110_ERROR_NO_PGD)
+ fault_name = "NO PGD FOR IOVA";
+ else if (error_code == DART_T8110_ERROR_NO_TTBR)
+ fault_name = "NO TTBR FOR IOVA";
+ else
+ fault_name = "unknown";
+
+ dev_err_ratelimited(
+ dart->dev,
+ "translation fault: status:0x%x stream:%d code:0x%x (%s) at 0x%llx",
+ error, stream_idx, error_code, fault_name, addr);
+
+ writel(error, dart->regs + DART_T8110_ERROR);
+ return IRQ_HANDLED;
+}
+
static int apple_dart_set_bus_ops(const struct iommu_ops *ops)
{
int ret;
@@ -908,7 +1060,7 @@ static int apple_dart_set_bus_ops(const struct iommu_ops *ops)
static int apple_dart_probe(struct platform_device *pdev)
{
int ret;
- u32 dart_params[2];
+ u32 dart_params[4];
struct resource *res;
struct apple_dart *dart;
struct device *dev = &pdev->dev;
@@ -948,7 +1100,20 @@ static int apple_dart_probe(struct platform_device *pdev)
dart->pgsize = 1 << FIELD_GET(DART_PARAMS1_PAGE_SHIFT, dart_params[0]);
dart->supports_bypass = dart_params[1] & DART_PARAMS2_BYPASS_SUPPORT;
- dart->num_streams = dart->hw->max_sid_count;
+ switch (dart->hw->type) {
+ case DART_T8020:
+ case DART_T6000:
+ dart->oas = dart->hw->oas;
+ dart->num_streams = dart->hw->max_sid_count;
+ break;
+
+ case DART_T8110:
+ dart_params[2] = readl(dart->regs + DART_T8110_PARAMS3);
+ dart_params[3] = readl(dart->regs + DART_T8110_PARAMS4);
+ dart->oas = FIELD_GET(DART_T8110_PARAMS3_PA_WIDTH, dart_params[2]);
+ dart->num_streams = FIELD_GET(DART_T8110_PARAMS4_NUM_SIDS, dart_params[3]);
+ break;
+ }
if (dart->num_streams > DART_MAX_STREAMS) {
dev_err(&pdev->dev, "Too many streams (%d > %d)\n",
@@ -1017,6 +1182,7 @@ static int apple_dart_remove(struct platform_device *pdev)
}
static const struct apple_dart_hw apple_dart_hw_t8103 = {
+ .type = DART_T8020,
.irq_handler = apple_dart_t8020_irq,
.invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
.oas = 36,
@@ -1041,6 +1207,7 @@ static const struct apple_dart_hw apple_dart_hw_t8103 = {
.ttbr_count = 4,
};
static const struct apple_dart_hw apple_dart_hw_t6000 = {
+ .type = DART_T6000,
.irq_handler = apple_dart_t8020_irq,
.invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
.oas = 42,
@@ -1065,6 +1232,32 @@ static const struct apple_dart_hw apple_dart_hw_t6000 = {
.ttbr_count = 4,
};
+static const struct apple_dart_hw apple_dart_hw_t8110 = {
+ .type = DART_T8110,
+ .irq_handler = apple_dart_t8110_irq,
+ .invalidate_tlb = apple_dart_t8110_hw_invalidate_tlb,
+ .fmt = APPLE_DART2,
+ .max_sid_count = 256,
+
+ .enable_streams = DART_T8110_ENABLE_STREAMS,
+ .disable_streams = DART_T8110_DISABLE_STREAMS,
+ .lock = DART_T8110_PROTECT,
+ .lock_bit = DART_T8110_PROTECT_TTBR_TCR,
+
+ .error = DART_T8110_ERROR,
+
+ .tcr = DART_T8110_TCR,
+ .tcr_enabled = DART_T8110_TCR_TRANSLATE_ENABLE,
+ .tcr_disabled = 0,
+ .tcr_bypass = DART_T8110_TCR_BYPASS_DAPF | DART_T8110_TCR_BYPASS_DART,
+
+ .ttbr = DART_T8110_TTBR,
+ .ttbr_valid = DART_T8110_TTBR_VALID,
+ .ttbr_addr_off = DART_T8110_TTBR_ADDR_OFF,
+ .ttbr_shift = DART_T8110_TTBR_SHIFT,
+ .ttbr_count = 1,
+};
+
#ifdef CONFIG_PM_SLEEP
static int apple_dart_suspend(struct device *dev)
{
@@ -1110,6 +1303,7 @@ static const struct dev_pm_ops apple_dart_pm_ops = {
#endif
static const struct of_device_id apple_dart_of_match[] = {
+ { .compatible = "apple,t8110-dart", .data = &apple_dart_hw_t8110 },
{ .compatible = "apple,t8103-dart", .data = &apple_dart_hw_t8103 },
{ .compatible = "apple,t6000-dart", .data = &apple_dart_hw_t6000 },
{},
--
2.34.1

View File

@ -0,0 +1,197 @@
From e375f9d76a88bc847d44f38157c2dba1c7e02203 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Mon, 20 Sep 2021 02:23:11 +0900
Subject: [PATCH 057/171] tty: serial: samsung_tty: Support runtime PM
This allows idle UART devices to be suspended using the standard
runtime-PM framework. The logic is modeled after stm32-usart.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/tty/serial/samsung_tty.c | 92 ++++++++++++++++++++------------
1 file changed, 59 insertions(+), 33 deletions(-)
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 1afe47b62ad5..2a4ba4f3d23c 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -40,6 +40,7 @@
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/of.h>
+#include <linux/pm_runtime.h>
#include <asm/irq.h>
/* UART name and device definitions */
@@ -1354,30 +1355,49 @@ static int apple_s5l_serial_startup(struct uart_port *port)
/* power power management control */
+static int __maybe_unused s3c24xx_serial_runtime_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ int timeout = 10000;
+
+ while (--timeout && !s3c24xx_serial_txempty_nofifo(port))
+ udelay(100);
+
+ if (!IS_ERR(ourport->baudclk))
+ clk_disable_unprepare(ourport->baudclk);
+
+ clk_disable_unprepare(ourport->clk);
+ return 0;
+};
+
+static int __maybe_unused s3c24xx_serial_runtime_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ clk_prepare_enable(ourport->clk);
+
+ if (!IS_ERR(ourport->baudclk))
+ clk_prepare_enable(ourport->baudclk);
+ return 0;
+};
+
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
unsigned int old)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
- int timeout = 10000;
ourport->pm_level = level;
switch (level) {
- case 3:
- while (--timeout && !s3c24xx_serial_txempty_nofifo(port))
- udelay(100);
-
- if (!IS_ERR(ourport->baudclk))
- clk_disable_unprepare(ourport->baudclk);
-
- clk_disable_unprepare(ourport->clk);
+ case UART_PM_STATE_OFF:
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_sync(port->dev);
break;
- case 0:
- clk_prepare_enable(ourport->clk);
-
- if (!IS_ERR(ourport->baudclk))
- clk_prepare_enable(ourport->baudclk);
+ case UART_PM_STATE_ON:
+ pm_runtime_get_sync(port->dev);
break;
default:
dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
@@ -2248,18 +2268,15 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
}
}
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
dev_dbg(&pdev->dev, "%s: adding port\n", __func__);
uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
platform_set_drvdata(pdev, &ourport->port);
- /*
- * Deactivate the clock enabled in s3c24xx_serial_init_port here,
- * so that a potential re-enablement through the pm-callback overlaps
- * and keeps the clock enabled in this case.
- */
- clk_disable_unprepare(ourport->clk);
- if (!IS_ERR(ourport->baudclk))
- clk_disable_unprepare(ourport->baudclk);
+ pm_runtime_put_sync(&pdev->dev);
ret = s3c24xx_serial_cpufreq_register(ourport);
if (ret < 0)
@@ -2273,10 +2290,21 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
static int s3c24xx_serial_remove(struct platform_device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
if (port) {
+ pm_runtime_get_sync(&dev->dev);
+
s3c24xx_serial_cpufreq_deregister(to_ourport(port));
uart_remove_one_port(&s3c24xx_uart_drv, port);
+
+ clk_disable_unprepare(ourport->clk);
+ if (!IS_ERR(ourport->baudclk))
+ clk_disable_unprepare(ourport->baudclk);
+
+ pm_runtime_disable(&dev->dev);
+ pm_runtime_set_suspended(&dev->dev);
+ pm_runtime_put_noidle(&dev->dev);
}
uart_unregister_driver(&s3c24xx_uart_drv);
@@ -2285,8 +2313,8 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
}
/* UART power management code */
-#ifdef CONFIG_PM_SLEEP
-static int s3c24xx_serial_suspend(struct device *dev)
+
+static int __maybe_unused s3c24xx_serial_suspend(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
@@ -2296,7 +2324,7 @@ static int s3c24xx_serial_suspend(struct device *dev)
return 0;
}
-static int s3c24xx_serial_resume(struct device *dev)
+static int __maybe_unused s3c24xx_serial_resume(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
@@ -2316,7 +2344,7 @@ static int s3c24xx_serial_resume(struct device *dev)
return 0;
}
-static int s3c24xx_serial_resume_noirq(struct device *dev)
+static int __maybe_unused s3c24xx_serial_resume_noirq(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
@@ -2386,16 +2414,14 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
}
static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
.suspend = s3c24xx_serial_suspend,
.resume = s3c24xx_serial_resume,
.resume_noirq = s3c24xx_serial_resume_noirq,
+#endif
+ SET_RUNTIME_PM_OPS(s3c24xx_serial_runtime_suspend,
+ s3c24xx_serial_runtime_resume, NULL)
};
-#define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops)
-
-#else /* !CONFIG_PM_SLEEP */
-
-#define SERIAL_SAMSUNG_PM_OPS NULL
-#endif /* CONFIG_PM_SLEEP */
/* Console code */
@@ -2936,7 +2962,7 @@ static struct platform_driver samsung_serial_driver = {
.id_table = s3c24xx_serial_driver_ids,
.driver = {
.name = "samsung-uart",
- .pm = SERIAL_SAMSUNG_PM_OPS,
+ .pm = &s3c24xx_serial_pm_ops,
.of_match_table = of_match_ptr(s3c24xx_uart_dt_match),
},
};
--
2.34.1

View File

@ -0,0 +1,83 @@
From 33d1d04ba47ab79e38400038347b1ef04aca10fc Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Fri, 4 Mar 2022 19:19:38 +0900
Subject: [PATCH 058/171] drm/simpledrm: Add backlight support
Allows devicetrees to link the simplefb node to a backlight device,
and toggles power to the backlight when the display pipe is
enabled/disabled. This is sufficient for basic DPMS style functionality
in trivial devices.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/gpu/drm/tiny/Kconfig | 1 +
drivers/gpu/drm/tiny/simpledrm.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index 627d637a1e7e..20c78bb1365d 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -71,6 +71,7 @@ config DRM_SIMPLEDRM
depends on DRM && MMU
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
+ select BACKLIGHT_CLASS_DEVICE
help
DRM driver for simple platform-provided framebuffers.
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 5422363690e7..40de01efbbd9 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/backlight.h>
#include <linux/clk.h>
#include <linux/of_clk.h>
#include <linux/minmax.h>
@@ -225,6 +226,9 @@ struct simpledrm_device {
size_t nformats;
struct drm_connector connector;
struct drm_simple_display_pipe pipe;
+
+ /* backlight */
+ struct backlight_device *backlight;
};
static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev)
@@ -673,6 +677,9 @@ simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip);
drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip);
+ if (sdev->backlight)
+ backlight_enable(sdev->backlight);
+
drm_dev_exit(idx);
}
@@ -686,6 +693,9 @@ simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
if (!drm_dev_enter(dev, &idx))
return;
+ if (sdev->backlight)
+ backlight_disable(sdev->backlight);
+
/* Clear screen to black if disabled */
memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay);
@@ -845,6 +855,10 @@ simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev)
sdev->pdev = pdev;
platform_set_drvdata(pdev, sdev);
+ sdev->backlight = devm_of_find_backlight(&pdev->dev);
+ if (IS_ERR(sdev->backlight))
+ sdev->backlight = NULL;
+
ret = simpledrm_device_init_clocks(sdev);
if (ret)
return ERR_PTR(ret);
--
2.34.1

View File

@ -0,0 +1,29 @@
From a9d5ced1ff2a58014dc850ece702cc194884870d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sat, 12 Mar 2022 00:07:09 +0900
Subject: [PATCH 059/171] of: Demote "Bad cell count" to debug message
This happens on the SPMI bus... TODO: figure out what the right solution
is here.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/of/address.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 94f017d808c4..68f54ec92496 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -538,7 +538,7 @@ static u64 __of_translate_address(struct device_node *dev,
pbus = of_match_bus(parent);
pbus->count_cells(dev, &pna, &pns);
if (!OF_CHECK_COUNTS(pna, pns)) {
- pr_err("Bad cell count for %pOF\n", dev);
+ pr_debug("Bad cell count for %pOF\n", dev);
break;
}
--
2.34.1

View File

@ -0,0 +1,37 @@
From 2c80db171f88a2c7384cfefbd20ba4b2ed570e5c Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 5 May 2022 01:40:31 +0900
Subject: [PATCH 060/171] mmc: sdhci-pci: Support external CD GPIO on all OF
systems
Allow OF systems to specify an external CD GPIO on all devices,
even if they have an internal CD feature.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/mmc/host/sdhci-pci-core.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index ed53276f6ad9..a711b4be3867 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -2096,6 +2096,15 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
dev_warn(&pdev->dev, "failed to setup card detect gpio\n");
slot->cd_idx = -1;
}
+ } else if (is_of_node(pdev->dev.fwnode)) {
+ /* Allow all OF systems to use a CD GPIO if provided */
+
+ ret = mmc_gpiod_request_cd(host->mmc, "cd", 0,
+ slot->cd_override_level, 0);
+ if (ret == -EPROBE_DEFER)
+ goto remove;
+ else if (ret == 0)
+ slot->cd_idx = 0;
}
if (chip->fixes && chip->fixes->add_host)
--
2.34.1

View File

@ -0,0 +1,65 @@
From 5f9f115872ee614c22a9417f68ae9100ec32b5c7 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 5 May 2022 02:27:35 +0900
Subject: [PATCH 061/171] mmc: sdhci-pci: Support setting CD debounce delay
Some systems (e.g. 2021 MacBook Pro 14/16") have noncompliant connectors
where CD activates before the card is fully inserted. We need debounce
delay support on these to avoid detection failures when the card isn't
inserted very quickly.
Set the default to 200ms for all systems instead of 0. This is the
default on non-PCI platforms, and will probably help other systems too.
The naughty MacBooks will need closer to 750ms in the device tree to
be reliable...
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/mmc/host/sdhci-pci-core.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index a711b4be3867..2fd4221b24aa 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -2015,6 +2015,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
struct sdhci_host *host;
int ret, bar = first_bar + slotno;
size_t priv_size = chip->fixes ? chip->fixes->priv_size : 0;
+ u32 cd_debounce_delay_ms;
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar);
@@ -2081,6 +2082,10 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
if (host->mmc->caps & MMC_CAP_CD_WAKE)
device_init_wakeup(&pdev->dev, true);
+ if (device_property_read_u32(&pdev->dev, "cd-debounce-delay-ms",
+ &cd_debounce_delay_ms))
+ cd_debounce_delay_ms = 200;
+
if (slot->cd_idx >= 0) {
ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx,
slot->cd_override_level, 0);
@@ -2088,7 +2093,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
ret = mmc_gpiod_request_cd(host->mmc, NULL,
slot->cd_idx,
slot->cd_override_level,
- 0);
+ cd_debounce_delay_ms * 1000);
if (ret == -EPROBE_DEFER)
goto remove;
@@ -2100,7 +2105,8 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
/* Allow all OF systems to use a CD GPIO if provided */
ret = mmc_gpiod_request_cd(host->mmc, "cd", 0,
- slot->cd_override_level, 0);
+ slot->cd_override_level,
+ cd_debounce_delay_ms * 1000);
if (ret == -EPROBE_DEFER)
goto remove;
else if (ret == 0)
--
2.34.1

View File

@ -0,0 +1,106 @@
From f60e434c0766aaf5db2d775bbcba49d896e1f518 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Mon, 2 May 2022 19:46:47 +0900
Subject: [PATCH 062/171] net: usb: ax88179_178a: Bind only to vendor-specific
interface
The Anker PowerExpand USB-C to Gigabit Ethernet adapter uses this
chipset, but exposes CDC Ethernet configurations as well as the
vendor specific one. This driver ends up binding first to both CDC
interfaces, tries to instantiate two Ethernet interfaces talking to
the same device, and the result is a nice fireworks show.
Change all the ID matches to specifically match the vendor-specific
interface. By default the device comes up in CDC mode and is bound by
that driver (which works fine); users may switch it to the vendor
interface using sysfs to set bConfigurationValue, at which point the
device actually goes through a reconnect cycle and comes back as a
vendor specific only device, and then this driver binds and works too.
The affected device uses VID/PID 0b95:1790, but we might as well change
all of them for good measure, since there is no good reason for this
driver to bind to standard CDC Ethernet interfaces.
v3: Added VID/PID info to commit message
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/net/usb/ax88179_178a.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index ac2d400d1d6c..aeb0294385ed 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1965,55 +1965,55 @@ static const struct driver_info at_umc2000sp_info = {
static const struct usb_device_id products[] = {
{
/* ASIX AX88179 10/100/1000 */
- USB_DEVICE(0x0b95, 0x1790),
+ USB_DEVICE_AND_INTERFACE_INFO(0x0b95, 0x1790, 0xff, 0xff, 0),
.driver_info = (unsigned long)&ax88179_info,
}, {
/* ASIX AX88178A 10/100/1000 */
- USB_DEVICE(0x0b95, 0x178a),
+ USB_DEVICE_AND_INTERFACE_INFO(0x0b95, 0x178a, 0xff, 0xff, 0),
.driver_info = (unsigned long)&ax88178a_info,
}, {
/* Cypress GX3 SuperSpeed to Gigabit Ethernet Bridge Controller */
- USB_DEVICE(0x04b4, 0x3610),
+ USB_DEVICE_AND_INTERFACE_INFO(0x04b4, 0x3610, 0xff, 0xff, 0),
.driver_info = (unsigned long)&cypress_GX3_info,
}, {
/* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */
- USB_DEVICE(0x2001, 0x4a00),
+ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x4a00, 0xff, 0xff, 0),
.driver_info = (unsigned long)&dlink_dub1312_info,
}, {
/* Sitecom USB 3.0 to Gigabit Adapter */
- USB_DEVICE(0x0df6, 0x0072),
+ USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0072, 0xff, 0xff, 0),
.driver_info = (unsigned long)&sitecom_info,
}, {
/* Samsung USB Ethernet Adapter */
- USB_DEVICE(0x04e8, 0xa100),
+ USB_DEVICE_AND_INTERFACE_INFO(0x04e8, 0xa100, 0xff, 0xff, 0),
.driver_info = (unsigned long)&samsung_info,
}, {
/* Lenovo OneLinkDock Gigabit LAN */
- USB_DEVICE(0x17ef, 0x304b),
+ USB_DEVICE_AND_INTERFACE_INFO(0x17ef, 0x304b, 0xff, 0xff, 0),
.driver_info = (unsigned long)&lenovo_info,
}, {
/* Belkin B2B128 USB 3.0 Hub + Gigabit Ethernet Adapter */
- USB_DEVICE(0x050d, 0x0128),
+ USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x0128, 0xff, 0xff, 0),
.driver_info = (unsigned long)&belkin_info,
}, {
/* Toshiba USB 3.0 GBit Ethernet Adapter */
- USB_DEVICE(0x0930, 0x0a13),
+ USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x0a13, 0xff, 0xff, 0),
.driver_info = (unsigned long)&toshiba_info,
}, {
/* Magic Control Technology U3-A9003 USB 3.0 Gigabit Ethernet Adapter */
- USB_DEVICE(0x0711, 0x0179),
+ USB_DEVICE_AND_INTERFACE_INFO(0x0711, 0x0179, 0xff, 0xff, 0),
.driver_info = (unsigned long)&mct_info,
}, {
/* Allied Telesis AT-UMC2000 USB 3.0/USB 3.1 Gen 1 to Gigabit Ethernet Adapter */
- USB_DEVICE(0x07c9, 0x000e),
+ USB_DEVICE_AND_INTERFACE_INFO(0x07c9, 0x000e, 0xff, 0xff, 0),
.driver_info = (unsigned long)&at_umc2000_info,
}, {
/* Allied Telesis AT-UMC200 USB 3.0/USB 3.1 Gen 1 to Fast Ethernet Adapter */
- USB_DEVICE(0x07c9, 0x000f),
+ USB_DEVICE_AND_INTERFACE_INFO(0x07c9, 0x000f, 0xff, 0xff, 0),
.driver_info = (unsigned long)&at_umc200_info,
}, {
/* Allied Telesis AT-UMC2000/SP USB 3.0/USB 3.1 Gen 1 to Gigabit Ethernet Adapter */
- USB_DEVICE(0x07c9, 0x0010),
+ USB_DEVICE_AND_INTERFACE_INFO(0x07c9, 0x0010, 0xff, 0xff, 0),
.driver_info = (unsigned long)&at_umc2000sp_info,
},
{ },
--
2.34.1

View File

@ -0,0 +1,89 @@
From 834ab8867f3537c2a1c40853309aeb63401f7b34 Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Sun, 7 Nov 2021 11:21:19 +0100
Subject: [PATCH 063/171] dt-bindings: usb: Add Apple dwc3 bindings
Apple Silicon SoCs such as the M1 have multiple USB controllers based on
the Synopsys DesignWare USB3 controller.
References to the ATC PHY required for SuperSpeed are left out for now
until support has been upstreamed as well.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
.../devicetree/bindings/usb/apple,dwc3.yaml | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/apple,dwc3.yaml
diff --git a/Documentation/devicetree/bindings/usb/apple,dwc3.yaml b/Documentation/devicetree/bindings/usb/apple,dwc3.yaml
new file mode 100644
index 000000000000..fb3b3489e6b2
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/apple,dwc3.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/apple,dwc3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple Silicon DWC3 USB controller
+
+maintainers:
+ - Sven Peter <sven@svenpeter.dev>
+
+description:
+ On Apple Silicon SoCs such as the M1 each Type-C port has a corresponding
+ USB controller based on the Synopsys DesignWare USB3 controller.
+
+ The common content of this binding is defined in snps,dwc3.yaml.
+
+allOf:
+ - $ref: snps,dwc3.yaml#
+
+select:
+ properties:
+ compatible:
+ contains:
+ const: apple,dwc3
+ required:
+ - compatible
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - apple,t8103-dwc3
+ - apple,t6000-dwc3
+ - const: apple,dwc3
+ - const: snps,dwc3
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/apple-aic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ usb@82280000 {
+ compatible = "apple,t8103-dwc3", "apple,dwc3", "snps,dwc3";
+ reg = <0x82280000 0x10000>;
+ interrupts = <AIC_IRQ 777 IRQ_TYPE_LEVEL_HIGH>;
+
+ dr_mode = "otg";
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ };
--
2.34.1

View File

@ -0,0 +1,172 @@
From bda2c5ab3f028f25bf7d0e8196ee1dee38973153 Mon Sep 17 00:00:00 2001
From: Sven Peter <sven@svenpeter.dev>
Date: Sun, 7 Nov 2021 11:21:20 +0100
Subject: [PATCH 064/171] usb: dwc3: Add role switch reset quirk for Apple DWC3
As mad as it sounds, the dwc3 controller present on the Apple M1 must be
reset and reinitialized whenever a device is unplugged from the root port.
The only reliable unplug/plug notification available comes from the USB
PD controller through the role-switch infrastructure.
This is required for at least two reasons:
- The USB2 D+/D- lines are connected through a stateful eUSB2 repeater
which in turn is controlled by a variant of the TI TPS6598x USB PD
chip. When the USB PD controller detects a hotplug event it resets
the eUSB2 repeater. Afterwards, no new device is recognized before
the DWC3 core and PHY are reset as well.
- It's possible to completely break the dwc3 controller by switching
it to device mode and unplugging the cable at just the wrong time.
Even a CORESOFTRESET is not enough to allow new devices again.
The only workaround is to trigger a hard reset of the entire
dwc3 core.
Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
drivers/usb/dwc3/core.c | 41 ++++++++++++++++++++++++++++++++++++++---
drivers/usb/dwc3/core.h | 6 ++++++
drivers/usb/dwc3/drd.c | 7 +++++++
3 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 573421984948..b4c58deccabb 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -116,6 +116,9 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
dwc->current_dr_role = mode;
}
+static void dwc3_core_exit(struct dwc3 *dwc);
+static int dwc3_core_init_for_resume(struct dwc3 *dwc);
+
static void __dwc3_set_mode(struct work_struct *work)
{
struct dwc3 *dwc = work_to_dwc(work);
@@ -130,10 +133,11 @@ static void __dwc3_set_mode(struct work_struct *work)
if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG)
dwc3_otg_update(dwc, 0);
- if (!dwc->desired_dr_role)
+ if (!dwc->desired_dr_role && !dwc->role_switch_reset_quirk)
goto out;
- if (dwc->desired_dr_role == dwc->current_dr_role)
+ if (dwc->desired_dr_role == dwc->current_dr_role &&
+ !dwc->role_switch_reset_quirk)
goto out;
if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev)
@@ -158,6 +162,34 @@ static void __dwc3_set_mode(struct work_struct *work)
break;
}
+ if (dwc->role_switch_reset_quirk) {
+ if (dwc->current_dr_role) {
+ dwc->current_dr_role = 0;
+ dwc3_core_exit(dwc);
+ }
+
+ if (dwc->desired_dr_role) {
+ /*
+ * the first call to __dwc3_set_mode comes from
+ * dwc3_drd_init. In that case dwc3_core_init has been
+ * called but dwc->current_dr_role is zero such that
+ * we must not reinitialize the core again here.
+ */
+ if (dwc->role_switch_reset_quirk_initialized) {
+ ret = dwc3_core_init_for_resume(dwc);
+ if (ret) {
+ dev_err(dwc->dev,
+ "failed to reinitialize core\n");
+ goto out;
+ }
+ }
+
+ dwc->role_switch_reset_quirk_initialized = 1;
+ } else {
+ goto out;
+ }
+ }
+
/* For DRD host or device mode only */
if (dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) {
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
@@ -1764,6 +1796,9 @@ static int dwc3_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(dwc->susp_clk),
"could not get suspend clock\n");
}
+
+ if (of_device_is_compatible(dev->of_node, "apple,dwc3"))
+ dwc->role_switch_reset_quirk = true;
}
ret = reset_control_deassert(dwc->reset);
@@ -1900,7 +1935,6 @@ static int dwc3_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
static int dwc3_core_init_for_resume(struct dwc3 *dwc)
{
int ret;
@@ -1927,6 +1961,7 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc)
return ret;
}
+#ifdef CONFIG_PM
static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
{
unsigned long flags;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 81c486b3941c..ee0225ce2234 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1103,6 +1103,9 @@ struct dwc3_scratchpad_array {
* 3 - Reserved
* @dis_metastability_quirk: set to disable metastability quirk.
* @dis_split_quirk: set to disable split boundary.
+ * @role_switch_reset_quirk: set to force reinitialization after any role switch
+ * @role_switch_reset_quirk_initialized: set to true after the first role switch
+ * which is triggered from dwc3_drd_init directly
* @imod_interval: set the interrupt moderation interval in 250ns
* increments or 0 to disable.
* @max_cfg_eps: current max number of IN eps used across all USB configs.
@@ -1318,6 +1321,9 @@ struct dwc3 {
unsigned dis_split_quirk:1;
unsigned async_callbacks:1;
+ unsigned role_switch_reset_quirk:1;
+ unsigned role_switch_reset_quirk_initialized:1;
+
u16 imod_interval;
int max_cfg_eps;
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
index 039bf241769a..4579505cac1f 100644
--- a/drivers/usb/dwc3/drd.c
+++ b/drivers/usb/dwc3/drd.c
@@ -461,6 +461,9 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
break;
}
+ if (dwc->role_switch_reset_quirk && role == USB_ROLE_NONE)
+ mode = 0;
+
dwc3_set_mode(dwc, mode);
return 0;
}
@@ -489,6 +492,10 @@ static enum usb_role dwc3_usb_role_switch_get(struct usb_role_switch *sw)
role = USB_ROLE_DEVICE;
break;
}
+
+ if (dwc->role_switch_reset_quirk && !dwc->current_dr_role)
+ role = USB_ROLE_NONE;
+
spin_unlock_irqrestore(&dwc->lock, flags);
return role;
}
--
2.34.1

View File

@ -0,0 +1,141 @@
From 6c8c3ae8ce7813a315f4729865f99d0d318f678a Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@kernel.dk>
Date: Wed, 16 Feb 2022 12:17:58 -0700
Subject: [PATCH 065/171] apple-nvme: defer cache flushes by a specified amount
Cache flushes on the M1 nvme are really slow, taking 17-18 msec to
complete. This can slow down workloads considerably, pure random writes
end up being bound by the flush latency and hence run at 55-60 IOPS.
Add a deferred flush work around to provide better performance, at a
minimal risk. By default, flushes are delayed at most 1 second, but this
is configurable.
With this work-around, a pure random write workload runs at ~12K IOPS
rather than 56 IOPS.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
drivers/nvme/host/apple.c | 69 +++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index d702d7d60235..46294f99a1b0 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -195,8 +195,20 @@ struct apple_nvme {
int irq;
spinlock_t lock;
+
+ /*
+ * Delayed cache flush handling state
+ */
+ struct nvme_ns *flush_ns;
+ unsigned long flush_interval;
+ unsigned long last_flush;
+ struct delayed_work flush_dwork;
};
+unsigned int flush_interval = 1000;
+module_param(flush_interval, uint, 0644);
+MODULE_PARM_DESC(flush_interval, "Grace period in msecs between flushes");
+
static_assert(sizeof(struct nvme_command) == 64);
static_assert(sizeof(struct apple_nvmmu_tcb) == 128);
@@ -729,6 +741,26 @@ static int apple_nvme_remove_sq(struct apple_nvme *anv)
return nvme_submit_sync_cmd(anv->ctrl.admin_q, &c, NULL, 0);
}
+static bool apple_nvme_delayed_flush(struct apple_nvme *anv, struct nvme_ns *ns,
+ struct request *req)
+{
+ if (!anv->flush_interval || req_op(req) != REQ_OP_FLUSH)
+ return false;
+ if (delayed_work_pending(&anv->flush_dwork))
+ return true;
+ if (time_before(jiffies, anv->last_flush + anv->flush_interval)) {
+ kblockd_mod_delayed_work_on(WORK_CPU_UNBOUND, &anv->flush_dwork,
+ anv->flush_interval);
+ if (WARN_ON_ONCE(anv->flush_ns && anv->flush_ns != ns))
+ goto out;
+ anv->flush_ns = ns;
+ return true;
+ }
+out:
+ anv->last_flush = jiffies;
+ return false;
+}
+
static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
@@ -764,6 +796,12 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
}
blk_mq_start_request(req);
+
+ if (apple_nvme_delayed_flush(anv, ns, req)) {
+ blk_mq_complete_request(req);
+ return BLK_STS_OK;
+ }
+
apple_nvme_submit_cmd(q, cmnd);
return BLK_STS_OK;
@@ -1366,6 +1404,28 @@ static int apple_nvme_attach_genpd(struct apple_nvme *anv)
return 0;
}
+static void apple_nvme_flush_work(struct work_struct *work)
+{
+ struct nvme_command c = { };
+ struct apple_nvme *anv;
+ struct nvme_ns *ns;
+ int err;
+
+ anv = container_of(work, struct apple_nvme, flush_dwork.work);
+ ns = anv->flush_ns;
+ if (WARN_ON_ONCE(!ns))
+ return;
+
+ c.common.opcode = nvme_cmd_flush;
+ c.common.nsid = cpu_to_le32(anv->flush_ns->head->ns_id);
+ err = nvme_submit_sync_cmd(ns->queue, &c, NULL, 0);
+ if (err) {
+ dev_err(anv->dev, "Deferred flush failed: %d\n", err);
+ } else {
+ anv->last_flush = jiffies;
+ }
+}
+
static int apple_nvme_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1508,6 +1568,14 @@ static int apple_nvme_probe(struct platform_device *pdev)
goto put_dev;
}
+ if (flush_interval) {
+ anv->flush_interval = msecs_to_jiffies(flush_interval);
+ anv->flush_ns = NULL;
+ anv->last_flush = jiffies - anv->flush_interval;
+ }
+
+ INIT_DELAYED_WORK(&anv->flush_dwork, apple_nvme_flush_work);
+
nvme_reset_ctrl(&anv->ctrl);
async_schedule(apple_nvme_async_probe, anv);
@@ -1541,6 +1609,7 @@ static void apple_nvme_shutdown(struct platform_device *pdev)
{
struct apple_nvme *anv = platform_get_drvdata(pdev);
+ flush_delayed_work(&anv->flush_dwork);
apple_nvme_disable(anv, true);
if (apple_rtkit_is_running(anv->rtk))
apple_rtkit_shutdown(anv->rtk);
--
2.34.1

View File

@ -0,0 +1,25 @@
From 17290bf07058d3b52c3a750be73831827af3f98d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Mon, 27 Jun 2022 21:47:43 +0900
Subject: [PATCH 066/171] apple-nvme: Release power domains when probe fails
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/nvme/host/apple.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index 46294f99a1b0..67cef4dda24c 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -1582,6 +1582,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
return 0;
put_dev:
+ apple_nvme_detach_genpd(anv);
put_device(anv->dev);
return ret;
}
--
2.34.1

View File

@ -0,0 +1,39 @@
From ef2e86f869f55da922fcb8235cd32ea78fe3e2b7 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 12 Dec 2021 12:28:41 +0900
Subject: [PATCH 067/171] MAINTAINERS: Add apple-spi driver & binding files
This Apple SPI controller is present on Apple ARM SoCs (t8103/t6000).
Splitting this change from the binding/driver commits to avoid merge
conflicts with other things touching this section, as usual.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
MAINTAINERS | 3 +++
1 file changed, 3 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 64379c699903..629c1a177d3f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1843,6 +1843,8 @@ F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: Documentation/devicetree/bindings/power/apple*
+F: Documentation/devicetree/bindings/spi/apple,spi.yaml
+F: Documentation/devicetree/bindings/usb/apple,dwc3.yaml
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
F: arch/arm64/boot/dts/apple/
F: drivers/clk/clk-apple-nco.c
@@ -1855,6 +1857,7 @@ F: drivers/nvme/host/apple.c
F: drivers/nvmem/apple-efuses.c
F: drivers/pinctrl/pinctrl-apple-gpio.c
F: drivers/soc/apple/*
+F: drivers/spi/spi-apple.c
F: drivers/watchdog/apple_wdt.c
F: include/dt-bindings/interrupt-controller/apple-aic.h
F: include/dt-bindings/pinctrl/apple.h
--
2.34.1

View File

@ -0,0 +1,88 @@
From c26ea602ff1a0f7d01421320ed5bea2f611f73cd Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 12 Dec 2021 11:46:33 +0900
Subject: [PATCH 068/171] dt-bindings: spi: apple,spi: Add binding for Apple
SPI controllers
The Apple SPI controller is present in SoCs such as the M1 (t8103) and
M1 Pro/Max (t600x). This controller uses one IRQ and one clock, and
doesn't need any special properties, so the binding is trivial.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../devicetree/bindings/spi/apple,spi.yaml | 63 +++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/apple,spi.yaml
diff --git a/Documentation/devicetree/bindings/spi/apple,spi.yaml b/Documentation/devicetree/bindings/spi/apple,spi.yaml
new file mode 100644
index 000000000000..bcbdc8943e92
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/apple,spi.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/apple,spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple ARM SoC SPI controller
+
+allOf:
+ - $ref: "spi-controller.yaml#"
+
+maintainers:
+ - Hector Martin <marcan@marcan.st>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - apple,t8103-spi
+ - apple,t6000-spi
+ - const: apple,spi
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+ - '#address-cells'
+ - '#size-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/apple-aic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ spi: spi@39b104000 {
+ compatible = "apple,t6000-spi", "apple,spi";
+ reg = <0x3 0x9b104000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1107 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clk>;
+ };
+ };
--
2.34.1

View File

@ -0,0 +1,618 @@
From 90521a1e8c3ebf5c2ee27d2e3f62bb81cf28e23f Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 9 Dec 2021 21:55:49 +0900
Subject: [PATCH 069/171] spi: apple: Add driver for Apple SPI controller
This SPI controller is present in Apple SoCs such as the M1 (t8103) and
M1 Pro/Max (t600x). It is a relatively straightforward design with two
16-entry FIFOs, arbitrary transfer sizes (up to 2**32 - 1) and fully
configurable word size up to 32 bits. It supports one hardware CS line
which can also be driven via the pinctrl/GPIO driver instead, if
desired. TX and RX can be independently enabled.
There are a surprising number of knobs for tweaking details of the
transfer, most of which we do not use right now. Hardware CS control
is available, but we haven't found a way to make it stay low across
multiple logical transfers, so we just use software CS control for now.
There is also a shared DMA offload coprocessor that can be used to handle
larger transfers without requiring an IRQ every 8-16 words, but that
feature depends on a bunch of scaffolding that isn't ready to be
upstreamed yet, so leave it for later.
The hardware shares some register bit definitions with spi-s3c24xx which
suggests it has a shared legacy with Samsung SoCs, but it is too
different to warrant sharing a driver.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/spi/Kconfig | 8 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-apple.c | 544 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 553 insertions(+)
create mode 100644 drivers/spi/spi-apple.c
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3b1044ebc400..863e215a5127 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -79,6 +79,14 @@ config SPI_ALTERA_DFL
Altera SPI master controller. The SPI master is connected
to a SPI slave to Avalon bridge in a Intel MAX BMC.
+config SPI_APPLE
+ tristate "Apple SoC SPI Controller platform driver"
+ depends on ARCH_APPLE || COMPILE_TEST
+ help
+ This enables support for the SPI controller present on
+ many Apple SoCs, including the t8103 (M1) and t600x
+ (M1 Pro/Max).
+
config SPI_AR934X
tristate "Qualcomm Atheros AR934X/QCA95XX SPI controller driver"
depends on ATH79 || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 0f44eb6083a5..f86ba8634f77 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o
obj-$(CONFIG_SPI_ALTERA) += spi-altera-platform.o
obj-$(CONFIG_SPI_ALTERA_CORE) += spi-altera-core.o
obj-$(CONFIG_SPI_ALTERA_DFL) += spi-altera-dfl.o
+obj-$(CONFIG_SPI_APPLE) += spi-apple.o
obj-$(CONFIG_SPI_AR934X) += spi-ar934x.o
obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o
obj-$(CONFIG_SPI_ASPEED_SMC) += spi-aspeed-smc.o
diff --git a/drivers/spi/spi-apple.c b/drivers/spi/spi-apple.c
new file mode 100644
index 000000000000..c483ad3f69ef
--- /dev/null
+++ b/drivers/spi/spi-apple.c
@@ -0,0 +1,544 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple SoC SPI device driver
+ *
+ * Copyright The Asahi Linux Contributors
+ *
+ * Based on spi-sifive.c, Copyright 2018 SiFive, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/spi/spi.h>
+
+#define APPLE_SPI_CTRL 0x000
+#define APPLE_SPI_CTRL_RUN BIT(0)
+#define APPLE_SPI_CTRL_TX_RESET BIT(2)
+#define APPLE_SPI_CTRL_RX_RESET BIT(3)
+
+#define APPLE_SPI_CFG 0x004
+#define APPLE_SPI_CFG_CPHA BIT(1)
+#define APPLE_SPI_CFG_CPOL BIT(2)
+#define APPLE_SPI_CFG_MODE GENMASK(6, 5)
+#define APPLE_SPI_CFG_MODE_POLLED 0
+#define APPLE_SPI_CFG_MODE_IRQ 1
+#define APPLE_SPI_CFG_MODE_DMA 2
+#define APPLE_SPI_CFG_IE_RXCOMPLETE BIT(7)
+#define APPLE_SPI_CFG_IE_TXRXTHRESH BIT(8)
+#define APPLE_SPI_CFG_LSB_FIRST BIT(13)
+#define APPLE_SPI_CFG_WORD_SIZE GENMASK(16, 15)
+#define APPLE_SPI_CFG_WORD_SIZE_8B 0
+#define APPLE_SPI_CFG_WORD_SIZE_16B 1
+#define APPLE_SPI_CFG_WORD_SIZE_32B 2
+#define APPLE_SPI_CFG_FIFO_THRESH GENMASK(18, 17)
+#define APPLE_SPI_CFG_FIFO_THRESH_8B 0
+#define APPLE_SPI_CFG_FIFO_THRESH_4B 1
+#define APPLE_SPI_CFG_FIFO_THRESH_1B 2
+#define APPLE_SPI_CFG_IE_TXCOMPLETE BIT(21)
+
+#define APPLE_SPI_STATUS 0x008
+#define APPLE_SPI_STATUS_RXCOMPLETE BIT(0)
+#define APPLE_SPI_STATUS_TXRXTHRESH BIT(1)
+#define APPLE_SPI_STATUS_TXCOMPLETE BIT(2)
+
+#define APPLE_SPI_PIN 0x00c
+#define APPLE_SPI_PIN_KEEP_MOSI BIT(0)
+#define APPLE_SPI_PIN_CS BIT(1)
+
+#define APPLE_SPI_TXDATA 0x010
+#define APPLE_SPI_RXDATA 0x020
+#define APPLE_SPI_CLKDIV 0x030
+#define APPLE_SPI_CLKDIV_MAX 0x7ff
+#define APPLE_SPI_RXCNT 0x034
+#define APPLE_SPI_WORD_DELAY 0x038
+#define APPLE_SPI_TXCNT 0x04c
+
+#define APPLE_SPI_FIFOSTAT 0x10c
+#define APPLE_SPI_FIFOSTAT_TXFULL BIT(4)
+#define APPLE_SPI_FIFOSTAT_LEVEL_TX GENMASK(15, 8)
+#define APPLE_SPI_FIFOSTAT_RXEMPTY BIT(20)
+#define APPLE_SPI_FIFOSTAT_LEVEL_RX GENMASK(31, 24)
+
+#define APPLE_SPI_IE_XFER 0x130
+#define APPLE_SPI_IF_XFER 0x134
+#define APPLE_SPI_XFER_RXCOMPLETE BIT(0)
+#define APPLE_SPI_XFER_TXCOMPLETE BIT(1)
+
+#define APPLE_SPI_IE_FIFO 0x138
+#define APPLE_SPI_IF_FIFO 0x13c
+#define APPLE_SPI_FIFO_RXTHRESH BIT(4)
+#define APPLE_SPI_FIFO_TXTHRESH BIT(5)
+#define APPLE_SPI_FIFO_RXFULL BIT(8)
+#define APPLE_SPI_FIFO_TXEMPTY BIT(9)
+#define APPLE_SPI_FIFO_RXUNDERRUN BIT(16)
+#define APPLE_SPI_FIFO_TXOVERFLOW BIT(17)
+
+#define APPLE_SPI_SHIFTCFG 0x150
+#define APPLE_SPI_SHIFTCFG_CLK_ENABLE BIT(0)
+#define APPLE_SPI_SHIFTCFG_CS_ENABLE BIT(1)
+#define APPLE_SPI_SHIFTCFG_AND_CLK_DATA BIT(8)
+#define APPLE_SPI_SHIFTCFG_CS_AS_DATA BIT(9)
+#define APPLE_SPI_SHIFTCFG_TX_ENABLE BIT(10)
+#define APPLE_SPI_SHIFTCFG_RX_ENABLE BIT(11)
+#define APPLE_SPI_SHIFTCFG_BITS GENMASK(21, 16)
+#define APPLE_SPI_SHIFTCFG_OVERRIDE_CS BIT(24)
+
+#define APPLE_SPI_PINCFG 0x154
+#define APPLE_SPI_PINCFG_KEEP_CLK BIT(0)
+#define APPLE_SPI_PINCFG_KEEP_CS BIT(1)
+#define APPLE_SPI_PINCFG_KEEP_MOSI BIT(2)
+#define APPLE_SPI_PINCFG_CLK_IDLE_VAL BIT(8)
+#define APPLE_SPI_PINCFG_CS_IDLE_VAL BIT(9)
+#define APPLE_SPI_PINCFG_MOSI_IDLE_VAL BIT(10)
+
+#define APPLE_SPI_DELAY_PRE 0x160
+#define APPLE_SPI_DELAY_POST 0x168
+#define APPLE_SPI_DELAY_ENABLE BIT(0)
+#define APPLE_SPI_DELAY_NO_INTERBYTE BIT(1)
+#define APPLE_SPI_DELAY_SET_SCK BIT(4)
+#define APPLE_SPI_DELAY_SET_MOSI BIT(6)
+#define APPLE_SPI_DELAY_SCK_VAL BIT(8)
+#define APPLE_SPI_DELAY_MOSI_VAL BIT(12)
+
+#define APPLE_SPI_FIFO_DEPTH 16
+
+/*
+ * The slowest refclock available is 24MHz, the highest divider is 0x7ff,
+ * the largest word size is 32 bits, the FIFO depth is 16, the maximum
+ * intra-word delay is 0xffff refclocks. So the maximum time a transfer
+ * cycle can take is:
+ *
+ * (0x7ff * 32 + 0xffff) * 16 / 24e6 Hz ~= 87ms
+ *
+ * Double it and round it up to 200ms for good measure.
+ */
+#define APPLE_SPI_TIMEOUT_MS 200
+
+struct apple_spi {
+ void __iomem *regs; /* MMIO register address */
+ struct clk *clk; /* bus clock */
+ struct completion done; /* wake-up from interrupt */
+};
+
+static inline void reg_write(struct apple_spi *spi, int offset, u32 value)
+{
+ writel_relaxed(value, spi->regs + offset);
+}
+
+static inline u32 reg_read(struct apple_spi *spi, int offset)
+{
+ return readl_relaxed(spi->regs + offset);
+}
+
+static inline void reg_mask(struct apple_spi *spi, int offset, u32 clear, u32 set)
+{
+ u32 val = reg_read(spi, offset);
+
+ val &= ~clear;
+ val |= set;
+ reg_write(spi, offset, val);
+}
+
+static void apple_spi_init(struct apple_spi *spi)
+{
+ /* Set CS high (inactive) and disable override and auto-CS */
+ reg_write(spi, APPLE_SPI_PIN, APPLE_SPI_PIN_CS);
+ reg_mask(spi, APPLE_SPI_SHIFTCFG, APPLE_SPI_SHIFTCFG_OVERRIDE_CS, 0);
+ reg_mask(spi, APPLE_SPI_PINCFG, APPLE_SPI_PINCFG_CS_IDLE_VAL, APPLE_SPI_PINCFG_KEEP_CS);
+
+ /* Reset FIFOs */
+ reg_write(spi, APPLE_SPI_CTRL, APPLE_SPI_CTRL_RX_RESET | APPLE_SPI_CTRL_TX_RESET);
+
+ /* Configure defaults */
+ reg_write(spi, APPLE_SPI_CFG,
+ FIELD_PREP(APPLE_SPI_CFG_FIFO_THRESH, APPLE_SPI_CFG_FIFO_THRESH_8B) |
+ FIELD_PREP(APPLE_SPI_CFG_MODE, APPLE_SPI_CFG_MODE_IRQ) |
+ FIELD_PREP(APPLE_SPI_CFG_WORD_SIZE, APPLE_SPI_CFG_WORD_SIZE_8B));
+
+ /* Disable IRQs */
+ reg_write(spi, APPLE_SPI_IE_FIFO, 0);
+ reg_write(spi, APPLE_SPI_IE_XFER, 0);
+
+ /* Disable delays */
+ reg_write(spi, APPLE_SPI_DELAY_PRE, 0);
+ reg_write(spi, APPLE_SPI_DELAY_POST, 0);
+}
+
+static int apple_spi_prepare_message(struct spi_controller *ctlr, struct spi_message *msg)
+{
+ struct apple_spi *spi = spi_controller_get_devdata(ctlr);
+ struct spi_device *device = msg->spi;
+
+ u32 cfg = ((device->mode & SPI_CPHA ? APPLE_SPI_CFG_CPHA : 0) |
+ (device->mode & SPI_CPOL ? APPLE_SPI_CFG_CPOL : 0) |
+ (device->mode & SPI_LSB_FIRST ? APPLE_SPI_CFG_LSB_FIRST : 0));
+
+ /* Update core config */
+ reg_mask(spi, APPLE_SPI_CFG,
+ APPLE_SPI_CFG_CPHA | APPLE_SPI_CFG_CPOL | APPLE_SPI_CFG_LSB_FIRST, cfg);
+
+ return 0;
+}
+
+static void apple_spi_set_cs(struct spi_device *device, bool is_high)
+{
+ struct apple_spi *spi = spi_controller_get_devdata(device->controller);
+
+ reg_mask(spi, APPLE_SPI_PIN, APPLE_SPI_PIN_CS, is_high ? APPLE_SPI_PIN_CS : 0);
+}
+
+static bool apple_spi_prep_transfer(struct apple_spi *spi, struct spi_transfer *t)
+{
+ u32 cr, fifo_threshold;
+
+ /* Calculate and program the clock rate */
+ cr = DIV_ROUND_UP(clk_get_rate(spi->clk), t->speed_hz);
+ reg_write(spi, APPLE_SPI_CLKDIV, min_t(u32, cr, APPLE_SPI_CLKDIV_MAX));
+
+ /* Update bits per word */
+ reg_mask(spi, APPLE_SPI_SHIFTCFG, APPLE_SPI_SHIFTCFG_BITS,
+ FIELD_PREP(APPLE_SPI_SHIFTCFG_BITS, t->bits_per_word));
+
+ /* We will want to poll if the time we need to wait is
+ * less than the context switching time.
+ * Let's call that threshold 5us. The operation will take:
+ * bits_per_word * fifo_threshold / hz <= 5 * 10^-6
+ * 200000 * bits_per_word * fifo_threshold <= hz
+ */
+ fifo_threshold = APPLE_SPI_FIFO_DEPTH / 2;
+ return (200000 * t->bits_per_word * fifo_threshold) <= t->speed_hz;
+}
+
+static irqreturn_t apple_spi_irq(int irq, void *dev_id)
+{
+ struct apple_spi *spi = dev_id;
+ u32 fifo = reg_read(spi, APPLE_SPI_IF_FIFO) & reg_read(spi, APPLE_SPI_IE_FIFO);
+ u32 xfer = reg_read(spi, APPLE_SPI_IF_XFER) & reg_read(spi, APPLE_SPI_IE_XFER);
+
+ if (fifo || xfer) {
+ /* Disable interrupts until next transfer */
+ reg_write(spi, APPLE_SPI_IE_XFER, 0);
+ reg_write(spi, APPLE_SPI_IE_FIFO, 0);
+ complete(&spi->done);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int apple_spi_wait(struct apple_spi *spi, u32 fifo_bit, u32 xfer_bit, int poll)
+{
+ int ret = 0;
+
+ if (poll) {
+ u32 fifo, xfer;
+ unsigned long timeout = jiffies + APPLE_SPI_TIMEOUT_MS * HZ / 1000;
+
+ do {
+ fifo = reg_read(spi, APPLE_SPI_IF_FIFO);
+ xfer = reg_read(spi, APPLE_SPI_IF_XFER);
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ } while (!((fifo & fifo_bit) || (xfer & xfer_bit)));
+ } else {
+ reinit_completion(&spi->done);
+ reg_write(spi, APPLE_SPI_IE_XFER, xfer_bit);
+ reg_write(spi, APPLE_SPI_IE_FIFO, fifo_bit);
+
+ if (!wait_for_completion_timeout(&spi->done,
+ msecs_to_jiffies(APPLE_SPI_TIMEOUT_MS)))
+ ret = -ETIMEDOUT;
+
+ reg_write(spi, APPLE_SPI_IE_XFER, 0);
+ reg_write(spi, APPLE_SPI_IE_FIFO, 0);
+ }
+
+ return ret;
+}
+
+static void apple_spi_tx(struct apple_spi *spi, const void **tx_ptr, u32 *left,
+ unsigned int bytes_per_word)
+{
+ u32 inuse, words, wrote;
+
+ if (!*tx_ptr)
+ return;
+
+ inuse = FIELD_GET(APPLE_SPI_FIFOSTAT_LEVEL_TX, reg_read(spi, APPLE_SPI_FIFOSTAT));
+ words = wrote = min_t(u32, *left, APPLE_SPI_FIFO_DEPTH - inuse);
+
+ if (!words)
+ return;
+
+ *left -= words;
+
+ switch (bytes_per_word) {
+ case 1: {
+ const u8 *p = *tx_ptr;
+
+ while (words--)
+ reg_write(spi, APPLE_SPI_TXDATA, *p++);
+ break;
+ }
+ case 2: {
+ const u16 *p = *tx_ptr;
+
+ while (words--)
+ reg_write(spi, APPLE_SPI_TXDATA, *p++);
+ break;
+ }
+ case 4: {
+ const u32 *p = *tx_ptr;
+
+ while (words--)
+ reg_write(spi, APPLE_SPI_TXDATA, *p++);
+ break;
+ }
+ default:
+ WARN_ON(1);
+ }
+
+ *tx_ptr = ((u8 *)*tx_ptr) + bytes_per_word * wrote;
+}
+
+static void apple_spi_rx(struct apple_spi *spi, void **rx_ptr, u32 *left,
+ unsigned int bytes_per_word)
+{
+ u32 words, read;
+
+ if (!*rx_ptr)
+ return;
+
+ words = read = FIELD_GET(APPLE_SPI_FIFOSTAT_LEVEL_RX, reg_read(spi, APPLE_SPI_FIFOSTAT));
+ WARN_ON(words > *left);
+
+ if (!words)
+ return;
+
+ *left -= min_t(u32, *left, words);
+
+ switch (bytes_per_word) {
+ case 1: {
+ u8 *p = *rx_ptr;
+
+ while (words--)
+ *p++ = reg_read(spi, APPLE_SPI_RXDATA);
+ break;
+ }
+ case 2: {
+ u16 *p = *rx_ptr;
+
+ while (words--)
+ *p++ = reg_read(spi, APPLE_SPI_RXDATA);
+ break;
+ }
+ case 4: {
+ u32 *p = *rx_ptr;
+
+ while (words--)
+ *p++ = reg_read(spi, APPLE_SPI_RXDATA);
+ break;
+ }
+ default:
+ WARN_ON(1);
+ }
+
+ *rx_ptr = ((u8 *)*rx_ptr) + bytes_per_word * read;
+}
+
+static int apple_spi_transfer_one(struct spi_controller *ctlr, struct spi_device *device,
+ struct spi_transfer *t)
+{
+ struct apple_spi *spi = spi_controller_get_devdata(ctlr);
+ bool poll = apple_spi_prep_transfer(spi, t);
+ const void *tx_ptr = t->tx_buf;
+ void *rx_ptr = t->rx_buf;
+ unsigned int bytes_per_word;
+ u32 words, remaining_tx, remaining_rx;
+ u32 xfer_flags = 0;
+ u32 fifo_flags;
+ int retries = 100;
+ int ret = 0;
+
+ if (t->bits_per_word > 16)
+ bytes_per_word = 4;
+ else if (t->bits_per_word > 8)
+ bytes_per_word = 2;
+ else
+ bytes_per_word = 1;
+
+ words = t->len / bytes_per_word;
+ remaining_tx = tx_ptr ? words : 0;
+ remaining_rx = rx_ptr ? words : 0;
+
+ /* Reset FIFOs */
+ reg_write(spi, APPLE_SPI_CTRL, APPLE_SPI_CTRL_RX_RESET | APPLE_SPI_CTRL_TX_RESET);
+
+ /* Clear IRQ flags */
+ reg_write(spi, APPLE_SPI_IF_XFER, ~0);
+ reg_write(spi, APPLE_SPI_IF_FIFO, ~0);
+
+ /* Determine transfer completion flags we wait for */
+ if (tx_ptr)
+ xfer_flags |= APPLE_SPI_XFER_TXCOMPLETE;
+ if (rx_ptr)
+ xfer_flags |= APPLE_SPI_XFER_RXCOMPLETE;
+
+ /* Set transfer length */
+ reg_write(spi, APPLE_SPI_TXCNT, remaining_tx);
+ reg_write(spi, APPLE_SPI_RXCNT, remaining_rx);
+
+ /* Prime transmit FIFO */
+ apple_spi_tx(spi, &tx_ptr, &remaining_tx, bytes_per_word);
+
+ /* Start transfer */
+ reg_write(spi, APPLE_SPI_CTRL, APPLE_SPI_CTRL_RUN);
+
+ /* TX again since a few words get popped off immediately */
+ apple_spi_tx(spi, &tx_ptr, &remaining_tx, bytes_per_word);
+
+ while (xfer_flags) {
+ fifo_flags = 0;
+
+ if (remaining_tx)
+ fifo_flags |= APPLE_SPI_FIFO_TXTHRESH;
+ if (remaining_rx)
+ fifo_flags |= APPLE_SPI_FIFO_RXTHRESH;
+
+ /* Wait for anything to happen */
+ ret = apple_spi_wait(spi, fifo_flags, xfer_flags, poll);
+ if (ret) {
+ dev_err(&ctlr->dev, "transfer timed out (remaining %d tx, %d rx)\n",
+ remaining_tx, remaining_rx);
+ goto err;
+ }
+
+ /* Stop waiting on transfer halves once they complete */
+ xfer_flags &= ~reg_read(spi, APPLE_SPI_IF_XFER);
+
+ /* Transmit and receive everything we can */
+ apple_spi_tx(spi, &tx_ptr, &remaining_tx, bytes_per_word);
+ apple_spi_rx(spi, &rx_ptr, &remaining_rx, bytes_per_word);
+ }
+
+ /*
+ * Sometimes the transfer completes before the last word is in the RX FIFO.
+ * Normally one retry is all it takes to get the last word out.
+ */
+ while (remaining_rx && retries--)
+ apple_spi_rx(spi, &rx_ptr, &remaining_rx, bytes_per_word);
+
+ if (remaining_tx)
+ dev_err(&ctlr->dev, "transfer completed with %d words left to transmit\n",
+ remaining_tx);
+ if (remaining_rx)
+ dev_err(&ctlr->dev, "transfer completed with %d words left to receive\n",
+ remaining_rx);
+
+err:
+ fifo_flags = reg_read(spi, APPLE_SPI_IF_FIFO);
+ WARN_ON(fifo_flags & APPLE_SPI_FIFO_TXOVERFLOW);
+ WARN_ON(fifo_flags & APPLE_SPI_FIFO_RXUNDERRUN);
+
+ /* Stop transfer */
+ reg_write(spi, APPLE_SPI_CTRL, 0);
+
+ return ret;
+}
+
+static void apple_spi_clk_disable_unprepare(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static int apple_spi_probe(struct platform_device *pdev)
+{
+ struct apple_spi *spi;
+ int ret, irq;
+ struct spi_controller *ctlr;
+
+ ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(struct apple_spi));
+ if (!ctlr)
+ return dev_err_probe(&pdev->dev, -ENOMEM, "out of memory\n");
+
+ spi = spi_controller_get_devdata(ctlr);
+ init_completion(&spi->done);
+ platform_set_drvdata(pdev, ctlr);
+
+ spi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(spi->regs))
+ return PTR_ERR(spi->regs);
+
+ spi->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(spi->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), "Unable to find bus clock\n");
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ return irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, apple_spi_irq, 0,
+ dev_name(&pdev->dev), spi);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Unable to bind to interrupt\n");
+
+ ret = clk_prepare_enable(spi->clk);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Unable to enable bus clock\n");
+
+ ret = devm_add_action_or_reset(&pdev->dev, apple_spi_clk_disable_unprepare, spi->clk);
+ if (ret)
+ return ret;
+
+ ctlr->dev.of_node = pdev->dev.of_node;
+ ctlr->bus_num = pdev->id;
+ ctlr->num_chipselect = 1;
+ ctlr->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST;
+ ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
+ ctlr->flags = 0;
+ ctlr->prepare_message = apple_spi_prepare_message;
+ ctlr->set_cs = apple_spi_set_cs;
+ ctlr->transfer_one = apple_spi_transfer_one;
+ ctlr->auto_runtime_pm = true;
+
+ pm_runtime_set_active(&pdev->dev);
+ devm_pm_runtime_enable(&pdev->dev);
+
+ apple_spi_init(spi);
+
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "devm_spi_register_controller failed\n");
+
+ return 0;
+}
+
+static const struct of_device_id apple_spi_of_match[] = {
+ { .compatible = "apple,spi", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, apple_spi_of_match);
+
+static struct platform_driver apple_spi_driver = {
+ .probe = apple_spi_probe,
+ .driver = {
+ .name = "apple-spi",
+ .owner = THIS_MODULE,
+ .of_match_table = apple_spi_of_match,
+ },
+};
+module_platform_driver(apple_spi_driver);
+
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
+MODULE_DESCRIPTION("Apple SoC SPI driver");
+MODULE_LICENSE("GPL");
--
2.34.1

View File

@ -0,0 +1,93 @@
From c67e6dd3d9c5590394faf5138021ba7ebe306343 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:50:39 +0100
Subject: [PATCH 070/171] dt-bindings: dma: Add apple,admac binding
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Audio DMA Controller (ADMAC) is used to load and store audio
samples from/to system memory. It is present on Apple SoCs from
the "Apple Silicon" family.
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
.../devicetree/bindings/dma/apple,admac.yaml | 65 +++++++++++++++++++
1 file changed, 65 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/apple,admac.yaml
diff --git a/Documentation/devicetree/bindings/dma/apple,admac.yaml b/Documentation/devicetree/bindings/dma/apple,admac.yaml
new file mode 100644
index 000000000000..34ede3b0de2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/apple,admac.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/apple,admac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple Audio DMA Controller (ADMAC)
+
+description: |
+ The Audio DMA Controller (ADMAC) is used to load and store audio
+ samples from/to system memory. It is present on Apple SoCs
+ from the "Apple Silicon" family.
+
+maintainers:
+ - Martin Povišer <povik@protonmail.com>
+
+allOf:
+ - $ref: "dma-controller.yaml#"
+
+properties:
+ compatible:
+ items:
+ - const: apple,t8103-admac
+ - const: apple,admac
+
+ reg:
+ maxItems: 1
+
+ '#dma-cells':
+ const: 1
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - '#dma-cells'
+ - dma-channels
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/apple-aic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ dart_sio: iommu@235004000 {
+ compatible = "apple,t8103-dart", "apple,dart";
+ reg = <0x2 0x35004000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 635 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ };
+
+ admac: dma-controller@238200000 {
+ compatible = "apple,t8103-admac", "apple,admac";
+ reg = <0x2 0x38200000 0x0 0x34000>;
+ dma-channels = <12>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 626 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ iommus = <&dart_sio 2>;
+ };
\ No newline at end of file
--
2.34.1

View File

@ -0,0 +1,806 @@
From 594ea25c7f3f1ee8d0e952c6547bcd06843f9045 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:49:23 +0100
Subject: [PATCH 071/171] dmaengine: apple-admac: Add Apple ADMAC driver
Add driver for Audio DMA Controller present on Apple SoCs
from the "Apple Silicon" family.
---
drivers/dma/Kconfig | 8 +
drivers/dma/Makefile | 1 +
drivers/dma/apple-admac.c | 752 ++++++++++++++++++++++++++++++++++++++
3 files changed, 761 insertions(+)
create mode 100644 drivers/dma/apple-admac.c
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 487ed4ddc3be..bda78b8172d4 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -85,6 +85,14 @@ config AMCC_PPC440SPE_ADMA
help
Enable support for the AMCC PPC440SPe RAID engines.
+config APPLE_ADMAC
+ tristate "Apple ADMAC support"
+ depends on ARCH_APPLE || COMPILE_TEST
+ select DMA_ENGINE
+ default ARCH_APPLE
+ help
+ Enable support for Audio DMA Controller found on Apple Silicon chips.
+
config AT_HDMAC
tristate "Atmel AHB DMA support"
depends on ARCH_AT91
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 2f1b87ffd7ab..10f7d4241001 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ALTERA_MSGDMA) += altera-msgdma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
obj-$(CONFIG_AMD_PTDMA) += ptdma/
+obj-$(CONFIG_APPLE_ADMAC) += apple-admac.o
obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
obj-$(CONFIG_AT_XDMAC) += at_xdmac.o
obj-$(CONFIG_AXI_DMAC) += dma-axi-dmac.o
diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
new file mode 100644
index 000000000000..aa4c07bcb72a
--- /dev/null
+++ b/drivers/dma/apple-admac.c
@@ -0,0 +1,752 @@
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+
+#include "dmaengine.h"
+
+#define NCHANNELS_MAX 64
+
+#define RING_WRITE_SLOT GENMASK(1, 0)
+#define RING_READ_SLOT GENMASK(5, 4)
+#define RING_FULL BIT(9)
+#define RING_EMPTY BIT(8)
+#define RING_ERR BIT(10)
+
+#define STATUS_DESC_DONE BIT(0)
+#define STATUS_ERR BIT(6)
+
+#define FLAG_DESC_NOTIFY BIT(16)
+
+#define REG_TX_START 0x0000
+#define REG_TX_STOP 0x0004
+#define REG_RX_START 0x0008
+#define REG_RX_STOP 0x000c
+
+#define REG_CHAN_CTL(ch) (0x8000 + (ch)*0x200)
+#define REG_CHAN_CTL_RST_RINGS BIT(0)
+
+#define REG_DESC_RING(ch) (0x8070 + (ch)*0x200)
+#define REG_REPORT_RING(ch) (0x8074 + (ch)*0x200)
+
+#define REG_RESIDUE(ch) (0x8064 + (ch)*0x200)
+
+#define REG_BUS_WIDTH(ch) (0x8040 + (ch)*0x200)
+
+#define BUS_WIDTH_8BIT 0x00
+#define BUS_WIDTH_16BIT 0x01
+#define BUS_WIDTH_32BIT 0x02
+#define BUS_WIDTH_FRAME_2_WORDS 0x10
+#define BUS_WIDTH_FRAME_4_WORDS 0x20
+
+#define REG_CHAN_BURSTSIZE(ch) (0x8054 + (ch)*0x200)
+
+#define REG_DESC_WRITE(ch) (0x10000 + (ch / 2) * 0x4 + (ch & 1) * 0x4000)
+#define REG_REPORT_READ(ch) (0x10100 + (ch / 2) * 0x4 + (ch & 1) * 0x4000)
+
+#define IRQ_INDEX_MAX 3
+
+#define REG_TX_INTSTATE(idx) (0x0030 + (idx) * 4)
+#define REG_RX_INTSTATE(idx) (0x0040 + (idx) * 4)
+#define REG_CHAN_INTSTATUS(ch,idx) (0x8010 + (ch) * 0x200 + (idx) * 4)
+#define REG_CHAN_INTMASK(ch,idx) (0x8020 + (ch) * 0x200 + (idx) * 4)
+
+struct admac_data;
+struct admac_tx;
+
+struct admac_chan {
+ int no;
+ struct admac_data *host;
+ struct dma_chan chan;
+ struct tasklet_struct tasklet;
+
+ spinlock_t lock;
+ struct admac_tx *current_tx;
+ int nperiod_acks;
+
+ struct list_head submitted;
+ struct list_head issued;
+};
+
+struct admac_data {
+ struct dma_device dma;
+ struct device *dev;
+ __iomem void *base;
+
+ int irq_index;
+ int nchannels;
+ struct admac_chan channels[];
+};
+
+struct admac_tx {
+ struct dma_async_tx_descriptor tx;
+ bool cyclic;
+ dma_addr_t buf_addr;
+ dma_addr_t buf_end;
+ size_t buf_len;
+ size_t period_len;
+
+ size_t submitted_pos;
+ size_t reclaimed_pos;
+
+ struct list_head node;
+};
+
+static void admac_poke(struct admac_data *ad, int reg, u32 val)
+{
+ writel_relaxed(val, ad->base + reg);
+}
+
+static u32 admac_peek(struct admac_data *ad, int reg)
+{
+ return readl_relaxed(ad->base + reg);
+}
+
+static void admac_modify(struct admac_data *ad, int reg, u32 mask, u32 val)
+{
+ void __iomem *addr = ad->base + reg;
+ u32 curr = readl_relaxed(addr);
+
+ writel_relaxed((curr & ~mask) | (val & mask), addr);
+}
+
+static struct admac_chan *to_admac_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct admac_chan, chan);
+}
+
+static struct admac_tx *to_admac_tx(struct dma_async_tx_descriptor *tx)
+{
+ return container_of(tx, struct admac_tx, tx);
+}
+
+static enum dma_transfer_direction admac_chan_direction(int channo)
+{
+ return (channo & 1) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
+}
+
+static dma_cookie_t admac_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct admac_tx *adtx = to_admac_tx(tx);
+ struct admac_chan *adchan = to_admac_chan(tx->chan);
+ unsigned long flags;
+ dma_cookie_t cookie;
+
+ spin_lock_irqsave(&adchan->lock, flags);
+ cookie = dma_cookie_assign(tx);
+ list_add_tail(&adtx->node, &adchan->submitted);
+ spin_unlock_irqrestore(&adchan->lock, flags);
+
+ return cookie;
+}
+
+static int admac_desc_free(struct dma_async_tx_descriptor *tx)
+{
+ struct admac_tx *adtx = to_admac_tx(tx);
+ devm_kfree(to_admac_chan(tx->chan)->host->dev, adtx);
+ return 0;
+}
+
+static struct dma_async_tx_descriptor *admac_prep_dma_cyclic(
+ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+ size_t period_len, enum dma_transfer_direction direction,
+ unsigned long flags)
+{
+ struct admac_chan *adchan = container_of(chan, struct admac_chan, chan);
+ struct admac_tx *adtx;
+
+ if (direction != admac_chan_direction(adchan->no))
+ return NULL;
+
+ adtx = devm_kzalloc(adchan->host->dev, sizeof(*adtx), GFP_NOWAIT);
+ if (!adtx)
+ return NULL;
+
+ adtx->cyclic = true;
+
+ adtx->buf_addr = buf_addr;
+ adtx->buf_len = buf_len;
+ adtx->buf_end = buf_addr + buf_len;
+ adtx->period_len = period_len;
+
+ adtx->submitted_pos = 0;
+ adtx->reclaimed_pos = 0;
+
+ dma_async_tx_descriptor_init(&adtx->tx, chan);
+ adtx->tx.tx_submit = admac_tx_submit;
+ adtx->tx.desc_free = admac_desc_free;
+
+ return &adtx->tx;
+}
+
+/*
+ * Write one hardware descriptor for a dmaegine cyclic transaction.
+ */
+static void admac_cyclic_write_one_desc(struct admac_data *ad, int channo,
+ struct admac_tx *tx)
+{
+ dma_addr_t addr;
+
+ if (WARN_ON(!tx->cyclic))
+ return;
+
+ addr = tx->buf_addr + (tx->submitted_pos % tx->buf_len);
+ WARN_ON(addr + tx->period_len > tx->buf_end);
+
+ dev_dbg(ad->dev, "ch%d descriptor: addr=0x%llx len=0x%x flags=0x%lx\n",
+ channo, addr, (u32) tx->period_len, FLAG_DESC_NOTIFY);
+
+ admac_poke(ad, REG_DESC_WRITE(channo), addr);
+ admac_poke(ad, REG_DESC_WRITE(channo), addr >> 32);
+ admac_poke(ad, REG_DESC_WRITE(channo), tx->period_len);
+ admac_poke(ad, REG_DESC_WRITE(channo), FLAG_DESC_NOTIFY);
+
+ tx->submitted_pos += tx->period_len;
+ tx->submitted_pos %= 2 * tx->buf_len;
+}
+
+/*
+ * Write all the hardware descriptors for a cyclic transaction
+ * there is space for.
+ */
+static void admac_cyclic_write_desc(struct admac_data *ad, int channo,
+ struct admac_tx *tx)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (admac_peek(ad, REG_DESC_RING(channo)) & RING_FULL)
+ break;
+ admac_cyclic_write_one_desc(ad, channo, tx);
+ }
+}
+
+static int admac_alloc_chan_resources(struct dma_chan *chan)
+{
+ return 0;
+}
+
+static void admac_free_chan_resources(struct dma_chan *chan)
+{
+ // TODO
+}
+
+static int admac_ring_noccupied_slots(int ringval)
+{
+ int wrslot = FIELD_GET(RING_WRITE_SLOT, ringval);
+ int rdslot = FIELD_GET(RING_READ_SLOT, ringval);
+
+ if (wrslot != rdslot) {
+ return (wrslot + 4 - rdslot) % 4;
+ } else {
+ WARN_ON((ringval & (RING_FULL | RING_EMPTY)) == 0);
+
+ if (ringval & RING_FULL)
+ return 4;
+ else
+ return 0;
+ }
+}
+
+/*
+ * Read from hardware the residue of a cyclic dmaengine transaction.
+ */
+u32 admac_cyclic_read_residue(struct admac_data *ad, int channo, struct admac_tx *adtx)
+{
+ u32 ring1, ring2;
+ u32 residue1, residue2;
+ int nreports;
+ size_t pos;
+
+ ring1 = admac_peek(ad, REG_REPORT_RING(channo));
+ residue1 = admac_peek(ad, REG_RESIDUE(channo));
+ ring2 = admac_peek(ad, REG_REPORT_RING(channo));
+ residue2 = admac_peek(ad, REG_RESIDUE(channo));
+
+ if (residue2 > residue1) {
+ // engine must have loaded next descriptor between the two residue reads
+ nreports = admac_ring_noccupied_slots(ring1) + 1;
+ } else {
+ // no descriptor load between the two reads, ring2 is safe to use
+ nreports = admac_ring_noccupied_slots(ring2);
+ }
+
+ pos = adtx->reclaimed_pos + adtx->period_len * (nreports + 1) \
+ - residue2;
+
+ return adtx->buf_len - pos % adtx->buf_len;
+}
+
+static enum dma_status admac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct admac_chan *adchan = to_admac_chan(chan);
+ struct admac_data *ad = adchan->host;
+ struct admac_tx *adtx;
+
+ enum dma_status ret;
+ size_t residue;
+ unsigned long flags;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_COMPLETE || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&adchan->lock, flags);
+ adtx = adchan->current_tx;
+
+ if (adtx && adtx->tx.cookie == cookie) {
+ ret = DMA_IN_PROGRESS;
+ residue = admac_cyclic_read_residue(ad, adchan->no, adtx);
+ } else {
+ ret = DMA_IN_PROGRESS;
+ residue = 0;
+ list_for_each_entry(adtx, &adchan->issued, node) {
+ if (adtx->tx.cookie == cookie) {
+ residue = adtx->buf_len;
+ break;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&adchan->lock, flags);
+
+ dma_set_residue(txstate, residue);
+ return ret;
+}
+
+static void admac_start_chan(struct admac_chan *adchan)
+{
+ u32 startbit = 1 << (adchan->no / 2);
+ switch (admac_chan_direction(adchan->no)) {
+ case DMA_MEM_TO_DEV:
+ admac_poke(adchan->host, REG_TX_START, startbit);
+ break;
+ case DMA_DEV_TO_MEM:
+ admac_poke(adchan->host, REG_RX_START, startbit);
+ break;
+ default:
+ break;
+ }
+ dev_dbg(adchan->host->dev, "ch%d start\n", adchan->no);
+}
+
+static void admac_stop_chan(struct admac_chan *adchan)
+{
+ u32 stopbit = 1 << (adchan->no / 2);
+ switch (admac_chan_direction(adchan->no)) {
+ case DMA_MEM_TO_DEV:
+ admac_poke(adchan->host, REG_TX_STOP, stopbit);
+ break;
+ case DMA_DEV_TO_MEM:
+ admac_poke(adchan->host, REG_RX_STOP, stopbit);
+ break;
+ default:
+ break;
+ }
+ dev_dbg(adchan->host->dev, "ch%d stop\n", adchan->no);
+}
+
+static void admac_start_current_tx(struct admac_chan *adchan)
+{
+ struct admac_data *ad = adchan->host;
+ int ch = adchan->no;
+
+ admac_poke(ad, REG_CHAN_INTSTATUS(ch, ad->irq_index),
+ STATUS_DESC_DONE | STATUS_ERR);
+ admac_poke(ad, REG_CHAN_CTL(ch), REG_CHAN_CTL_RST_RINGS);
+ admac_poke(ad, REG_CHAN_CTL(ch), 0);
+
+ admac_cyclic_write_one_desc(ad, ch, adchan->current_tx);
+ admac_start_chan(adchan);
+ admac_cyclic_write_desc(ad, ch, adchan->current_tx);
+}
+
+static void admac_issue_pending(struct dma_chan *chan)
+{
+ struct admac_chan *adchan = to_admac_chan(chan);
+ struct admac_tx *tx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adchan->lock, flags);
+ list_splice_tail_init(&adchan->submitted, &adchan->issued);
+ if (!list_empty(&adchan->issued) && !adchan->current_tx) {
+ tx = list_first_entry(&adchan->issued, struct admac_tx, node);
+ list_del(&tx->node);
+
+ adchan->current_tx = tx;
+ adchan->nperiod_acks = 0;
+ admac_start_current_tx(adchan);
+ }
+ spin_unlock_irqrestore(&adchan->lock, flags);
+}
+
+static int admac_pause(struct dma_chan *chan)
+{
+ struct admac_chan *adchan = to_admac_chan(chan);
+
+ admac_stop_chan(adchan);
+
+ return 0;
+}
+
+static int admac_resume(struct dma_chan *chan)
+{
+ struct admac_chan *adchan = to_admac_chan(chan);
+
+ admac_start_chan(adchan);
+
+ return 0;
+}
+
+static int admac_terminate_all(struct dma_chan *chan)
+{
+ struct admac_chan *adchan = to_admac_chan(chan);
+ struct admac_tx *adtx, *_adtx;
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&adchan->lock, flags);
+ admac_stop_chan(adchan);
+ adchan->current_tx = NULL;
+ list_splice_tail_init(&adchan->submitted, &head);
+ list_splice_tail_init(&adchan->issued, &head);
+ spin_unlock_irqrestore(&adchan->lock, flags);
+
+ list_for_each_entry_safe(adtx, _adtx, &head, node) {
+ list_del(&adtx->node);
+ admac_desc_free(&adtx->tx);
+ }
+
+ return 0;
+}
+
+static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct admac_data *ad = (struct admac_data*) ofdma->of_dma_data;
+ unsigned int index;
+
+ if (dma_spec->args_count != 1)
+ return NULL;
+
+ index = dma_spec->args[0];
+
+ if (index >= ad->nchannels) {
+ dev_err(ad->dev, "channel index %u out of bounds\n", index);
+ return NULL;
+ }
+
+ return &ad->channels[index].chan;
+}
+
+static int admac_drain_reports(struct admac_data *ad, int channo)
+{
+ int count;
+
+ for (count = 0; count < 4; count++) {
+ u32 countval_hi, countval_lo, unk1, flags;
+
+ if (admac_peek(ad, REG_REPORT_RING(channo)) & RING_EMPTY)
+ break;
+
+ countval_lo = admac_peek(ad, REG_REPORT_READ(channo));
+ countval_hi = admac_peek(ad, REG_REPORT_READ(channo));
+ unk1 = admac_peek(ad, REG_REPORT_READ(channo));
+ flags = admac_peek(ad, REG_REPORT_READ(channo));
+
+ dev_dbg(ad->dev, "ch%d report: countval=0x%llx unk1=0x%x flags=0x%x\n",
+ channo, ((u64) countval_hi) << 32 | countval_lo, unk1, flags);
+ }
+
+ return count;
+}
+
+static void admac_handle_status_err(struct admac_data *ad, int channo)
+{
+ bool handled = false;
+
+ if (admac_peek(ad, REG_DESC_RING(channo) & RING_ERR)) {
+ admac_poke(ad, REG_DESC_RING(channo), RING_ERR);
+ dev_err(ad->dev, "ch%d descriptor ring error\n", channo);
+ handled = true;
+ }
+
+ if (admac_peek(ad, REG_REPORT_RING(channo)) & RING_ERR) {
+ admac_poke(ad, REG_REPORT_RING(channo), RING_ERR);
+ dev_err(ad->dev, "ch%d report ring error\n", channo);
+ handled = true;
+ }
+
+ if (unlikely(!handled)) {
+ dev_err(ad->dev, "ch%d unknown error, masking future error interrupts\n", channo);
+ admac_modify(ad, REG_CHAN_INTMASK(channo, ad->irq_index), STATUS_ERR, 0);
+ }
+}
+
+static void admac_handle_status_desc_done(struct admac_data *ad, int channo)
+{
+ struct admac_chan *adchan = &ad->channels[channo];
+ unsigned long flags;
+ int nreports;
+
+ admac_poke(ad, REG_CHAN_INTSTATUS(channo, ad->irq_index),
+ STATUS_DESC_DONE);
+
+ spin_lock_irqsave(&adchan->lock, flags);
+ nreports = admac_drain_reports(ad, channo);
+
+ if (adchan->current_tx) {
+ struct admac_tx *tx = adchan->current_tx;
+
+ adchan->nperiod_acks += nreports;
+ tx->reclaimed_pos += nreports * tx->period_len;
+ tx->reclaimed_pos %= 2 * tx->buf_len;
+
+ admac_cyclic_write_desc(ad, channo, tx);
+ tasklet_schedule(&adchan->tasklet);
+ }
+ spin_unlock_irqrestore(&adchan->lock, flags);
+}
+
+static void admac_handle_chan_int(struct admac_data *ad, int no)
+{
+ u32 cause = admac_peek(ad, REG_CHAN_INTSTATUS(no, ad->irq_index));
+
+ if (cause & STATUS_ERR)
+ admac_handle_status_err(ad, no);
+
+ if (cause & STATUS_DESC_DONE)
+ admac_handle_status_desc_done(ad, no);
+}
+
+static irqreturn_t admac_interrupt(int irq, void *devid)
+{
+ struct admac_data *ad = devid;
+ u32 rx_intstate, tx_intstate;
+ int i;
+
+ rx_intstate = admac_peek(ad, REG_RX_INTSTATE(ad->irq_index));
+ tx_intstate = admac_peek(ad, REG_TX_INTSTATE(ad->irq_index));
+
+ for (i = 0; i < ad->nchannels; i += 2)
+ if (tx_intstate & (1 << (i / 2)))
+ admac_handle_chan_int(ad, i);
+
+ for (i = 1; i < ad->nchannels; i += 2)
+ if (rx_intstate & (1 << (i / 2)))
+ admac_handle_chan_int(ad, i);
+
+ return (tx_intstate | rx_intstate) != 0 ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void admac_chan_tasklet(struct tasklet_struct *t)
+{
+ struct admac_chan *adchan = from_tasklet(adchan, t, tasklet);
+ struct admac_tx *adtx;
+ struct dmaengine_desc_callback cb;
+ struct dmaengine_result tx_result;
+ int nacks;
+
+ spin_lock_irq(&adchan->lock);
+ adtx = adchan->current_tx;
+ nacks = adchan->nperiod_acks;
+ adchan->nperiod_acks = 0;
+ spin_unlock_irq(&adchan->lock);
+
+ if (!adtx || !nacks)
+ return;
+
+ tx_result.result = DMA_TRANS_NOERROR;
+ tx_result.residue = 0;
+
+ dmaengine_desc_get_callback(&adtx->tx, &cb);
+ while (nacks--)
+ dmaengine_desc_callback_invoke(&cb, &tx_result);
+}
+
+static int admac_device_config(struct dma_chan *chan,
+ struct dma_slave_config *config)
+{
+ struct admac_chan *adchan = to_admac_chan(chan);
+ struct admac_data *ad = adchan->host;
+ bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV;
+ u32 bus_width = 0;
+
+
+ switch (is_tx ? config->dst_addr_width : config->src_addr_width) {
+ case DMA_SLAVE_BUSWIDTH_1_BYTE:
+ bus_width |= BUS_WIDTH_8BIT;
+ break;
+ case DMA_SLAVE_BUSWIDTH_2_BYTES:
+ bus_width |= BUS_WIDTH_16BIT;
+ break;
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ bus_width |= BUS_WIDTH_32BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (is_tx ? config->dst_port_window_size : config->src_port_window_size) {
+ case 0 ... 1:
+ break;
+ case 2:
+ bus_width |= BUS_WIDTH_FRAME_2_WORDS;
+ break;
+ case 4:
+ bus_width |= BUS_WIDTH_FRAME_4_WORDS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ admac_poke(adchan->host, REG_BUS_WIDTH(adchan->no), bus_width);
+
+ /* TODO: burst size */
+
+ admac_poke(adchan->host, REG_CHAN_BURSTSIZE(adchan->no), 0xc00060);
+
+ /* TODO: this belongs elsewhere */
+ admac_poke(adchan->host, REG_CHAN_INTSTATUS(adchan->no, ad->irq_index),
+ STATUS_DESC_DONE | STATUS_ERR);
+ admac_poke(adchan->host, REG_CHAN_INTMASK(adchan->no, ad->irq_index),
+ STATUS_DESC_DONE | STATUS_ERR);
+ return 0;
+}
+
+static int admac_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct admac_data *ad;
+ struct dma_device *dma;
+ int nchannels;
+ int err, irq, i;
+
+ err = of_property_read_u32(np, "dma-channels", &nchannels);
+ if (err || nchannels > NCHANNELS_MAX) {
+ dev_err(&pdev->dev, "missing or invalid dma-channels property\n");
+ return -EINVAL;
+ }
+
+ ad = devm_kzalloc(&pdev->dev, struct_size(ad, channels, nchannels), GFP_KERNEL);
+ if (!ad)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ad);
+ ad->dev = &pdev->dev;
+ ad->nchannels = nchannels;
+
+ err = of_property_read_u32(np, "apple,internal-irq-destination", &ad->irq_index);
+ if (err || ad->irq_index > IRQ_INDEX_MAX) {
+ dev_err(&pdev->dev, "missing or invalid apple,internal-irq-destination property\n");
+ return -EINVAL;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "unable to obtain interrupt resource\n");
+ return irq;
+ }
+
+ err = devm_request_irq(&pdev->dev, irq, admac_interrupt,
+ 0, dev_name(&pdev->dev), ad);
+ if (err) {
+ dev_err(&pdev->dev, "unable to register interrupt: %d\n", err);
+ return err;
+ }
+
+ ad->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ad->base)) {
+ dev_err(&pdev->dev, "unable to obtain MMIO resource\n");
+ return PTR_ERR(ad->base);
+ }
+
+ dma = &ad->dma;
+
+ dma_cap_set(DMA_PRIVATE, dma->cap_mask);
+ dma_cap_set(DMA_CYCLIC, dma->cap_mask);
+
+ dma->dev = &pdev->dev;
+ dma->device_alloc_chan_resources = admac_alloc_chan_resources;
+ dma->device_free_chan_resources = admac_free_chan_resources;
+ dma->device_tx_status = admac_tx_status;
+ dma->device_issue_pending = admac_issue_pending;
+ dma->device_terminate_all = admac_terminate_all;
+ dma->device_prep_dma_cyclic = admac_prep_dma_cyclic;
+ dma->device_config = admac_device_config;
+ dma->device_pause = admac_pause;
+ dma->device_resume = admac_resume;
+
+ dma->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM);
+ dma->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+
+ INIT_LIST_HEAD(&dma->channels);
+ for (i = 0; i < nchannels; i++) {
+ struct admac_chan *adchan = &ad->channels[i];
+ adchan->host = ad;
+ adchan->no = i;
+ adchan->chan.device = &ad->dma;
+ dma_cookie_init(&adchan->chan);
+ spin_lock_init(&adchan->lock);
+ INIT_LIST_HEAD(&adchan->submitted);
+ INIT_LIST_HEAD(&adchan->issued);
+ list_add_tail(&adchan->chan.device_node, &dma->channels);
+ tasklet_setup(&adchan->tasklet, admac_chan_tasklet);
+ }
+
+ err = dma_async_device_register(&ad->dma);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register DMA device: %d\n", err);
+ return err;
+ }
+
+ err = of_dma_controller_register(pdev->dev.of_node, admac_dma_of_xlate, ad);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register with OF: %d\n", err);
+ dma_async_device_unregister(&ad->dma);
+ return err;
+ }
+
+ dev_dbg(&pdev->dev, "all good, ready to go!\n");
+
+ return 0;
+}
+
+static int admac_remove(struct platform_device *pdev)
+{
+ struct admac_data *ad = platform_get_drvdata(pdev);
+
+ of_dma_controller_free(pdev->dev.of_node);
+ dma_async_device_unregister(&ad->dma);
+
+ return 0;
+}
+
+static const struct of_device_id admac_of_match[] = {
+ { .compatible = "apple,admac", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, admac_of_match);
+
+static struct platform_driver apple_admac_driver = {
+ .driver = {
+ .name = "apple-admac",
+ .of_match_table = admac_of_match,
+ },
+ .probe = admac_probe,
+ .remove = admac_remove,
+};
+module_platform_driver(apple_admac_driver);
+
+MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>");
+MODULE_DESCRIPTION("Driver for Audio DMA Controller (ADMAC) in Apple SoCs");
+MODULE_LICENSE("GPL v2");
--
2.34.1

View File

@ -0,0 +1,99 @@
From 25cfbd57efaf69fbbf65c4db2c4d541b8715e5f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:49:34 +0100
Subject: [PATCH 073/171] ASoC: tas2770: Set correct FSYNC polarity
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fix setting of FSYNC polarity for DAI formats other than I2S. Also
add support for polarity inversion.
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
sound/soc/codecs/tas2770.c | 21 ++++++++++++++++++++-
sound/soc/codecs/tas2770.h | 3 +++
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index c1dbd978d550..2b214223265e 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -337,7 +337,7 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
struct snd_soc_component *component = dai->component;
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
- u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
+ u8 tdm_rx_start_slot = 0, invert_fpol = 0, fpol_preinv = 0, asi_cfg_1 = 0;
int ret;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -349,9 +349,15 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_IF:
+ invert_fpol = 1;
+ fallthrough;
case SND_SOC_DAIFMT_NB_NF:
asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_RSING;
break;
+ case SND_SOC_DAIFMT_IB_IF:
+ invert_fpol = 1;
+ fallthrough;
case SND_SOC_DAIFMT_IB_NF:
asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_FALING;
break;
@@ -369,15 +375,19 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
tdm_rx_start_slot = 1;
+ fpol_preinv = 0;
break;
case SND_SOC_DAIFMT_DSP_A:
tdm_rx_start_slot = 0;
+ fpol_preinv = 1;
break;
case SND_SOC_DAIFMT_DSP_B:
tdm_rx_start_slot = 1;
+ fpol_preinv = 1;
break;
case SND_SOC_DAIFMT_LEFT_J:
tdm_rx_start_slot = 0;
+ fpol_preinv = 1;
break;
default:
dev_err(tas2770->dev,
@@ -391,6 +401,15 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
if (ret < 0)
return ret;
+
+ ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG0,
+ TAS2770_TDM_CFG_REG0_FPOL_MASK,
+ (fpol_preinv ^ invert_fpol)
+ ? TAS2770_TDM_CFG_REG0_FPOL_RSING
+ : TAS2770_TDM_CFG_REG0_FPOL_FALING);
+ if (ret < 0)
+ return ret;
+
return 0;
}
diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h
index d156666bcc55..42277fb6bc10 100644
--- a/sound/soc/codecs/tas2770.h
+++ b/sound/soc/codecs/tas2770.h
@@ -41,6 +41,9 @@
#define TAS2770_TDM_CFG_REG0_31_44_1_48KHZ 0x6
#define TAS2770_TDM_CFG_REG0_31_88_2_96KHZ 0x8
#define TAS2770_TDM_CFG_REG0_31_176_4_192KHZ 0xa
+#define TAS2770_TDM_CFG_REG0_FPOL_MASK BIT(0)
+#define TAS2770_TDM_CFG_REG0_FPOL_RSING 0
+#define TAS2770_TDM_CFG_REG0_FPOL_FALING 1
/* TDM Configuration Reg1 */
#define TAS2770_TDM_CFG_REG1 TAS2770_REG(0X0, 0x0B)
#define TAS2770_TDM_CFG_REG1_MASK GENMASK(5, 1)
--
2.34.1

View File

@ -0,0 +1,27 @@
From b65315774f730e0b8553230d6cff9912a0341ca9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:49:45 +0100
Subject: [PATCH 074/171] HACK: ASoC: tas2770: Set no of channels to 1
---
sound/soc/codecs/tas2770.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index 2b214223265e..753e3f8d459a 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -508,8 +508,8 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = {
.id = 0,
.playback = {
.stream_name = "ASI1 Playback",
- .channels_min = 2,
- .channels_max = 2,
+ .channels_min = 1,
+ .channels_max = 1,
.rates = TAS2770_RATES,
.formats = TAS2770_FORMATS,
},
--
2.34.1

View File

@ -0,0 +1,26 @@
From 289067bf88e5b44f8e5a34535693bd01bb3adb97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:49:48 +0100
Subject: [PATCH 075/171] HACK: ASoC: cs42l42: Disable regcache
There's some issue that has yet to be pinned down.
---
sound/soc/codecs/cs42l42.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 4fade2388797..5fb28df85b8a 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -380,7 +380,7 @@ static const struct regmap_config cs42l42_regmap = {
.max_register = CS42L42_MAX_REGISTER,
.reg_defaults = cs42l42_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(cs42l42_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ //.cache_type = REGCACHE_RBTREE,
.use_single_read = true,
.use_single_write = true,
--
2.34.1

View File

@ -0,0 +1,33 @@
From 27fe5e0a4429c0a92635d1395a673fcea6289046 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:49:50 +0100
Subject: [PATCH 076/171] ASoC: cs42l42: Bypass device ID check
The cs42l42 driver is also applicable to the cs42l83 part.
---
sound/soc/codecs/cs42l42.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 5fb28df85b8a..2a98f9bc7144 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2273,13 +2273,10 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
goto err_disable;
}
- if (devid != CS42L42_CHIP_ID) {
- ret = -ENODEV;
- dev_err(&i2c_client->dev,
+ if (devid != CS42L42_CHIP_ID)
+ dev_warn(&i2c_client->dev,
"CS42L42 Device ID (%X). Expected %X\n",
devid, CS42L42_CHIP_ID);
- goto err_disable;
- }
ret = regmap_read(cs42l42->regmap, CS42L42_REVID, &reg);
if (ret < 0) {
--
2.34.1

View File

@ -0,0 +1,205 @@
From 170220fc8fb15839654131612ac3dc84bb4469ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sun, 20 Feb 2022 14:29:38 +0100
Subject: [PATCH 077/171] HACK: ASoC: Add card->filter_controls hook
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add a new ASoC card callback for filtering the kcontrols of the card's
constituent components. This lets the card take over some of the
controls, deciding their value instead of leaving it up to userspace.
Also, and here's the HACK: part, move dapm_new_widgets call in front
of the card's late_probe call. This way all kcontrols should have been
crated by the time late_probe is called.
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
include/sound/soc.h | 3 +++
sound/soc/soc-core.c | 45 +++++++++++++++++++++++++++-----------------
sound/soc/soc-dapm.c | 34 ++++++++++++++++++++++++++++-----
3 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h
index b276dcb5d4e8..7ef168a8c759 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -916,6 +916,9 @@ struct snd_soc_card {
int (*late_probe)(struct snd_soc_card *card);
int (*remove)(struct snd_soc_card *card);
+ int (*filter_controls)(struct snd_soc_card *card,
+ struct snd_kcontrol *kcontrol);
+
/* the pre and post PM functions are used to do any PM work before and
* after the codec and DAI's do any PM work. */
int (*suspend_pre)(struct snd_soc_card *card);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 9574f86dd4de..37e2a8b2af10 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2069,12 +2069,12 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
}
}
+ snd_soc_dapm_new_widgets(card);
+
ret = snd_soc_card_late_probe(card);
if (ret < 0)
goto probe_end;
- snd_soc_dapm_new_widgets(card);
-
ret = snd_card_register(card->snd_card);
if (ret < 0) {
dev_err(card->dev, "ASoC: failed to register soundcard %d\n",
@@ -2209,19 +2209,34 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
}
EXPORT_SYMBOL_GPL(snd_soc_cnew);
-static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
+static int snd_soc_add_controls(struct snd_soc_card *card, struct device *dev,
const struct snd_kcontrol_new *controls, int num_controls,
const char *prefix, void *data)
{
- int i;
+ int i, err;
for (i = 0; i < num_controls; i++) {
- const struct snd_kcontrol_new *control = &controls[i];
- int err = snd_ctl_add(card, snd_soc_cnew(control, data,
- control->name, prefix));
+ const struct snd_kcontrol_new *control_new = &controls[i];
+ struct snd_kcontrol *control;
+
+ control = snd_soc_cnew(control_new, data,
+ control_new->name, prefix);
+
+ if (card->filter_controls) {
+ err = card->filter_controls(card, control);
+ if (err < 0) {
+ snd_ctl_free_one(control);
+ return err;
+ } else if (err) {
+ continue;
+ }
+ }
+
+ err = snd_ctl_add(card->snd_card, control);
+
if (err < 0) {
dev_err(dev, "ASoC: Failed to add %s: %d\n",
- control->name, err);
+ control_new->name, err);
return err;
}
}
@@ -2241,9 +2256,7 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
int snd_soc_add_component_controls(struct snd_soc_component *component,
const struct snd_kcontrol_new *controls, unsigned int num_controls)
{
- struct snd_card *card = component->card->snd_card;
-
- return snd_soc_add_controls(card, component->dev, controls,
+ return snd_soc_add_controls(component->card, component->dev, controls,
num_controls, component->name_prefix, component);
}
EXPORT_SYMBOL_GPL(snd_soc_add_component_controls);
@@ -2258,13 +2271,11 @@ EXPORT_SYMBOL_GPL(snd_soc_add_component_controls);
*
* Return 0 for success, else error.
*/
-int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+int snd_soc_add_card_controls(struct snd_soc_card *card,
const struct snd_kcontrol_new *controls, int num_controls)
{
- struct snd_card *card = soc_card->snd_card;
-
- return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
- NULL, soc_card);
+ return snd_soc_add_controls(card, card->dev, controls, num_controls,
+ NULL, card);
}
EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
@@ -2281,7 +2292,7 @@ EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
const struct snd_kcontrol_new *controls, int num_controls)
{
- struct snd_card *card = dai->component->card->snd_card;
+ struct snd_soc_card *card = dai->component->card;
return snd_soc_add_controls(card, dai->dev, controls, num_controls,
NULL, dai);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index a8e842e02cdc..c87137f364da 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -878,7 +878,7 @@ static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w,
int kci)
{
struct snd_soc_dapm_context *dapm = w->dapm;
- struct snd_card *card = dapm->card->snd_card;
+ struct snd_soc_card *card = dapm->card;
const char *prefix;
size_t prefix_len;
int shared;
@@ -962,7 +962,19 @@ static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w,
goto exit_free;
}
- ret = snd_ctl_add(card, kcontrol);
+ if (card->filter_controls) {
+ ret = card->filter_controls(card, kcontrol);
+ if (ret < 0) {
+ snd_ctl_free_one(kcontrol);
+ goto exit_free;
+ }
+
+ if (!ret)
+ ret = snd_ctl_add(card->snd_card, kcontrol);
+ } else {
+ ret = snd_ctl_add(card->snd_card, kcontrol);
+ }
+
if (ret < 0) {
dev_err(dapm->dev,
"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
@@ -1079,7 +1091,7 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
/* create new dapm dai link control */
static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
{
- int i;
+ int i, ret;
struct snd_soc_pcm_runtime *rtd = w->priv;
/* create control for links with > 1 config */
@@ -1089,10 +1101,22 @@ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
/* add kcontrol */
for (i = 0; i < w->num_kcontrols; i++) {
struct snd_soc_dapm_context *dapm = w->dapm;
- struct snd_card *card = dapm->card->snd_card;
+ struct snd_soc_card *card = dapm->card;
struct snd_kcontrol *kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
w, w->name, NULL);
- int ret = snd_ctl_add(card, kcontrol);
+
+ if (card->filter_controls) {
+ ret = card->filter_controls(card, kcontrol);
+ if (ret < 0) {
+ snd_ctl_free_one(kcontrol);
+ return ret;
+ }
+
+ if (!ret)
+ ret = snd_ctl_add(card->snd_card, kcontrol);
+ } else {
+ ret = snd_ctl_add(card->snd_card, kcontrol);
+ }
if (ret < 0) {
dev_err(dapm->dev,
--
2.34.1

View File

@ -0,0 +1,29 @@
From 3153617d401d69c1d4f52eb3ca69f5b4b8d2086a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Thu, 24 Feb 2022 14:50:34 +0100
Subject: [PATCH 078/171] ASoC: Add asoc_pcm_to_rtd utility function
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
include/sound/soc.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 7ef168a8c759..73cc83d73163 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1101,6 +1101,8 @@ struct snd_soc_pcm_runtime {
#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->num_cpus]
#define asoc_substream_to_rtd(substream) \
(struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream)
+#define asoc_pcm_to_rtd(pcm) \
+ ((struct snd_soc_pcm_runtime *)pcm->private_data)
#define for_each_rtd_components(rtd, i, component) \
for ((i) = 0, component = NULL; \
--
2.34.1

View File

@ -0,0 +1,34 @@
From 3a8e536be0711ee4985c227fee67e569aa93f9a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Thu, 24 Feb 2022 14:51:00 +0100
Subject: [PATCH 079/171] HACK: ASoC: Allow an N-cpus-to-M-codecs link
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
sound/soc/soc-pcm.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index a827cc3c158a..542c308df17c 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2811,9 +2811,10 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
} else if (rtd->num_cpus == rtd->num_codecs) {
cpu_dai = asoc_rtd_to_cpu(rtd, i);
} else {
- dev_err(rtd->card->dev,
- "N cpus to M codecs link is not supported yet\n");
- return -EINVAL;
+ cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ //dev_err(rtd->card->dev,
+ // "N cpus to M codecs link is not supported yet\n");
+ //return -EINVAL;
}
if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
--
2.34.1

View File

@ -0,0 +1,632 @@
From 1bd9f82e027617111fd5a1a653dad3880f71ddf7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Sat, 19 Feb 2022 09:49:56 +0100
Subject: [PATCH 080/171] ASoC: Add macaudio machine driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
sound/soc/apple/Kconfig | 9 +
sound/soc/apple/Makefile | 3 +
sound/soc/apple/macaudio.c | 579 +++++++++++++++++++++++++++++++++++++
3 files changed, 591 insertions(+)
create mode 100644 sound/soc/apple/macaudio.c
diff --git a/sound/soc/apple/Kconfig b/sound/soc/apple/Kconfig
index ebe66d713b96..a3f6a97140e2 100644
--- a/sound/soc/apple/Kconfig
+++ b/sound/soc/apple/Kconfig
@@ -1,3 +1,12 @@
+
+config SND_SOC_APPLE_SILICON
+ tristate "ASoC machine driver for Apple Silicon Macs"
+ depends on ARCH_APPLE || COMPILE_TEST
+ select SND_SOC_APPLE_MCA
+ default ARCH_APPLE
+ help
+ This option enables an ASoC machine driver for Apple Silicon Macs.
+
config SND_SOC_APPLE_MCA
tristate "Apple Silicon MCA driver"
depends on ARCH_APPLE || COMPILE_TEST
diff --git a/sound/soc/apple/Makefile b/sound/soc/apple/Makefile
index c1e492d57649..a45cf8213c29 100644
--- a/sound/soc/apple/Makefile
+++ b/sound/soc/apple/Makefile
@@ -1,3 +1,6 @@
snd-soc-apple-mca-objs := mca.o
+snd-soc-apple-silicon-objs := macaudio.o
obj-$(CONFIG_SND_SOC_APPLE_MCA) += snd-soc-apple-mca.o
+obj-$(CONFIG_SND_SOC_APPLE_SILICON) += snd-soc-apple-silicon.o
+
diff --git a/sound/soc/apple/macaudio.c b/sound/soc/apple/macaudio.c
new file mode 100644
index 000000000000..a1f2b1fcea1f
--- /dev/null
+++ b/sound/soc/apple/macaudio.c
@@ -0,0 +1,579 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ASoC machine driver for Apple Silicon Macs
+ *
+ * Copyright (C) The Asahi Linux Contributors
+ *
+ * Based on sound/soc/qcom/{sc7180.c|common.c}
+ *
+ * Copyright (c) 2018, Linaro Limited.
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/simple_card_utils.h>
+#include <sound/soc.h>
+#include <uapi/linux/input-event-codes.h>
+
+#define DRIVER_NAME "snd-soc-apple-macaudio"
+
+struct macaudio_snd_data {
+ struct snd_soc_card card;
+ struct snd_soc_jack_pin pin;
+ struct snd_soc_jack jack;
+
+ struct macaudio_link_props {
+ unsigned int mclk_fs;
+ } *link_props;
+
+ const struct snd_pcm_chmap_elem *speaker_chmap;
+
+ unsigned int speaker_nchans_array[2];
+ struct snd_pcm_hw_constraint_list speaker_nchans_list;
+
+ struct list_head hidden_kcontrols;
+};
+
+static int macaudio_parse_of(struct macaudio_snd_data *ma, struct snd_soc_card *card)
+{
+ struct device_node *np;
+ struct device_node *codec = NULL;
+ struct device_node *cpu = NULL;
+ struct device *dev = card->dev;
+ struct snd_soc_dai_link *link;
+ struct macaudio_link_props *link_props;
+ int ret, num_links;
+ int i = 0;
+
+ ret = snd_soc_of_parse_card_name(card, "model");
+ if (ret) {
+ dev_err(dev, "Error parsing card name: %d\n", ret);
+ return ret;
+ }
+
+ ret = asoc_simple_parse_routing(card, NULL);
+ if (ret) {
+ return ret;
+ }
+
+ /* Populate links */
+ num_links = of_get_available_child_count(dev->of_node);
+
+ /* Allocate the DAI link array */
+ card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
+ ma->link_props = devm_kcalloc(dev, num_links, sizeof(*ma->link_props), GFP_KERNEL);
+ if (!card->dai_link || !ma->link_props)
+ return -ENOMEM;
+
+ card->num_links = num_links;
+ link = card->dai_link;
+ link_props = ma->link_props;
+
+ for_each_available_child_of_node(dev->of_node, np) {
+ link->id = i++;
+
+ /* CPU side is bit and frame clock master, I2S with both clocks inverted */
+ link->dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_CBC_CFC |
+ SND_SOC_DAIFMT_GATED |
+ SND_SOC_DAIFMT_IB_IF;
+
+ ret = of_property_read_string(np, "link-name", &link->name);
+ if (ret) {
+ dev_err(card->dev, "Missing link name\n");
+ goto err_put_np;
+ }
+
+ cpu = of_get_child_by_name(np, "cpu");
+ codec = of_get_child_by_name(np, "codec");
+
+ if (!codec || !cpu) {
+ dev_err(dev, "Missing DAI specifications for '%s'\n", link->name);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
+ if (ret < 0) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(card->dev, "%s: codec dai not found: %d\n",
+ link->name, ret);
+ goto err;
+ }
+
+ ret = snd_soc_of_get_dai_link_cpus(dev, cpu, link);
+ if (ret < 0) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(card->dev, "%s: cpu dai not found: %d\n",
+ link->name, ret);
+ goto err;
+ }
+
+ link->num_platforms = 1;
+ link->platforms = devm_kzalloc(dev, sizeof(*link->platforms),
+ GFP_KERNEL);
+ if (!link->platforms) {
+ ret = -ENOMEM;
+ goto err_put_np;
+ }
+ link->platforms->of_node = link->cpus->of_node;
+
+ of_property_read_u32(np, "mclk-fs", &link_props->mclk_fs);
+
+ link->stream_name = link->name;
+ link++;
+ link_props++;
+
+ of_node_put(cpu);
+ of_node_put(codec);
+ }
+
+ /* TODO: snd_soc_of_get_dai_link_codecs cleanup */
+
+ return 0;
+err:
+ of_node_put(cpu);
+ of_node_put(codec);
+err_put_np:
+ of_node_put(np);
+ return ret;
+}
+
+static int macaudio_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(rtd->card);
+ struct macaudio_link_props *props = &ma->link_props[rtd->num];
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *dai;
+ int i, mclk;
+
+ if (props->mclk_fs) {
+ mclk = params_rate(params) * props->mclk_fs;
+
+ for_each_rtd_codec_dais(rtd, i, dai)
+ snd_soc_dai_set_sysclk(dai, 0, mclk, SND_SOC_CLOCK_IN);
+
+ snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, SND_SOC_CLOCK_OUT);
+ }
+
+ return 0;
+}
+
+static void macaudio_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(rtd->card);
+ struct macaudio_link_props *props = &ma->link_props[rtd->num];
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *dai;
+ int i;
+
+ if (props->mclk_fs) {
+ for_each_rtd_codec_dais(rtd, i, dai)
+ snd_soc_dai_set_sysclk(dai, 0, 0, SND_SOC_CLOCK_IN);
+
+ snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
+ }
+}
+
+
+static int macaudio_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_card *card = rtd->card;
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(card);
+ struct snd_pcm_hw_constraint_list *nchans_list = &ma->speaker_nchans_list;
+ unsigned int *nchans_array = ma->speaker_nchans_array;
+ int ret;
+
+ if (!strcmp(rtd->dai_link->name, "Speakers")) {
+ if (rtd->num_codecs > 2) {
+ nchans_list->count = 2;
+ nchans_list->list = nchans_array;
+ nchans_array[0] = 2;
+ nchans_array[1] = rtd->num_codecs;
+
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS, nchans_list);
+ if (ret < 0)
+ return ret;
+ } else if (rtd->num_codecs == 2) {
+ ret = snd_pcm_hw_constraint_single(substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int macaudio_assign_tdm(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dai *dai, *cpu_dai;
+ int ret, i;
+ int nchans = 0, nslots = 0, slot_width = 32;
+
+ nslots = rtd->num_codecs;
+
+ for_each_rtd_codec_dais(rtd, i, dai) {
+ int codec_nchans = 1;
+ int mask = ((1 << codec_nchans) - 1) << nchans;
+
+ ret = snd_soc_dai_set_tdm_slot(dai, mask,
+ mask, nslots, slot_width);
+ if (ret == -EINVAL)
+ /* Try without the RX mask */
+ ret = snd_soc_dai_set_tdm_slot(dai, mask,
+ 0, nslots, slot_width);
+
+ if (ret < 0) {
+ dev_err(card->dev, "DAI %s refuses TDM settings: %d",
+ dai->name, ret);
+ return ret;
+ }
+
+ nchans += codec_nchans;
+ }
+
+ cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, (1 << nslots) - 1,
+ (1 << nslots) - 1, nslots, slot_width);
+ if (ret < 0) {
+ dev_err(card->dev, "CPU DAI %s refuses TDM settings: %d",
+ cpu_dai->name, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int macaudio_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(card);
+ struct snd_soc_component *component;
+ int ret, i;
+
+ if (rtd->num_codecs > 1) {
+ ret = macaudio_assign_tdm(rtd);
+ if (ret < 0)
+ return ret;
+ }
+
+ for_each_rtd_components(rtd, i, component)
+ snd_soc_component_set_jack(component, &ma->jack, NULL);
+
+ return 0;
+}
+
+static void macaudio_exit(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *component;
+ int i;
+
+ for_each_rtd_components(rtd, i, component)
+ snd_soc_component_set_jack(component, NULL, NULL);
+}
+
+struct fixed_kctl {
+ char *name;
+ char *value;
+} macaudio_fixed_kctls[] = {
+ {"ASI1 Sel", "Left"},
+ {"Left ASI1 Sel", "Left"},
+ {"Right ASI1 Sel", "Left"},
+ {"Left Front ASI1 Sel", "Left"},
+ {"Left Rear ASI1 Sel", "Left"},
+ {"Right Front ASI1 Sel", "Left"},
+ {"Right Rear ASI1 Sel", "Left"},
+ {"Left Tweeter ASI1 Sel", "Left"},
+ {"Left Woofer 1 ASI1 Sel", "Left"},
+ {"Left Woofer 2 ASI1 Sel", "Left"},
+ {"Right Tweeter ASI1 Sel", "Left"},
+ {"Right Woofer 1 ASI1 Sel", "Left"},
+ {"Right Woofer 2 ASI1 Sel", "Left"},
+ {"Left ISENSE Switch", "Off"},
+ {"Left VSENSE Switch", "Off"},
+ {"Right ISENSE Switch", "Off"},
+ {"Right VSENSE Switch", "Off"},
+ {"Jack Mixer Volume", "63"},
+ { }
+};
+
+static struct fixed_kctl *find_fixed_kctl(const char *name)
+{
+ struct fixed_kctl *fctl;
+
+ for (fctl = macaudio_fixed_kctls; fctl->name != NULL; fctl++)
+ if (!strcmp(fctl->name, name))
+ return fctl;
+
+ return NULL;
+}
+
+static int macaudio_probe(struct snd_soc_card *card)
+{
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ INIT_LIST_HEAD(&ma->hidden_kcontrols);
+
+ ma->pin.pin = "Headphones";
+ ma->pin.mask = SND_JACK_HEADSET | SND_JACK_HEADPHONE;
+ ret = snd_soc_card_jack_new_pins(card, ma->pin.pin,
+ SND_JACK_HEADSET |
+ SND_JACK_HEADPHONE |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3,
+ &ma->jack, &ma->pin, 1);
+
+ if (ret < 0)
+ dev_err(card->dev, "jack creation failed: %d\n", ret);
+
+ return ret;
+}
+
+static int macaudio_remove(struct snd_soc_card *card)
+{
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(card);
+ struct snd_kcontrol *kcontrol;
+
+ list_for_each_entry(kcontrol, &ma->hidden_kcontrols, list)
+ snd_ctl_free_one(kcontrol);
+
+ return 0;
+}
+
+static void snd_soc_kcontrol_set_strval(struct snd_soc_card *card,
+ struct snd_kcontrol *kcontrol, const char *strvalue)
+{
+ struct snd_ctl_elem_value value;
+ struct snd_ctl_elem_info info;
+ int sel, i, ret;
+
+ ret = kcontrol->info(kcontrol, &info);
+ if (ret < 0) {
+ dev_err(card->dev, "can't obtain info on control '%s': %d",
+ kcontrol->id.name, ret);
+ return;
+ }
+
+ switch (info.type) {
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ for (sel = 0; sel < info.value.enumerated.items; sel++) {
+ info.value.enumerated.item = sel;
+ kcontrol->info(kcontrol, &info);
+
+ if (!strcmp(strvalue, info.value.enumerated.name))
+ break;
+ }
+
+ if (sel == info.value.enumerated.items)
+ goto not_avail;
+
+ for (i = 0; i < info.count; i++)
+ value.value.enumerated.item[i] = sel;
+ break;
+
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ sel = !strcmp(strvalue, "On");
+
+ if (!sel && strcmp(strvalue, "Off"))
+ goto not_avail;
+
+ for (i = 0; i < info.count; i++) /* TODO */
+ value.value.integer.value[i] = sel;
+ break;
+
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ if (kstrtoint(strvalue, 10, &sel))
+ goto not_avail;
+
+ for (i = 0; i < info.count; i++)
+ value.value.integer.value[i] = sel;
+ break;
+
+ default:
+ dev_err(card->dev, "%s: control '%s' has unsupported type %d",
+ __func__, kcontrol->id.name, info.type);
+ return;
+ }
+
+ ret = kcontrol->put(kcontrol, &value);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set control '%s' to '%s': %d",
+ kcontrol->id.name, strvalue, ret);
+ return;
+ }
+
+ dev_info(card->dev, "set '%s' to '%s'",
+ kcontrol->id.name, strvalue);
+ return;
+
+not_avail:
+ dev_err(card->dev, "option '%s' on control '%s' not available",
+ strvalue, kcontrol->id.name);
+ return;
+
+}
+
+static int macaudio_late_probe(struct snd_soc_card *card)
+{
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(card);
+ struct snd_kcontrol *kcontrol;
+ struct snd_soc_pcm_runtime *rtd;
+ int ret;
+
+ list_for_each_entry(kcontrol, &ma->hidden_kcontrols, list) {
+ struct fixed_kctl *fctl = find_fixed_kctl(kcontrol->id.name);
+
+ if (fctl)
+ snd_soc_kcontrol_set_strval(card, kcontrol, fctl->value);
+ }
+
+ for_each_card_rtds(card, rtd) {
+ bool speakers_link = !strcmp(rtd->dai_link->name, "Speaker")
+ || !strcmp(rtd->dai_link->name, "Speakers");
+
+ if (speakers_link && ma->speaker_chmap) {
+ ret = snd_pcm_add_chmap_ctls(rtd->pcm,
+ SNDRV_PCM_STREAM_PLAYBACK, ma->speaker_chmap,
+ rtd->num_codecs, 0, NULL);
+ if (ret < 0)
+ dev_err(card->dev, "failed to add channel map on '%s': %d\n",
+ rtd->dai_link->name, ret);
+ }
+ }
+
+ return 0;
+}
+
+static int macaudio_filter_controls(struct snd_soc_card *card,
+ struct snd_kcontrol *kcontrol)
+{
+ struct fixed_kctl *fctl = find_fixed_kctl(kcontrol->id.name);
+ struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(card);
+
+ dev_info(card->dev, "visiting control %s, have match %d\n",
+ kcontrol->id.name, !!fctl);
+
+ if (!fctl)
+ return 0;
+
+ list_add_tail(&kcontrol->list, &ma->hidden_kcontrols);
+ return 1;
+}
+
+static const struct snd_soc_ops macaudio_ops = {
+ .startup = macaudio_startup,
+ .shutdown = macaudio_shutdown,
+ .hw_params = macaudio_hw_params,
+};
+
+static const struct snd_soc_dapm_widget macaudio_snd_widgets[] = {
+ SND_SOC_DAPM_HP("Headphones", NULL),
+};
+
+static const struct snd_pcm_chmap_elem macaudio_j274_chmaps[] = {
+ { .channels = 1,
+ .map = { SNDRV_CHMAP_MONO } },
+ { }
+};
+
+static const struct snd_pcm_chmap_elem macaudio_j293_chmaps[] = {
+ { .channels = 2,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+ { .channels = 4,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+ SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+ { }
+};
+
+static const struct snd_pcm_chmap_elem macaudio_j314_chmaps[] = {
+ { .channels = 2,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+ { .channels = 6,
+ .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR,
+ SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+ SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+ { }
+};
+
+static const struct of_device_id macaudio_snd_device_id[] = {
+ { .compatible = "apple,j274-macaudio", .data = macaudio_j274_chmaps },
+ { .compatible = "apple,j293-macaudio", .data = macaudio_j293_chmaps },
+ { .compatible = "apple,j314-macaudio", .data = macaudio_j314_chmaps },
+ { .compatible = "apple,macaudio", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, macaudio_snd_device_id);
+
+static int macaudio_snd_platform_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card;
+ struct macaudio_snd_data *data;
+ struct device *dev = &pdev->dev;
+ struct snd_soc_dai_link *link;
+ const struct of_device_id *of_id;
+ int ret;
+ int i;
+
+ of_id = of_match_device(macaudio_snd_device_id, dev);
+ if (!of_id)
+ return -EINVAL;
+
+ /* Allocate the private data */
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->speaker_chmap = of_id->data;
+ card = &data->card;
+ snd_soc_card_set_drvdata(card, data);
+
+ card->owner = THIS_MODULE;
+ card->driver_name = DRIVER_NAME;
+ card->dev = dev;
+ card->dapm_widgets = macaudio_snd_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(macaudio_snd_widgets);
+ card->probe = macaudio_probe;
+ card->late_probe = macaudio_late_probe;
+ card->remove = macaudio_remove;
+ card->filter_controls = macaudio_filter_controls;
+ card->remove = macaudio_remove;
+
+ ret = macaudio_parse_of(data, card);
+ if (ret)
+ return ret;
+
+ for_each_card_prelinks(card, i, link) {
+ link->ops = &macaudio_ops;
+ link->init = macaudio_init;
+ link->exit = macaudio_exit;
+ }
+
+ return devm_snd_soc_register_card(dev, card);
+}
+
+static struct platform_driver macaudio_snd_driver = {
+ .probe = macaudio_snd_platform_probe,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = macaudio_snd_device_id,
+ .pm = &snd_soc_pm_ops,
+ },
+};
+module_platform_driver(macaudio_snd_driver);
+
+MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>");
+MODULE_DESCRIPTION("Apple Silicon Macs machine sound driver");
+MODULE_LICENSE("GPL v2");
--
2.34.1

View File

@ -0,0 +1,161 @@
From 11d06018fefa454eff591ade9181e20a23acff48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Fri, 11 Mar 2022 11:55:44 +0100
Subject: [PATCH 081/171] ASoC: tas2764: Extend driver to SN012776
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
SN012776 is a speaker amp chip found in Apple's 2021 laptops. It appears
similar and more-or-less compatible to TAS2764. Extend the TAS2764
driver with some SN012776 specifics and configure the chip assuming
it's in one of the Apple machines.
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
sound/soc/codecs/tas2764.c | 51 ++++++++++++++++++++++++++++++++++----
sound/soc/codecs/tas2764.h | 3 +++
2 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 4cb788f3e5f7..dd36c99e633b 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -16,6 +16,7 @@
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/pcm.h>
@@ -25,13 +26,20 @@
#include "tas2764.h"
+enum tas2764_devid {
+ DEVID_TAS2764 = 0,
+ DEVID_SN012776 = 1
+};
+
struct tas2764_priv {
struct snd_soc_component *component;
struct gpio_desc *reset_gpio;
struct gpio_desc *sdz_gpio;
struct regmap *regmap;
struct device *dev;
-
+
+ enum tas2764_devid devid;
+
int v_sense_slot;
int i_sense_slot;
};
@@ -502,10 +510,16 @@ static struct snd_soc_dai_driver tas2764_dai_driver[] = {
},
};
+static uint8_t sn012776_bop_presets[] = {
+ 0x01, 0x32, 0x02, 0x22, 0x83, 0x2d, 0x80, 0x02, 0x06,
+ 0x32, 0x46, 0x30, 0x02, 0x06, 0x38, 0x40, 0x30, 0x02,
+ 0x06, 0x3e, 0x37, 0x30, 0xff, 0xe6
+};
+
static int tas2764_codec_probe(struct snd_soc_component *component)
{
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
- int ret;
+ int ret, i;
tas2764->component = component;
@@ -532,6 +546,23 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
if (ret < 0)
return ret;
+ if (tas2764->devid == DEVID_SN012776) {
+ ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_BOP_SRC,
+ TAS2764_PWR_CTRL_BOP_SRC);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(sn012776_bop_presets); i++) {
+ ret = snd_soc_component_write(component,
+ TAS2764_BOP_CFG0 + i,
+ sn012776_bop_presets[i]);
+
+ if (ret < 0)
+ return ret;
+ }
+ }
+
return 0;
}
@@ -631,9 +662,12 @@ static int tas2764_parse_dt(struct device *dev, struct tas2764_priv *tas2764)
return 0;
}
+static const struct of_device_id tas2764_of_match[];
+
static int tas2764_i2c_probe(struct i2c_client *client)
{
struct tas2764_priv *tas2764;
+ const struct of_device_id *of_id = NULL;
int result;
tas2764 = devm_kzalloc(&client->dev, sizeof(struct tas2764_priv),
@@ -641,6 +675,14 @@ static int tas2764_i2c_probe(struct i2c_client *client)
if (!tas2764)
return -ENOMEM;
+ if (client->dev.of_node)
+ of_id = of_match_device(tas2764_of_match, &client->dev);
+
+ if (of_id)
+ tas2764->devid = (enum tas2764_devid) of_id->data;
+ else
+ tas2764->devid = DEVID_TAS2764;
+
tas2764->dev = &client->dev;
i2c_set_clientdata(client, tas2764);
dev_set_drvdata(&client->dev, tas2764);
@@ -674,13 +716,12 @@ static const struct i2c_device_id tas2764_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id);
-#if defined(CONFIG_OF)
static const struct of_device_id tas2764_of_match[] = {
- { .compatible = "ti,tas2764" },
+ { .compatible = "ti,tas2764", .data = (void*) DEVID_TAS2764 },
+ { .compatible = "ti,sn012776", .data = (void*) DEVID_SN012776 },
{},
};
MODULE_DEVICE_TABLE(of, tas2764_of_match);
-#endif
static struct i2c_driver tas2764_i2c_driver = {
.driver = {
diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h
index f015f22a083b..d7e171a9480c 100644
--- a/sound/soc/codecs/tas2764.h
+++ b/sound/soc/codecs/tas2764.h
@@ -29,6 +29,7 @@
#define TAS2764_PWR_CTRL_ACTIVE 0x0
#define TAS2764_PWR_CTRL_MUTE BIT(0)
#define TAS2764_PWR_CTRL_SHUTDOWN BIT(1)
+#define TAS2764_PWR_CTRL_BOP_SRC BIT(7)
#define TAS2764_VSENSE_POWER_EN 3
#define TAS2764_ISENSE_POWER_EN 4
@@ -87,4 +88,6 @@
#define TAS2764_TDM_CFG6_ISNS_ENABLE BIT(6)
#define TAS2764_TDM_CFG6_50_MASK GENMASK(5, 0)
+#define TAS2764_BOP_CFG0 TAS2764_REG(0X0, 0x1d)
+
#endif /* __TAS2764__ */
--
2.34.1

View File

@ -0,0 +1,147 @@
From b94fc3351432c6a0a75962c4af03750d8879d205 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 13 Mar 2022 03:13:08 +0900
Subject: [PATCH 082/171] ASoC: tas2764: Add workaround for spurious shutdowns
on SN012776
It seems that on SHUTDOWN -> MUTE transitions, the SN012776 can end up
in a borked state raising an overcurrent error.
Going through the ACTIVE state seems to make it work reliably, so do
that.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
sound/soc/codecs/tas2764.c | 65 +++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 29 deletions(-)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index dd36c99e633b..b3c99f470916 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -58,27 +58,47 @@ static void tas2764_reset(struct tas2764_priv *tas2764)
usleep_range(1000, 2000);
}
+static int tas2764_set_power(struct tas2764_priv *tas2764, u8 mode)
+{
+ int ret;
+
+ // TODO: Does this only affect the SN012776 variant?
+ if (tas2764->devid == DEVID_SN012776 && mode == TAS2764_PWR_CTRL_MUTE) {
+ ret = snd_soc_component_update_bits(tas2764->component,
+ TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_MASK,
+ TAS2764_PWR_CTRL_ACTIVE);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = snd_soc_component_update_bits(tas2764->component,
+ TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_MASK,
+ mode);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
static int tas2764_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
+ u8 mode;
switch (level) {
case SND_SOC_BIAS_ON:
- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_ACTIVE);
+ mode = TAS2764_PWR_CTRL_ACTIVE;
break;
case SND_SOC_BIAS_STANDBY:
case SND_SOC_BIAS_PREPARE:
- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_MUTE);
+ mode = TAS2764_PWR_CTRL_MUTE;
break;
case SND_SOC_BIAS_OFF:
- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_SHUTDOWN);
+ mode = TAS2764_PWR_CTRL_SHUTDOWN;
break;
default:
@@ -87,7 +107,7 @@ static int tas2764_set_bias_level(struct snd_soc_component *component,
return -EINVAL;
}
- return 0;
+ return tas2764_set_power(tas2764, mode);
}
#ifdef CONFIG_PM
@@ -96,10 +116,7 @@ static int tas2764_codec_suspend(struct snd_soc_component *component)
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
int ret;
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_SHUTDOWN);
-
+ ret = tas2764_set_power(tas2764, TAS2764_PWR_CTRL_SHUTDOWN);
if (ret < 0)
return ret;
@@ -122,10 +139,7 @@ static int tas2764_codec_resume(struct snd_soc_component *component)
usleep_range(1000, 2000);
}
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_ACTIVE);
-
+ ret = tas2764_set_power(tas2764, TAS2764_PWR_CTRL_ACTIVE);
if (ret < 0)
return ret;
@@ -154,28 +168,21 @@ static int tas2764_dac_event(struct snd_soc_dapm_widget *w,
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
- int ret;
+ u8 mode;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_MUTE);
+ mode = TAS2764_PWR_CTRL_MUTE;
break;
case SND_SOC_DAPM_PRE_PMD:
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_SHUTDOWN);
+ mode = TAS2764_PWR_CTRL_SHUTDOWN;
break;
default:
dev_err(tas2764->dev, "Unsupported event\n");
return -EINVAL;
}
- if (ret < 0)
- return ret;
-
- return 0;
+ return tas2764_set_power(tas2764, mode);
}
static const struct snd_kcontrol_new isense_switch =
--
2.34.1

View File

@ -0,0 +1,31 @@
From 91b1840731bc223fdfa0b86b0d9b1904213e3299 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Date: Tue, 15 Mar 2022 19:41:05 +0100
Subject: [PATCH 083/171] ASoC: macaudio: State missing simple-card-utils
dependency
State that the macaudio module depends on simple-card-utils to fix build
errors of the kind:
ld.lld: error: undefined symbol: asoc_simple_parse_routing
>>> referenced by macaudio.c:59 (sound/soc/apple/macaudio.c:59)
>>> soc/apple/macaudio.o:(macaudio_snd_platform_probe) in archive
---
sound/soc/apple/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/soc/apple/Kconfig b/sound/soc/apple/Kconfig
index a3f6a97140e2..ce6188aa659d 100644
--- a/sound/soc/apple/Kconfig
+++ b/sound/soc/apple/Kconfig
@@ -3,6 +3,7 @@ config SND_SOC_APPLE_SILICON
tristate "ASoC machine driver for Apple Silicon Macs"
depends on ARCH_APPLE || COMPILE_TEST
select SND_SOC_APPLE_MCA
+ select SND_SIMPLE_CARD_UTILS
default ARCH_APPLE
help
This option enables an ASoC machine driver for Apple Silicon Macs.
--
2.34.1

View File

@ -0,0 +1,25 @@
From ddf6983d9229819248d0373854d32b4e4a0e123d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sat, 19 Mar 2022 06:06:20 +0900
Subject: [PATCH 084/171] macaudio: Unbork jack volume
Signed-off-by: Hector Martin <marcan@marcan.st>
---
sound/soc/apple/macaudio.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/sound/soc/apple/macaudio.c b/sound/soc/apple/macaudio.c
index a1f2b1fcea1f..d39ef638ea95 100644
--- a/sound/soc/apple/macaudio.c
+++ b/sound/soc/apple/macaudio.c
@@ -305,7 +305,6 @@ struct fixed_kctl {
{"Left VSENSE Switch", "Off"},
{"Right ISENSE Switch", "Off"},
{"Right VSENSE Switch", "Off"},
- {"Jack Mixer Volume", "63"},
{ }
};
--
2.34.1

View File

@ -0,0 +1,88 @@
From 4c5d245b445841af3cff2d861a3b461c645b3b57 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 26 Dec 2021 22:04:09 +0900
Subject: [PATCH 085/171] dt-bindings: net: bcm4329-fmac: Add Apple properties
& chips
This binding is currently used for SDIO devices, but these chips are
also used as PCIe devices on DT platforms and may be represented in the
DT. Re-use the existing binding and add chip compatibles used by Apple
T2 and M1 platforms (the T2 ones are not known to be used in DT
platforms, but we might as well document them).
Then, add properties required for firmware selection and calibration on
M1 machines.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../net/wireless/brcm,bcm4329-fmac.yaml | 37 +++++++++++++++++--
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
index c11f23b20c4c..8b4147c64355 100644
--- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/net/wireless/brcm,bcm4329-fmac.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Broadcom BCM4329 family fullmac wireless SDIO devices
+title: Broadcom BCM4329 family fullmac wireless SDIO/PCIE devices
maintainers:
- Arend van Spriel <arend@broadcom.com>
@@ -42,10 +42,16 @@ properties:
- cypress,cyw43012-fmac
- const: brcm,bcm4329-fmac
- const: brcm,bcm4329-fmac
+ - enum:
+ - pci14e4,43dc # BCM4355
+ - pci14e4,4464 # BCM4364
+ - pci14e4,4488 # BCM4377
+ - pci14e4,4425 # BCM4378
+ - pci14e4,4433 # BCM4387
reg:
- description: SDIO function number for the device, for most cases
- this will be 1.
+ description: SDIO function number for the device (for most cases
+ this will be 1) or PCI device identifier.
interrupts:
maxItems: 1
@@ -75,6 +81,31 @@ properties:
items:
pattern: '^[A-Z][A-Z]-[A-Z][0-9A-Z]-[0-9]+$'
+ brcm,cal-blob:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description: A per-device calibration blob for the Wi-Fi radio. This
+ should be filled in by the bootloader from platform configuration
+ data, if necessary, and will be uploaded to the device if present.
+
+ brcm,board-type:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Overrides the board type, which is normally the compatible of
+ the root node. This can be used to decouple the overall system board or
+ device name from the board type for WiFi purposes, which is used to
+ construct firmware and NVRAM configuration filenames, allowing for
+ multiple devices that share the same module or characteristics for the
+ WiFi subsystem to share the same firmware/NVRAM files. On Apple platforms,
+ this should be the Apple module-instance codename prefixed by "apple,",
+ e.g. "apple,honshu".
+
+ apple,antenna-sku:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Antenna SKU used to identify a specific antenna configuration
+ on Apple platforms. This is use to build firmware filenames, to allow
+ platforms with different antenna configs to have different firmware and/or
+ NVRAM. This would normally be filled in by the bootloader from platform
+ configuration data.
+
required:
- compatible
- reg
--
2.34.1

View File

@ -0,0 +1,76 @@
From 6e3dabd08775a78c7a6ba10779bdb9418852cd1b Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sat, 18 Dec 2021 20:52:04 +0900
Subject: [PATCH 086/171] brcmfmac: firmware: Handle per-board clm_blob files
Teach brcm_alt_fw_paths to correctly split off variable length
extensions, and enable alt firmware lookups for the CLM blob firmware
requests.
Apple platforms have per-board CLM blob files.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 33 +++++++++++--------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index dcbe55b56e43..deacd39b3f7b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -596,22 +596,29 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
static char *brcm_alt_fw_path(const char *path, const char *board_type)
{
- char alt_path[BRCMF_FW_NAME_LEN];
- char suffix[5];
+ char base[BRCMF_FW_NAME_LEN];
+ const char *suffix;
+ char *ret;
- strscpy(alt_path, path, BRCMF_FW_NAME_LEN);
- /* At least one character + suffix */
- if (strlen(alt_path) < 5)
+ if (!board_type)
return NULL;
- /* strip .txt or .bin at the end */
- strscpy(suffix, alt_path + strlen(alt_path) - 4, 5);
- alt_path[strlen(alt_path) - 4] = 0;
- strlcat(alt_path, ".", BRCMF_FW_NAME_LEN);
- strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN);
- strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN);
+ suffix = strrchr(path, '.');
+ if (!suffix || suffix == path)
+ return NULL;
+
+ /* strip extension at the end */
+ strscpy(base, path, BRCMF_FW_NAME_LEN);
+ base[suffix - path] = 0;
+
+ ret = kasprintf(GFP_KERNEL, "%s.%s%s", base, board_type, suffix);
+ if (!ret)
+ brcmf_err("out of memory allocating firmware path for '%s'\n",
+ path);
+
+ brcmf_dbg(TRACE, "FW alt path: %s\n", ret);
- return kstrdup(alt_path, GFP_KERNEL);
+ return ret;
}
static int brcmf_fw_request_firmware(const struct firmware **fw,
@@ -621,7 +628,7 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,
int ret;
/* Files can be board-specific, first try a board-specific path */
- if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) {
+ if (fwctx->req->board_type) {
char *alt_path;
alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type);
--
2.34.1

View File

@ -0,0 +1,376 @@
From a0e0f6cebc9a2112a11c56d0f6c55681cf2b120d Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:13:49 +0900
Subject: [PATCH 087/171] brcmfmac: pcie/sdio/usb: Get CLM blob via standard
firmware mechanism
Now that the firmware fetcher can handle per-board CLM files, load the
CLM blob alongside the other firmware files and change the bus API to
just return the existing blob, instead of fetching the filename.
This enables per-board CLM blobs, which are required on Apple platforms.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/bus.h | 19 ++++++---
.../broadcom/brcm80211/brcmfmac/common.c | 12 +-----
.../broadcom/brcm80211/brcmfmac/pcie.c | 39 ++++++++++++-------
.../broadcom/brcm80211/brcmfmac/sdio.c | 36 ++++++++++-------
.../broadcom/brcm80211/brcmfmac/sdio.h | 2 +
.../broadcom/brcm80211/brcmfmac/usb.c | 23 +++--------
6 files changed, 69 insertions(+), 62 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index 3f5da3bb6aa5..b13af8f631f3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -7,6 +7,8 @@
#define BRCMFMAC_BUS_H
#include "debug.h"
+#include <linux/kernel.h>
+#include <linux/firmware.h>
/* IDs of the 6 default common rings of msgbuf protocol */
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
@@ -34,6 +36,11 @@ enum brcmf_bus_protocol_type {
BRCMF_PROTO_MSGBUF
};
+/* Firmware blobs that may be available */
+enum brcmf_blob_type {
+ BRCMF_BLOB_CLM,
+};
+
struct brcmf_mp_device;
struct brcmf_bus_dcmd {
@@ -60,7 +67,7 @@ struct brcmf_bus_dcmd {
* @wowl_config: specify if dongle is configured for wowl when going to suspend
* @get_ramsize: obtain size of device memory.
* @get_memdump: obtain device memory dump in provided buffer.
- * @get_fwname: obtain firmware name.
+ * @get_blob: obtain a firmware blob.
*
* This structure provides an abstract interface towards the
* bus specific driver. For control messages to common driver
@@ -77,8 +84,8 @@ struct brcmf_bus_ops {
void (*wowl_config)(struct device *dev, bool enabled);
size_t (*get_ramsize)(struct device *dev);
int (*get_memdump)(struct device *dev, void *data, size_t len);
- int (*get_fwname)(struct device *dev, const char *ext,
- unsigned char *fw_name);
+ int (*get_blob)(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type);
void (*debugfs_create)(struct device *dev);
int (*reset)(struct device *dev);
};
@@ -220,10 +227,10 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
}
static inline
-int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
- unsigned char *fw_name)
+int brcmf_bus_get_blob(struct brcmf_bus *bus, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
- return bus->ops->get_fwname(bus->dev, ext, fw_name);
+ return bus->ops->get_blob(bus->dev, fw, type);
}
static inline
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index fe01da9e620d..95d4c133efdd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -123,7 +123,6 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
struct brcmf_bus *bus = drvr->bus_if;
struct brcmf_dload_data_le *chunk_buf;
const struct firmware *clm = NULL;
- u8 clm_name[BRCMF_FW_NAME_LEN];
u32 chunk_len;
u32 datalen;
u32 cumulative_len;
@@ -133,15 +132,8 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
brcmf_dbg(TRACE, "Enter\n");
- memset(clm_name, 0, sizeof(clm_name));
- err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
- if (err) {
- bphy_err(drvr, "get CLM blob file name failed (%d)\n", err);
- return err;
- }
-
- err = firmware_request_nowarn(&clm, clm_name, bus->dev);
- if (err) {
+ err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM);
+ if (err || !clm) {
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
err);
return 0;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 97f0f13dfe50..ec73d2620ec9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -66,6 +66,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
/* per-board firmware binaries */
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");
static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
@@ -261,6 +262,8 @@ struct brcmf_pciedev_info {
struct pci_dev *pdev;
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
+ char clm_name[BRCMF_FW_NAME_LEN];
+ const struct firmware *clm_fw;
void __iomem *regs;
void __iomem *tcm;
u32 ram_base;
@@ -1382,23 +1385,25 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
return 0;
}
-static
-int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_fw_request *fwreq;
- struct brcmf_fw_name fwnames[] = {
- { ext, fw_name },
- };
+ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+ struct brcmf_pciedev_info *devinfo = buspub->devinfo;
- fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
- brcmf_pcie_fwnames,
- ARRAY_SIZE(brcmf_pcie_fwnames),
- fwnames, ARRAY_SIZE(fwnames));
- if (!fwreq)
- return -ENOMEM;
+ switch (type) {
+ case BRCMF_BLOB_CLM:
+ *fw = devinfo->clm_fw;
+ devinfo->clm_fw = NULL;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ if (!*fw)
+ return -ENOENT;
- kfree(fwreq);
return 0;
}
@@ -1445,7 +1450,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
.wowl_config = brcmf_pcie_wowl_config,
.get_ramsize = brcmf_pcie_get_ramsize,
.get_memdump = brcmf_pcie_get_memdump,
- .get_fwname = brcmf_pcie_get_fwname,
+ .get_blob = brcmf_pcie_get_blob,
.reset = brcmf_pcie_reset,
};
@@ -1731,6 +1736,7 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
#define BRCMF_PCIE_FW_CODE 0
#define BRCMF_PCIE_FW_NVRAM 1
+#define BRCMF_PCIE_FW_CLM 2
static void brcmf_pcie_setup(struct device *dev, int ret,
struct brcmf_fw_request *fwreq)
@@ -1755,6 +1761,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
+ devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;
kfree(fwreq);
ret = brcmf_chip_get_raminfo(devinfo->ci);
@@ -1830,6 +1837,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
struct brcmf_fw_name fwnames[] = {
{ ".bin", devinfo->fw_name },
{ ".txt", devinfo->nvram_name },
+ { ".clm_blob", devinfo->clm_name },
};
fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
@@ -1842,6 +1850,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
+ fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
+ fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->board_type = devinfo->settings->board_type;
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
@@ -1981,6 +1991,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
brcmf_pcie_release_ringbuffers(devinfo);
brcmf_pcie_reset_device(devinfo);
brcmf_pcie_release_resource(devinfo);
+ release_firmware(devinfo->clm_fw);
if (devinfo->ci)
brcmf_chip_detach(devinfo->ci);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 212fbbe1cd7e..27dc8ed29ac8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4130,23 +4130,24 @@ brcmf_sdio_watchdog(struct timer_list *t)
}
}
-static
-int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+static int brcmf_sdio_get_blob(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_fw_request *fwreq;
- struct brcmf_fw_name fwnames[] = {
- { ext, fw_name },
- };
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
- brcmf_sdio_fwnames,
- ARRAY_SIZE(brcmf_sdio_fwnames),
- fwnames, ARRAY_SIZE(fwnames));
- if (!fwreq)
- return -ENOMEM;
+ switch (type) {
+ case BRCMF_BLOB_CLM:
+ *fw = sdiodev->clm_fw;
+ sdiodev->clm_fw = NULL;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ if (!*fw)
+ return -ENOENT;
- kfree(fwreq);
return 0;
}
@@ -4189,13 +4190,14 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.wowl_config = brcmf_sdio_wowl_config,
.get_ramsize = brcmf_sdio_bus_get_ramsize,
.get_memdump = brcmf_sdio_bus_get_memdump,
- .get_fwname = brcmf_sdio_get_fwname,
+ .get_blob = brcmf_sdio_get_blob,
.debugfs_create = brcmf_sdio_debugfs_create,
.reset = brcmf_sdio_bus_reset
};
#define BRCMF_SDIO_FW_CODE 0
#define BRCMF_SDIO_FW_NVRAM 1
+#define BRCMF_SDIO_FW_CLM 2
static void brcmf_sdio_firmware_callback(struct device *dev, int err,
struct brcmf_fw_request *fwreq)
@@ -4218,6 +4220,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
+ sdiod->clm_fw = fwreq->items[BRCMF_SDIO_FW_CLM].binary;
kfree(fwreq);
/* try to download image and nvram to the dongle */
@@ -4416,6 +4419,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
struct brcmf_fw_name fwnames[] = {
{ ".bin", bus->sdiodev->fw_name },
{ ".txt", bus->sdiodev->nvram_name },
+ { ".clm_blob", bus->sdiodev->clm_name },
};
fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
@@ -4427,6 +4431,8 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
+ fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
+ fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->board_type = bus->sdiodev->settings->board_type;
return fwreq;
@@ -4583,6 +4589,8 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
if (bus->sdiodev->settings)
brcmf_release_module_param(bus->sdiodev->settings);
+ release_firmware(bus->sdiodev->clm_fw);
+ bus->sdiodev->clm_fw = NULL;
kfree(bus->rxbuf);
kfree(bus->hdrbuf);
kfree(bus);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 15d2c02fa3ec..7b74c295e4c9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -186,9 +186,11 @@ struct brcmf_sdio_dev {
struct sg_table sgtable;
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
+ char clm_name[BRCMF_FW_NAME_LEN];
bool wowl_enabled;
enum brcmf_sdiod_state state;
struct brcmf_sdiod_freezer *freezer;
+ const struct firmware *clm_fw;
};
/* sdio core registers */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 9fb68c2dc7e3..85e18fb9c497 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1154,24 +1154,11 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
return NULL;
}
-static
-int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+static int brcmf_usb_get_blob(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
- struct brcmf_bus *bus = dev_get_drvdata(dev);
- struct brcmf_fw_request *fwreq;
- struct brcmf_fw_name fwnames[] = {
- { ext, fw_name },
- };
-
- fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev,
- brcmf_usb_fwnames,
- ARRAY_SIZE(brcmf_usb_fwnames),
- fwnames, ARRAY_SIZE(fwnames));
- if (!fwreq)
- return -ENOMEM;
-
- kfree(fwreq);
- return 0;
+ /* No blobs for USB devices... */
+ return -ENOENT;
}
static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
@@ -1180,7 +1167,7 @@ static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx,
.txctl = brcmf_usb_tx_ctlpkt,
.rxctl = brcmf_usb_rx_ctlpkt,
- .get_fwname = brcmf_usb_get_fwname,
+ .get_blob = brcmf_usb_get_blob,
};
#define BRCMF_USB_FW_CODE 0
--
2.34.1

View File

@ -0,0 +1,181 @@
From 95500b48e476af858b0a3ae6c96d9fe8ab92cb61 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Fri, 7 Jan 2022 11:14:44 +0900
Subject: [PATCH 088/171] brcmfmac: firmware: Support passing in multiple
board_types
Apple platforms have firmware and config files identified with multiple
dimensions. We want to be able to find the most specific firmware
available for any given platform, progressively trying more general
firmwares.
To do this, first add support for passing in multiple board_types,
which will be tried in sequence.
Since this will cause more log spam due to missing firmwares, also
switch the secondary firmware fecthes to use the _nowarn variant, which
will not log if the firmware is not found.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 53 +++++++++++++++----
.../broadcom/brcm80211/brcmfmac/firmware.h | 4 +-
.../broadcom/brcm80211/brcmfmac/pcie.c | 4 +-
.../broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
4 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index deacd39b3f7b..d04a59cf4a1e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -430,6 +430,7 @@ struct brcmf_fw {
struct device *dev;
struct brcmf_fw_request *req;
u32 curpos;
+ unsigned int board_index;
void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
};
@@ -625,17 +626,21 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,
struct brcmf_fw *fwctx)
{
struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos];
+ unsigned int i;
int ret;
- /* Files can be board-specific, first try a board-specific path */
- if (fwctx->req->board_type) {
+ /* Files can be board-specific, first try board-specific paths */
+ for (i = 0; i < ARRAY_SIZE(fwctx->req->board_types); i++) {
char *alt_path;
- alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type);
+ if (!fwctx->req->board_types[i])
+ goto fallback;
+ alt_path = brcm_alt_fw_path(cur->path,
+ fwctx->req->board_types[i]);
if (!alt_path)
goto fallback;
- ret = request_firmware(fw, alt_path, fwctx->dev);
+ ret = firmware_request_nowarn(fw, alt_path, fwctx->dev);
kfree(alt_path);
if (ret == 0)
return ret;
@@ -669,15 +674,40 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)
{
struct brcmf_fw *fwctx = ctx;
struct brcmf_fw_item *first = &fwctx->req->items[0];
+ const char *board_type, *alt_path;
int ret = 0;
- /* Fall back to canonical path if board firmware not found */
- if (!fw)
- ret = request_firmware_nowait(THIS_MODULE, true, first->path,
+ if (fw) {
+ brcmf_fw_request_done(fw, ctx);
+ return;
+ }
+
+ /* Try next board firmware */
+ if (fwctx->board_index < ARRAY_SIZE(fwctx->req->board_types)) {
+ board_type = fwctx->req->board_types[fwctx->board_index++];
+ if (!board_type)
+ goto fallback;
+ alt_path = brcm_alt_fw_path(first->path, board_type);
+ if (!alt_path)
+ goto fallback;
+
+ ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
fwctx->dev, GFP_KERNEL, fwctx,
- brcmf_fw_request_done);
+ brcmf_fw_request_done_alt_path);
+ kfree(alt_path);
- if (fw || ret < 0)
+ if (ret < 0)
+ brcmf_fw_request_done(fw, ctx);
+ return;
+ }
+
+fallback:
+ /* Fall back to canonical path if board firmware not found */
+ ret = request_firmware_nowait(THIS_MODULE, true, first->path,
+ fwctx->dev, GFP_KERNEL, fwctx,
+ brcmf_fw_request_done);
+
+ if (ret < 0)
brcmf_fw_request_done(fw, ctx);
}
@@ -721,10 +751,11 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
fwctx->done = fw_cb;
/* First try alternative board-specific path if any */
- if (fwctx->req->board_type)
+ if (fwctx->req->board_types[0])
alt_path = brcm_alt_fw_path(first->path,
- fwctx->req->board_type);
+ fwctx->req->board_types[0]);
if (alt_path) {
+ fwctx->board_index++;
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
fwctx->dev, GFP_KERNEL, fwctx,
brcmf_fw_request_done_alt_path);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
index e290dec9c53d..1266cbaee072 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -11,6 +11,8 @@
#define BRCMF_FW_DEFAULT_PATH "brcm/"
+#define BRCMF_FW_MAX_BOARD_TYPES 8
+
/**
* struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
* filename and nvram filename. Each bus type implementation should create
@@ -66,7 +68,7 @@ struct brcmf_fw_request {
u16 domain_nr;
u16 bus_nr;
u32 n_items;
- const char *board_type;
+ const char *board_types[BRCMF_FW_MAX_BOARD_TYPES];
struct brcmf_fw_item items[];
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index ec73d2620ec9..2a74c9d8d46a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -1852,11 +1852,13 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
- fwreq->board_type = devinfo->settings->board_type;
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
fwreq->bus_nr = devinfo->pdev->bus->number;
+ brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);
+ fwreq->board_types[0] = devinfo->settings->board_type;
+
return fwreq;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 27dc8ed29ac8..2b71991f7d9b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4433,7 +4433,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
- fwreq->board_type = bus->sdiodev->settings->board_type;
+ fwreq->board_types[0] = bus->sdiodev->settings->board_type;
return fwreq;
}
--
2.34.1

View File

@ -0,0 +1,299 @@
From e5b8ff4d315b814e2d81e40838a6df7164f61a77 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:26:34 +0900
Subject: [PATCH 089/171] brcmfmac: pcie: Read Apple OTP information
On Apple platforms, the One Time Programmable ROM in the Broadcom chips
contains information about the specific board design (module, vendor,
version) that is required to select the correct NVRAM file. Parse this
OTP ROM and extract the required strings.
Note that the user OTP offset/size is per-chip. This patch does not add
any chips yet.
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 218 ++++++++++++++++++
include/linux/bcma/bcma_driver_chipcommon.h | 1 +
2 files changed, 219 insertions(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 2a74c9d8d46a..17d0353e9105 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -256,6 +256,15 @@ struct brcmf_pcie_core_info {
u32 wrapbase;
};
+#define BRCMF_OTP_MAX_PARAM_LEN 16
+
+struct brcmf_otp_params {
+ char module[BRCMF_OTP_MAX_PARAM_LEN];
+ char vendor[BRCMF_OTP_MAX_PARAM_LEN];
+ char version[BRCMF_OTP_MAX_PARAM_LEN];
+ bool valid;
+};
+
struct brcmf_pciedev_info {
enum brcmf_pcie_state state;
bool in_irq;
@@ -283,6 +292,7 @@ struct brcmf_pciedev_info {
void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
u16 value);
struct brcmf_mp_device *settings;
+ struct brcmf_otp_params otp;
};
struct brcmf_pcie_ringbuf {
@@ -354,6 +364,14 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
static struct brcmf_fw_request *
brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo);
+static u16
+brcmf_pcie_read_reg16(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
+{
+ void __iomem *address = devinfo->regs + reg_offset;
+
+ return ioread16(address);
+}
+
static u32
brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
{
@@ -499,6 +517,8 @@ brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
}
+#define READCC32(devinfo, reg) brcmf_pcie_read_reg32(devinfo, \
+ CHIPCREGOFFS(reg))
#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
CHIPCREGOFFS(reg), value)
@@ -1734,6 +1754,198 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
.write32 = brcmf_pcie_buscore_write32,
};
+#define BRCMF_OTP_SYS_VENDOR 0x15
+#define BRCMF_OTP_BRCM_CIS 0x80
+
+#define BRCMF_OTP_VENDOR_HDR 0x00000008
+
+static int
+brcmf_pcie_parse_otp_sys_vendor(struct brcmf_pciedev_info *devinfo,
+ u8 *data, size_t size)
+{
+ int idx = 4;
+ const char *chip_params;
+ const char *board_params;
+ const char *p;
+
+ /* 4-byte header and two empty strings */
+ if (size < 6)
+ return -EINVAL;
+
+ if (get_unaligned_le32(data) != BRCMF_OTP_VENDOR_HDR)
+ return -EINVAL;
+
+ chip_params = &data[idx];
+
+ /* Skip first string, including terminator */
+ idx += strnlen(chip_params, size - idx) + 1;
+ if (idx >= size)
+ return -EINVAL;
+
+ board_params = &data[idx];
+
+ /* Skip to terminator of second string */
+ idx += strnlen(board_params, size - idx);
+ if (idx >= size)
+ return -EINVAL;
+
+ /* At this point both strings are guaranteed NUL-terminated */
+ brcmf_dbg(PCIE, "OTP: chip_params='%s' board_params='%s'\n",
+ chip_params, board_params);
+
+ p = skip_spaces(board_params);
+ while (*p) {
+ char tag = *p++;
+ const char *end;
+ size_t len;
+
+ if (*p++ != '=') /* implicit NUL check */
+ return -EINVAL;
+
+ /* *p might be NUL here, if so end == p and len == 0 */
+ end = strchrnul(p, ' ');
+ len = end - p;
+
+ /* leave 1 byte for NUL in destination string */
+ if (len > (BRCMF_OTP_MAX_PARAM_LEN - 1))
+ return -EINVAL;
+
+ /* Copy len characters plus a NUL terminator */
+ switch (tag) {
+ case 'M':
+ strscpy(devinfo->otp.module, p, len + 1);
+ break;
+ case 'V':
+ strscpy(devinfo->otp.vendor, p, len + 1);
+ break;
+ case 'm':
+ strscpy(devinfo->otp.version, p, len + 1);
+ break;
+ }
+
+ /* Skip to next arg, if any */
+ p = skip_spaces(end);
+ }
+
+ brcmf_dbg(PCIE, "OTP: module=%s vendor=%s version=%s\n",
+ devinfo->otp.module, devinfo->otp.vendor,
+ devinfo->otp.version);
+
+ if (!devinfo->otp.module[0] ||
+ !devinfo->otp.vendor[0] ||
+ !devinfo->otp.version[0])
+ return -EINVAL;
+
+ devinfo->otp.valid = true;
+ return 0;
+}
+
+static int
+brcmf_pcie_parse_otp(struct brcmf_pciedev_info *devinfo, u8 *otp, size_t size)
+{
+ int p = 0;
+ int ret = -EINVAL;
+
+ brcmf_dbg(PCIE, "parse_otp size=%ld\n", size);
+
+ while (p < (size - 1)) {
+ u8 type = otp[p];
+ u8 length = otp[p + 1];
+
+ if (type == 0)
+ break;
+
+ if ((p + 2 + length) > size)
+ break;
+
+ switch (type) {
+ case BRCMF_OTP_SYS_VENDOR:
+ brcmf_dbg(PCIE, "OTP @ 0x%x (%d): SYS_VENDOR\n",
+ p, length);
+ ret = brcmf_pcie_parse_otp_sys_vendor(devinfo,
+ &otp[p + 2],
+ length);
+ break;
+ case BRCMF_OTP_BRCM_CIS:
+ brcmf_dbg(PCIE, "OTP @ 0x%x (%d): BRCM_CIS\n",
+ p, length);
+ break;
+ default:
+ brcmf_dbg(PCIE, "OTP @ 0x%x (%d): Unknown type 0x%x\n",
+ p, length, type);
+ break;
+ }
+
+ p += 2 + length;
+ }
+
+ return ret;
+}
+
+static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
+{
+ const struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
+ u32 coreid, base, words, idx, sromctl;
+ u16 *otp;
+ struct brcmf_core *core;
+ int ret;
+
+ switch (devinfo->ci->chip) {
+ default:
+ /* OTP not supported on this chip */
+ return 0;
+ }
+
+ core = brcmf_chip_get_core(devinfo->ci, coreid);
+ if (!core) {
+ brcmf_err(bus, "No OTP core\n");
+ return -ENODEV;
+ }
+
+ if (coreid == BCMA_CORE_CHIPCOMMON) {
+ /* Chips with OTP accessed via ChipCommon need additional
+ * handling to access the OTP
+ */
+ brcmf_pcie_select_core(devinfo, coreid);
+ sromctl = READCC32(devinfo, sromcontrol);
+
+ if (!(sromctl & BCMA_CC_SROM_CONTROL_OTP_PRESENT)) {
+ /* Chip lacks OTP, try without it... */
+ brcmf_err(bus,
+ "OTP unavailable, using default firmware\n");
+ return 0;
+ }
+
+ /* Map OTP to shadow area */
+ WRITECC32(devinfo, sromcontrol,
+ sromctl | BCMA_CC_SROM_CONTROL_OTPSEL);
+ }
+
+ otp = kcalloc(words, sizeof(u16), GFP_KERNEL);
+ if (!otp)
+ return -ENOMEM;
+
+ /* Map bus window to SROM/OTP shadow area in core */
+ base = brcmf_pcie_buscore_prep_addr(devinfo->pdev, base + core->base);
+
+ brcmf_dbg(PCIE, "OTP data:\n");
+ for (idx = 0; idx < words; idx++) {
+ otp[idx] = brcmf_pcie_read_reg16(devinfo, base + 2 * idx);
+ brcmf_dbg(PCIE, "[%8x] 0x%04x\n", base + 2 * idx, otp[idx]);
+ }
+
+ if (coreid == BCMA_CORE_CHIPCOMMON) {
+ brcmf_pcie_select_core(devinfo, coreid);
+ WRITECC32(devinfo, sromcontrol, sromctl);
+ }
+
+ ret = brcmf_pcie_parse_otp(devinfo, (u8 *)otp, 2 * words);
+ kfree(otp);
+
+ return ret;
+}
+
#define BRCMF_PCIE_FW_CODE 0
#define BRCMF_PCIE_FW_NVRAM 1
#define BRCMF_PCIE_FW_CLM 2
@@ -1930,6 +2142,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto fail_bus;
+ ret = brcmf_pcie_read_otp(devinfo);
+ if (ret) {
+ brcmf_err(bus, "failed to parse OTP\n");
+ goto fail_brcmf;
+ }
+
fwreq = brcmf_pcie_prepare_fw_request(devinfo);
if (!fwreq) {
ret = -ENOMEM;
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index e3314f746bfa..2d94c30ed439 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -271,6 +271,7 @@
#define BCMA_CC_SROM_CONTROL_OP_WRDIS 0x40000000
#define BCMA_CC_SROM_CONTROL_OP_WREN 0x60000000
#define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010
+#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020
#define BCMA_CC_SROM_CONTROL_LOCK 0x00000008
#define BCMA_CC_SROM_CONTROL_SIZE_MASK 0x00000006
#define BCMA_CC_SROM_CONTROL_SIZE_1K 0x00000000
--
2.34.1

View File

@ -0,0 +1,68 @@
From 59a447e856db9a2c8312d617a6a4f89a629d1bff Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:27:19 +0900
Subject: [PATCH 090/171] brcmfmac: of: Fetch Apple properties
On Apple ARM64 platforms, firmware selection requires two properties
that come from system firmware: the module-instance (aka "island", a
codename representing a given hardware platform) and the antenna-sku.
We map Apple's module codenames to board_types in the form
"apple,<module-instance>".
The mapped board_type is added to the DTS file in that form, while the
antenna-sku is forwarded by our bootloader from the Apple Device Tree
into the FDT. Grab them from the DT so firmware selection can use
them.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../wireless/broadcom/brcm80211/brcmfmac/common.h | 1 +
.../net/wireless/broadcom/brcm80211/brcmfmac/of.c | 12 +++++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index 15accc88d5c0..1f678bbd87aa 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -51,6 +51,7 @@ struct brcmf_mp_device {
struct brcmfmac_pd_cc *country_codes;
const char *board_type;
unsigned char mac[ETH_ALEN];
+ const char *antenna_sku;
union {
struct brcmfmac_sdio_pd sdio;
} bus;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
index 083ac58f466d..644cc48eae40 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
@@ -64,14 +64,24 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
{
struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
struct device_node *root, *np = dev->of_node;
+ const char *prop;
int irq;
int err;
u32 irqf;
u32 val;
+ /* Apple ARM64 platforms have their own idea of board type, passed in
+ * via the device tree. They also have an antenna SKU parameter
+ */
+ if (!of_property_read_string(np, "brcm,board-type", &prop))
+ settings->board_type = prop;
+
+ if (!of_property_read_string(np, "apple,antenna-sku", &prop))
+ settings->antenna_sku = prop;
+
/* Set board-type to the first string of the machine compatible prop */
root = of_find_node_by_path("/");
- if (root) {
+ if (root && !settings->board_type) {
int i;
char *board_type;
const char *tmp;
--
2.34.1

View File

@ -0,0 +1,134 @@
From 608e39fd3521d26bfc846383626f4605d7b273a7 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:45:21 +0900
Subject: [PATCH 091/171] brcmfmac: pcie: Perform firmware selection for Apple
platforms
On Apple platforms, firmware selection uses the following elements:
Property Example Source
============== ======= ========================
* Chip name 4378 Device ID
* Chip revision B1 OTP
* Platform shikoku DT (ARM64) or ACPI (x86)
* Module type RASP OTP
* Module vendor m OTP
* Module version 6.11 OTP
* Antenna SKU X3 DT (ARM64) or ACPI (x86)
In macOS, these firmwares are stored using filenames in this format
under /usr/share/firmware/wifi:
C-4378__s-B1/P-shikoku-X3_M-RASP_V-m__m-6.11.txt
To prepare firmwares for Linux, we rename these to a scheme following
the existing brcmfmac convention:
brcmfmac<chip><lower(rev)>-pcie.apple,<platform>-<mod_type>-\
<mod_vendor>-<mod_version>-<antenna_sku>.txt
The NVRAM uses all the components, while the firmware and CLM blob only
use the chip/revision/platform/antenna_sku:
brcmfmac<chip><lower(rev)>-pcie.apple,<platform>-<antenna_sku>.bin
e.g.
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.bin
In addition, since there are over 1000 files in total, many of which are
symlinks or outright duplicates, we deduplicate and prune the firmware
tree to reduce firmware filenames to fewer dimensions. For example, the
shikoku platform (MacBook Air M1 2020) simplifies to just 4 files:
brcm/brcmfmac4378b1-pcie.apple,shikoku.clm_blob
brcm/brcmfmac4378b1-pcie.apple,shikoku.bin
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-u.txt
This reduces the total file count to around 170, of which 75 are
symlinks and 95 are regular files: 7 firmware blobs, 27 CLM blobs, and
61 NVRAM config files. We also slightly process NVRAM files to correct
some formatting issues.
To handle this, the driver must try the following path formats when
looking for firmware files:
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.txt *
brcm/brcmfmac4378b1-pcie.apple,shikoku.txt
* Not relevant for NVRAM, only for firmware/CLM.
The chip revision nominally comes from OTP on Apple platforms, but it
can be mapped to the PCI revision number, so we ignore the OTP revision
and continue to use the existing PCI revision mechanism to identify chip
revisions, as the driver already does for other chips. Unfortunately,
the mapping is not consistent between different chip types, so this has
to be determined experimentally.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 41 ++++++++++++++++++-
1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 17d0353e9105..86807d990cc7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -2068,8 +2068,45 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
fwreq->bus_nr = devinfo->pdev->bus->number;
- brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);
- fwreq->board_types[0] = devinfo->settings->board_type;
+ /* Apple platforms with fancy firmware/NVRAM selection */
+ if (devinfo->settings->board_type &&
+ devinfo->settings->antenna_sku &&
+ devinfo->otp.valid) {
+ const struct brcmf_otp_params *otp = &devinfo->otp;
+ struct device *dev = &devinfo->pdev->dev;
+ const char **bt = fwreq->board_types;
+
+ brcmf_dbg(PCIE, "Apple board: %s\n",
+ devinfo->settings->board_type);
+
+ /* Example: apple,shikoku-RASP-m-6.11-X3 */
+ bt[0] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s-%s",
+ devinfo->settings->board_type,
+ otp->module, otp->vendor, otp->version,
+ devinfo->settings->antenna_sku);
+ bt[1] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s",
+ devinfo->settings->board_type,
+ otp->module, otp->vendor, otp->version);
+ bt[2] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s",
+ devinfo->settings->board_type,
+ otp->module, otp->vendor);
+ bt[3] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
+ devinfo->settings->board_type,
+ otp->module);
+ bt[4] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
+ devinfo->settings->board_type,
+ devinfo->settings->antenna_sku);
+ bt[5] = devinfo->settings->board_type;
+
+ if (!bt[0] || !bt[1] || !bt[2] || !bt[3] || !bt[4]) {
+ kfree(fwreq);
+ return NULL;
+ }
+
+ } else {
+ brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);
+ fwreq->board_types[0] = devinfo->settings->board_type;
+ }
return fwreq;
}
--
2.34.1

View File

@ -0,0 +1,125 @@
From 76efd4b5d7adea522c649c6b44d7379e981141b5 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 23 Dec 2021 22:32:08 +0900
Subject: [PATCH 092/171] brcmfmac: firmware: Allow platform to override
macaddr
On Device Tree platforms, it is customary to be able to set the MAC
address via the Device Tree, as it is often stored in system firmware.
This is particularly relevant for Apple ARM64 platforms, where this
information comes from system configuration and passed through by the
bootloader into the DT.
Implement support for this by fetching the platform MAC address and
adding or replacing the macaddr= property in nvram. This becomes the
dongle's default MAC address.
On platforms with an SROM MAC address, this overrides it. On platforms
without one, such as Apple ARM64 devices, this is required for the
firmware to boot (it will fail if it does not have a valid MAC at all).
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 28 +++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index d04a59cf4a1e..fbfc9458d240 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -21,6 +21,8 @@
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff"
+#define BRCMF_FW_MACADDR_FMT "macaddr=%pM"
+#define BRCMF_FW_MACADDR_LEN (7 + ETH_ALEN * 3)
enum nvram_parser_state {
IDLE,
@@ -57,6 +59,7 @@ struct nvram_parser {
bool multi_dev_v1;
bool multi_dev_v2;
bool boardrev_found;
+ bool strip_mac;
};
/*
@@ -121,6 +124,10 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
nvp->multi_dev_v2 = true;
if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0)
nvp->boardrev_found = true;
+ /* strip macaddr if platform MAC overrides */
+ if (nvp->strip_mac &&
+ strncmp(&nvp->data[nvp->entry], "macaddr", 7) == 0)
+ st = COMMENT;
} else if (!is_nvram_char(c) || c == ' ') {
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
nvp->line, nvp->column);
@@ -209,6 +216,7 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
size = data_len;
/* Add space for properties we may add */
size += strlen(BRCMF_FW_DEFAULT_BOARDREV) + 1;
+ size += BRCMF_FW_MACADDR_LEN + 1;
/* Alloc for extra 0 byte + roundup by 4 + length field */
size += 1 + 3 + sizeof(u32);
nvp->nvram = kzalloc(size, GFP_KERNEL);
@@ -368,22 +376,34 @@ static void brcmf_fw_add_defaults(struct nvram_parser *nvp)
nvp->nvram_len++;
}
+static void brcmf_fw_add_macaddr(struct nvram_parser *nvp, u8 *mac)
+{
+ BUG_ON(snprintf(&nvp->nvram[nvp->nvram_len], BRCMF_FW_MACADDR_LEN + 1,
+ BRCMF_FW_MACADDR_FMT, mac) != BRCMF_FW_MACADDR_LEN);
+ nvp->nvram_len += BRCMF_FW_MACADDR_LEN + 1;
+}
+
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
* End of buffer is completed with token identifying length of buffer.
*/
static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
- u32 *new_length, u16 domain_nr, u16 bus_nr)
+ u32 *new_length, u16 domain_nr, u16 bus_nr,
+ struct device *dev)
{
struct nvram_parser nvp;
u32 pad;
u32 token;
__le32 token_le;
+ u8 mac[ETH_ALEN];
if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
return NULL;
+ if (eth_platform_get_mac_address(dev, mac) == 0)
+ nvp.strip_mac = true;
+
while (nvp.pos < data_len) {
nvp.state = nv_parser_states[nvp.state](&nvp);
if (nvp.state == END)
@@ -404,6 +424,9 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
brcmf_fw_add_defaults(&nvp);
+ if (nvp.strip_mac)
+ brcmf_fw_add_macaddr(&nvp, mac);
+
pad = nvp.nvram_len;
*new_length = roundup(nvp.nvram_len + 1, 4);
while (pad != *new_length) {
@@ -547,7 +570,8 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
if (data)
nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
fwctx->req->domain_nr,
- fwctx->req->bus_nr);
+ fwctx->req->bus_nr,
+ fwctx->dev);
if (free_bcm47xx_nvram)
bcm47xx_nvram_release_contents(data);
--
2.34.1

View File

@ -0,0 +1,36 @@
From 9fd60252c13e93ca8ff245f63faf248da6c390f4 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:39:04 +0900
Subject: [PATCH 093/171] brcmfmac: msgbuf: Increase RX ring sizes to 1024
Newer chips used on Apple platforms have a max_rxbufpost greater than
512, which causes warnings when brcmf_msgbuf_rxbuf_data_fill tries to
put more entries in the ring than will fit. Increase the ring sizes
to 1024.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
index 2e322edbb907..6a849f4a94dd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
@@ -8,10 +8,10 @@
#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 64
-#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 512
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 1024
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 64
#define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024
-#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 512
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 1024
#define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40
--
2.34.1

View File

@ -0,0 +1,265 @@
From aa48c835720f5e04ebbe14e3f6b053c8415fb6d9 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:25:35 +0900
Subject: [PATCH 094/171] brcmfmac: pcie: Support PCIe core revisions >= 64
These newer PCIe core revisions include new sets of registers that must
be used instead of the legacy ones. Introduce a brcmf_pcie_reginfo to
hold the specific register offsets and values to use for a given
platform, and change all the register accesses to indirect through it.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 125 +++++++++++++++---
1 file changed, 105 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 86807d990cc7..a2ef3de834f6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -119,6 +119,12 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0 0x140
#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1 0x144
+#define BRCMF_PCIE_64_PCIE2REG_INTMASK 0xC14
+#define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT 0xC30
+#define BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK 0xC34
+#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0 0xA20
+#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1 0xA24
+
#define BRCMF_PCIE2_INTA 0x01
#define BRCMF_PCIE2_INTB 0x02
@@ -138,6 +144,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_PCIE_MB_INT_D2H3_DB0 0x400000
#define BRCMF_PCIE_MB_INT_D2H3_DB1 0x800000
+#define BRCMF_PCIE_MB_INT_FN0 (BRCMF_PCIE_MB_INT_FN0_0 | \
+ BRCMF_PCIE_MB_INT_FN0_1)
#define BRCMF_PCIE_MB_INT_D2H_DB (BRCMF_PCIE_MB_INT_D2H0_DB0 | \
BRCMF_PCIE_MB_INT_D2H0_DB1 | \
BRCMF_PCIE_MB_INT_D2H1_DB0 | \
@@ -147,6 +155,40 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_PCIE_MB_INT_D2H3_DB0 | \
BRCMF_PCIE_MB_INT_D2H3_DB1)
+#define BRCMF_PCIE_64_MB_INT_D2H0_DB0 0x1
+#define BRCMF_PCIE_64_MB_INT_D2H0_DB1 0x2
+#define BRCMF_PCIE_64_MB_INT_D2H1_DB0 0x4
+#define BRCMF_PCIE_64_MB_INT_D2H1_DB1 0x8
+#define BRCMF_PCIE_64_MB_INT_D2H2_DB0 0x10
+#define BRCMF_PCIE_64_MB_INT_D2H2_DB1 0x20
+#define BRCMF_PCIE_64_MB_INT_D2H3_DB0 0x40
+#define BRCMF_PCIE_64_MB_INT_D2H3_DB1 0x80
+#define BRCMF_PCIE_64_MB_INT_D2H4_DB0 0x100
+#define BRCMF_PCIE_64_MB_INT_D2H4_DB1 0x200
+#define BRCMF_PCIE_64_MB_INT_D2H5_DB0 0x400
+#define BRCMF_PCIE_64_MB_INT_D2H5_DB1 0x800
+#define BRCMF_PCIE_64_MB_INT_D2H6_DB0 0x1000
+#define BRCMF_PCIE_64_MB_INT_D2H6_DB1 0x2000
+#define BRCMF_PCIE_64_MB_INT_D2H7_DB0 0x4000
+#define BRCMF_PCIE_64_MB_INT_D2H7_DB1 0x8000
+
+#define BRCMF_PCIE_64_MB_INT_D2H_DB (BRCMF_PCIE_64_MB_INT_D2H0_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H0_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H1_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H1_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H2_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H2_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H3_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H3_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H4_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H4_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H5_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H5_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H6_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H6_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H7_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H7_DB1)
+
#define BRCMF_PCIE_SHARED_VERSION_7 7
#define BRCMF_PCIE_MIN_SHARED_VERSION 5
#define BRCMF_PCIE_MAX_SHARED_VERSION BRCMF_PCIE_SHARED_VERSION_7
@@ -273,6 +315,7 @@ struct brcmf_pciedev_info {
char nvram_name[BRCMF_FW_NAME_LEN];
char clm_name[BRCMF_FW_NAME_LEN];
const struct firmware *clm_fw;
+ const struct brcmf_pcie_reginfo *reginfo;
void __iomem *regs;
void __iomem *tcm;
u32 ram_base;
@@ -359,6 +402,36 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
};
+struct brcmf_pcie_reginfo {
+ u32 intmask;
+ u32 mailboxint;
+ u32 mailboxmask;
+ u32 h2d_mailbox_0;
+ u32 h2d_mailbox_1;
+ u32 int_d2h_db;
+ u32 int_fn0;
+};
+
+static const struct brcmf_pcie_reginfo brcmf_reginfo_default = {
+ .intmask = BRCMF_PCIE_PCIE2REG_INTMASK,
+ .mailboxint = BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ .mailboxmask = BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+ .h2d_mailbox_0 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0,
+ .h2d_mailbox_1 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1,
+ .int_d2h_db = BRCMF_PCIE_MB_INT_D2H_DB,
+ .int_fn0 = BRCMF_PCIE_MB_INT_FN0,
+};
+
+static const struct brcmf_pcie_reginfo brcmf_reginfo_64 = {
+ .intmask = BRCMF_PCIE_64_PCIE2REG_INTMASK,
+ .mailboxint = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT,
+ .mailboxmask = BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK,
+ .h2d_mailbox_0 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0,
+ .h2d_mailbox_1 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1,
+ .int_d2h_db = BRCMF_PCIE_64_MB_INT_D2H_DB,
+ .int_fn0 = 0,
+};
+
static void brcmf_pcie_setup(struct device *dev, int ret,
struct brcmf_fw_request *fwreq);
static struct brcmf_fw_request *
@@ -802,30 +875,29 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
{
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, 0);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
}
static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
{
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
- BRCMF_PCIE_MB_INT_D2H_DB |
- BRCMF_PCIE_MB_INT_FN0_0 |
- BRCMF_PCIE_MB_INT_FN0_1);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
+ devinfo->reginfo->int_d2h_db |
+ devinfo->reginfo->int_fn0);
}
static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
{
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)
brcmf_pcie_write_reg32(devinfo,
- BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
+ devinfo->reginfo->h2d_mailbox_1, 1);
}
static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
{
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT)) {
+ if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
brcmf_pcie_intr_disable(devinfo);
brcmf_dbg(PCIE, "Enter\n");
return IRQ_WAKE_THREAD;
@@ -840,15 +912,14 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
u32 status;
devinfo->in_irq = true;
- status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
brcmf_dbg(PCIE, "Enter %x\n", status);
if (status) {
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
status);
- if (status & (BRCMF_PCIE_MB_INT_FN0_0 |
- BRCMF_PCIE_MB_INT_FN0_1))
+ if (status & devinfo->reginfo->int_fn0)
brcmf_pcie_handle_mb_data(devinfo);
- if (status & BRCMF_PCIE_MB_INT_D2H_DB) {
+ if (status & devinfo->reginfo->int_d2h_db) {
if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
brcmf_proto_msgbuf_rx_trigger(
&devinfo->pdev->dev);
@@ -907,8 +978,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
if (devinfo->in_irq)
brcmf_err(bus, "Still in IRQ (processing) !!!\n");
- status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status);
+ status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
devinfo->irq_allocated = false;
}
@@ -960,7 +1031,7 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
brcmf_dbg(PCIE, "RING !\n");
/* Any arbitrary value will do, lets use 1 */
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->h2d_mailbox_0, 1);
return 0;
}
@@ -1723,15 +1794,22 @@ static int brcmf_pcie_buscoreprep(void *ctx)
static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
{
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
- u32 val;
+ struct brcmf_core *core;
+ u32 val, reg;
devinfo->ci = chip;
brcmf_pcie_reset_device(devinfo);
- val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ /* reginfo is not ready yet */
+ core = brcmf_chip_get_core(chip, BCMA_CORE_PCIE2);
+ if (core->rev >= 64)
+ reg = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT;
+ else
+ reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
+
+ val = brcmf_pcie_read_reg32(devinfo, reg);
if (val != 0xffffffff)
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
- val);
+ brcmf_pcie_write_reg32(devinfo, reg, val);
return 0;
}
@@ -2119,6 +2197,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct brcmf_pciedev_info *devinfo;
struct brcmf_pciedev *pcie_bus_dev;
struct brcmf_bus *bus;
+ struct brcmf_core *core;
brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
@@ -2137,6 +2216,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto fail;
}
+ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
+ if (core->rev >= 64)
+ devinfo->reginfo = &brcmf_reginfo_64;
+ else
+ devinfo->reginfo = &brcmf_reginfo_default;
+
pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);
if (pcie_bus_dev == NULL) {
ret = -ENOMEM;
@@ -2306,7 +2391,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
/* Check if device is still up and running, if so we are ready */
- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
+ if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {
brcmf_dbg(PCIE, "Try to wakeup device....\n");
if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
goto cleanup;
--
2.34.1

View File

@ -0,0 +1,97 @@
From 54af2b6f4ba6a6a477d9739d24fafe447b1235a3 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 21 Dec 2021 17:46:40 +0900
Subject: [PATCH 095/171] brcmfmac: pcie: Add IDs/properties for BCM4378
This chip is present on Apple M1 (t8103) platforms:
* atlantisb (apple,j274): Mac mini (M1, 2020)
* honshu (apple,j293): MacBook Pro (13-inch, M1, 2020)
* shikoku (apple,j313): MacBook Air (M1, 2020)
* capri (apple,j456): iMac (24-inch, 4x USB-C, M1, 2020)
* santorini (apple,j457): iMac (24-inch, 2x USB-C, M1, 2020)
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 ++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 ++++++++
.../net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++
3 files changed, 12 insertions(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index 4ec7773b6906..7f1d6cea2141 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -732,6 +732,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
return 0x160000;
case CY_CC_43752_CHIP_ID:
return 0x170000;
+ case BRCM_CC_4378_CHIP_ID:
+ return 0x352000;
default:
brcmf_err("unknown chip: %s\n", ci->pub.name);
break;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index a2ef3de834f6..2ca2c4b603cf 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -59,6 +59,7 @@ BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");
BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
+BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
/* firmware config files */
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
@@ -88,6 +89,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
+ BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* 3 */
};
#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */
@@ -1970,6 +1972,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
int ret;
switch (devinfo->ci->chip) {
+ case BRCM_CC_4378_CHIP_ID:
+ coreid = BCMA_CORE_GCI;
+ base = 0x1120;
+ words = 0x170;
+ break;
default:
/* OTP not supported on this chip */
return 0;
@@ -2458,6 +2465,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID),
{ /* end: all zeroes */ }
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index ed0b707f0cdf..43158a404652 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -51,6 +51,7 @@
#define BRCM_CC_43664_CHIP_ID 43664
#define BRCM_CC_43666_CHIP_ID 43666
#define BRCM_CC_4371_CHIP_ID 0x4371
+#define BRCM_CC_4378_CHIP_ID 0x4378
#define CY_CC_4373_CHIP_ID 0x4373
#define CY_CC_43012_CHIP_ID 43012
#define CY_CC_43752_CHIP_ID 43752
@@ -87,6 +88,7 @@
#define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4
#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5
#define BRCM_PCIE_4371_DEVICE_ID 0x440d
+#define BRCM_PCIE_4378_DEVICE_ID 0x4425
/* brcmsmac IDs */
--
2.34.1

View File

@ -0,0 +1,55 @@
From 7107b9724f933acdb31a3cc87dc80ce7a7484bd5 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 23 Dec 2021 19:51:11 +0900
Subject: [PATCH 096/171] ACPI / property: Support strings in Apple _DSM props
The Wi-Fi module in Apple machines has a "module-instance" device
property that specifies the platform type and is used for firmware
selection. Its value is a string, so add support for string values in
acpi_extract_apple_properties().
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
drivers/acpi/x86/apple.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/x86/apple.c b/drivers/acpi/x86/apple.c
index c285c91a5e9c..71b8f103ab0f 100644
--- a/drivers/acpi/x86/apple.c
+++ b/drivers/acpi/x86/apple.c
@@ -70,13 +70,16 @@ void acpi_extract_apple_properties(struct acpi_device *adev)
if ( key->type != ACPI_TYPE_STRING ||
(val->type != ACPI_TYPE_INTEGER &&
- val->type != ACPI_TYPE_BUFFER))
+ val->type != ACPI_TYPE_BUFFER &&
+ val->type != ACPI_TYPE_STRING))
continue; /* skip invalid properties */
__set_bit(i, valid);
newsize += key->string.length + 1;
if ( val->type == ACPI_TYPE_BUFFER)
newsize += val->buffer.length;
+ else if (val->type == ACPI_TYPE_STRING)
+ newsize += val->string.length + 1;
}
numvalid = bitmap_weight(valid, numprops);
@@ -118,6 +121,12 @@ void acpi_extract_apple_properties(struct acpi_device *adev)
newprops[v].type = val->type;
if (val->type == ACPI_TYPE_INTEGER) {
newprops[v].integer.value = val->integer.value;
+ } else if (val->type == ACPI_TYPE_STRING) {
+ newprops[v].string.length = val->string.length;
+ newprops[v].string.pointer = free_space;
+ memcpy(free_space, val->string.pointer,
+ val->string.length);
+ free_space += val->string.length + 1;
} else {
newprops[v].buffer.length = val->buffer.length;
newprops[v].buffer.pointer = free_space;
--
2.34.1

View File

@ -0,0 +1,127 @@
From 30cf50137a081ece01ac609de4131e20b8cccc1c Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 23 Dec 2021 19:51:36 +0900
Subject: [PATCH 097/171] brcmfmac: acpi: Add support for fetching Apple ACPI
properties
On DT platforms, the module-instance and antenna-sku-info properties
are passed in the DT. On ACPI platforms, module-instance is passed via
the analogous Apple device property mechanism, while the antenna SKU
info is instead obtained via an ACPI method that grabs it from
non-volatile storage.
Add support for this, to allow proper firmware selection on Apple
platforms.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/Makefile | 2 +
.../broadcom/brcm80211/brcmfmac/acpi.c | 52 +++++++++++++++++++
.../broadcom/brcm80211/brcmfmac/common.c | 1 +
.../broadcom/brcm80211/brcmfmac/common.h | 9 ++++
4 files changed, 64 insertions(+)
create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
index 13c13504a6e8..19009eb9db93 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
@@ -47,3 +47,5 @@ brcmfmac-$(CONFIG_OF) += \
of.o
brcmfmac-$(CONFIG_DMI) += \
dmi.o
+brcmfmac-$(CONFIG_ACPI) += \
+ acpi.o
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c
new file mode 100644
index 000000000000..dec6a83d13b1
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/acpi.h>
+#include "debug.h"
+#include "core.h"
+#include "common.h"
+
+void brcmf_acpi_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ struct brcmf_mp_device *settings)
+{
+ acpi_status status;
+ const union acpi_object *o;
+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+
+ if (!adev)
+ return;
+
+ if (!ACPI_FAILURE(acpi_dev_get_property(adev, "module-instance",
+ ACPI_TYPE_STRING, &o))) {
+ brcmf_dbg(INFO, "ACPI module-instance=%s\n", o->string.pointer);
+ settings->board_type = devm_kasprintf(dev, GFP_KERNEL,
+ "apple,%s",
+ o->string.pointer);
+ } else {
+ brcmf_dbg(INFO, "No ACPI module-instance\n");
+ }
+
+ status = acpi_evaluate_object(adev->handle, "RWCV", NULL, &buf);
+ o = buf.pointer;
+ if (!ACPI_FAILURE(status) && o && o->type == ACPI_TYPE_BUFFER &&
+ o->buffer.length >= 2) {
+ char *antenna_sku = devm_kzalloc(dev, 3, GFP_KERNEL);
+
+ if (!antenna_sku) {
+ brcmf_err("Failed to allocate antenna-sku");
+ } else {
+ memcpy(antenna_sku, o->buffer.pointer, 2);
+ brcmf_dbg(INFO, "ACPI RWCV data=%*phN antenna-sku=%s\n",
+ (int)o->buffer.length, o->buffer.pointer,
+ antenna_sku);
+ settings->antenna_sku = antenna_sku;
+ }
+
+ kfree(buf.pointer);
+ } else {
+ brcmf_dbg(INFO, "No ACPI antenna-sku\n");
+ }
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 95d4c133efdd..ea2475bfc2d7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -448,6 +448,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
/* No platform data for this device, try OF and DMI data */
brcmf_dmi_probe(settings, chip, chiprev);
brcmf_of_probe(dev, bus_type, settings);
+ brcmf_acpi_probe(dev, bus_type, settings);
}
return settings;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index 1f678bbd87aa..960b1042a7c2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -74,6 +74,15 @@ static inline void
brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev) {}
#endif
+#ifdef CONFIG_ACPI
+void brcmf_acpi_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ struct brcmf_mp_device *settings);
+#else
+static inline void brcmf_acpi_probe(struct device *dev,
+ enum brcmf_bus_type bus_type,
+ struct brcmf_mp_device *settings) {}
+#endif
+
u8 brcmf_map_prio_to_prec(void *cfg, u8 prio);
u8 brcmf_map_prio_to_aci(void *cfg, u8 prio);
--
2.34.1

View File

@ -0,0 +1,82 @@
From b696ea7c641c2172aff67297e9c0f13d8d46620f Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Thu, 23 Dec 2021 19:30:17 +0900
Subject: [PATCH 098/171] brcmfmac: pcie: Provide a buffer of random bytes to
the device
Newer Apple firmwares on chipsets without a hardware RNG require the
host to provide a buffer of 256 random bytes to the device on
initialization. This buffer is present immediately before NVRAM,
suffixed by a footer containing a magic number and the buffer length.
This won't affect chips/firmwares that do not use this feature, so do it
unconditionally.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 2ca2c4b603cf..1e2afca5a60b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -13,6 +13,7 @@
#include <linux/bcma/bcma.h>
#include <linux/sched.h>
#include <linux/io.h>
+#include <linux/random.h>
#include <asm/unaligned.h>
#include <soc.h>
@@ -1625,6 +1626,13 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
return 0;
}
+struct brcmf_random_seed_footer {
+ __le32 length;
+ __le32 magic;
+};
+
+#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de
+#define BRCMF_RANDOM_SEED_LENGTH 0x100
static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
const struct firmware *fw, void *nvram,
@@ -1656,11 +1664,32 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
if (nvram) {
+ size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;
+ struct brcmf_random_seed_footer footer = {
+ .length = cpu_to_le32(rand_len),
+ .magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
+ };
+ void *randbuf;
+
brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
address = devinfo->ci->rambase + devinfo->ci->ramsize -
nvram_len;
memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
brcmf_fw_nvram_free(nvram);
+
+ /* Some Apple chips/firmwares expect a buffer of random data
+ * to be present before NVRAM
+ */
+ brcmf_dbg(PCIE, "Download random seed\n");
+
+ address -= sizeof(footer);
+ memcpy_toio(devinfo->tcm + address, &footer, sizeof(footer));
+
+ address -= rand_len;
+ randbuf = kzalloc(rand_len, GFP_KERNEL);
+ get_random_bytes(randbuf, rand_len);
+ memcpy_toio(devinfo->tcm + address, randbuf, rand_len);
+ kfree(randbuf);
} else {
brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
devinfo->nvram_name);
--
2.34.1

Some files were not shown because too many files have changed in this diff Show More