d1: add new target

This target adds support for the Allwinner D1 RISC-V based SoCs.

 - RISC-V single-core T-Head C906 (RV64GCV)
 - Tensilica HiFi4 DSP
 - DDR2/DDR3 support
 - 10/100/1000M ethernet
 - usual peripherals like USB2, SPI, I2C, PWM, etc.

Four boards are supported:
 - Dongshan Nezha STU
    - 512Mb RAM
    - ethernet

 - LicheePi RV Dock
    - 512Mb RAM
    - wireless-only (RTL8723DS)

 - MangoPi MQ-Pro
    - 512Mb RAM
    - there are pads available for an SPI flash
    - wireless-only (RTL8723DS)

 - Nezha D1
    - 512Mb/1Gb/2Gb RAM
    - 256Mb NAND flash
    - ethernet, wireless

Installation:
Standard SD-card installation via dd-ing the generated image to
an SD-card of at least 256Mb.

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
This commit is contained in:
Zoltan HERPAI 2023-05-24 23:51:14 +02:00
parent d41d9befb9
commit 99545b4bb1
124 changed files with 13256 additions and 0 deletions

21
target/linux/d1/Makefile Normal file
View File

@ -0,0 +1,21 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2024 Toco Technologies <info@toco.ae>
#
include $(TOPDIR)/rules.mk
ARCH:=riscv64
BOARD:=d1
BOARDNAME:=AllWinner D1 RISC-V SoC
FEATURES:=ext4 squashfs
KERNELNAME:=Image dtbs
KERNEL_PATCHVER:=6.1
include $(INCLUDE_DIR)/target.mk
define Target/Description
Build firmware images for Allwinner D1 RISC-V boards
endef
$(eval $(call BuildTarget))

View File

@ -0,0 +1,18 @@
#!/bin/sh
#
# Copyright (C) 2013-2015 OpenWrt.org
#
. /lib/functions/uci-defaults.sh
board_config_update
case "$(board_name)" in
*)
ucidef_set_interface_lan 'eth0'
;;
esac
board_config_flush
exit 0

View File

@ -0,0 +1,5 @@
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown
tts/0::askfirst:/usr/libexec/login.sh
ttyS0::askfirst:/usr/libexec/login.sh
tty1::askfirst:/usr/libexec/login.sh

396
target/linux/d1/config-6.1 Normal file
View File

@ -0,0 +1,396 @@
CONFIG_64BIT=y
# CONFIG_AHCI_SUNXI is not set
CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_MMAP_RND_BITS=18
CONFIG_ARCH_MMAP_RND_BITS_MAX=24
CONFIG_ARCH_MMAP_RND_BITS_MIN=18
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
CONFIG_ARCH_RV64I=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_WANTS_THP_SWAP=y
CONFIG_ASN1=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_MQ_PCI=y
CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
CONFIG_CC_NO_ARRAY_BOUNDS=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CLZ_TAB=y
CONFIG_CMODEL_MEDANY=y
# CONFIG_CMODEL_MEDLOW is not set
CONFIG_COMMON_CLK=y
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
# CONFIG_COMPAT_32BIT_TIME is not set
CONFIG_COMPAT_BRK=y
CONFIG_CONTEXT_TRACKING=y
CONFIG_CONTEXT_TRACKING_IDLE=y
CONFIG_COREDUMP=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_CPU_ISOLATION=y
CONFIG_CPU_RMAP=y
CONFIG_CRC16=y
# CONFIG_CRC32_SARWATE is not set
CONFIG_CRC32_SLICEBY8=y
CONFIG_CRC7=y
CONFIG_CRC_ITU_T=y
CONFIG_CRYPTO_DEV_ALLWINNER=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DMADEVICES=y
CONFIG_DMA_DIRECT_REMAP=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_SUN6I=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DTC=y
CONFIG_DWMAC_GENERIC=y
CONFIG_DWMAC_SUN8I=y
CONFIG_DWMAC_SUNXI=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EFI=y
CONFIG_EFIVAR_FS=m
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
# CONFIG_EFI_CAPSULE_LOADER is not set
# CONFIG_EFI_COCO_SECRET is not set
# CONFIG_EFI_DISABLE_PCI_DMA is not set
# CONFIG_EFI_DISABLE_RUNTIME is not set
CONFIG_EFI_EARLYCON=y
CONFIG_EFI_ESRT=y
CONFIG_EFI_GENERIC_STUB=y
CONFIG_EFI_PARAMS_FROM_FDT=y
CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_EFI_STUB=y
# CONFIG_EFI_TEST is not set
# CONFIG_EFI_ZBOOT is not set
CONFIG_ELF_CORE=y
# CONFIG_ERRATA_SIFIVE is not set
CONFIG_ERRATA_THEAD=y
CONFIG_ERRATA_THEAD_CMO=y
CONFIG_ERRATA_THEAD_PBMT=y
CONFIG_EXT4_FS=y
CONFIG_EXTCON=y
CONFIG_FAILOVER=y
CONFIG_FHANDLE=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FONT_8x16=y
CONFIG_FONT_AUTOSELECT=y
CONFIG_FONT_SUPPORT=y
CONFIG_FPU=y
CONFIG_FRAME_POINTER=y
CONFIG_FRAME_WARN=2048
CONFIG_FS_IOMAP=y
CONFIG_FS_MBCACHE=y
CONFIG_FWNODE_MDIO=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_FW_LOADER_SYSFS=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_CSUM=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IOREMAP=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_LIB_DEVMEM_IS_ALLOWED=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_IRQCHIP=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_PCF857X=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HID=y
CONFIG_HID_GENERIC=y
CONFIG_HVC_DRIVER=y
CONFIG_HVC_RISCV_SBI=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_OCORES=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=y
CONFIG_IOMMU_API=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IO_URING=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_JBD2=y
CONFIG_KALLSYMS=y
# CONFIG_KEYBOARD_SUN4I_LRADC is not set
# CONFIG_LEDS_PWM_MULTICOLOR is not set
# CONFIG_LEDS_SUN50I_A100 is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_LIBFDT=y
CONFIG_LOCALVERSION_AUTO=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_MAILBOX=y
# CONFIG_MAILBOX_TEST is not set
CONFIG_MDIO_BUS=y
CONFIG_MDIO_BUS_MUX=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
# CONFIG_MDIO_SUN4I is not set
CONFIG_MEMFD_CREATE=y
CONFIG_MFD_AXP20X=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_CORE=y
# CONFIG_MFD_SUN4I_GPADC is not set
CONFIG_MFD_SUN6I_PRCM=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_SUNXI=y
CONFIG_MMIOWB=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
# CONFIG_MUSB_PIO_ONLY is not set
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NET_PTP_CLASSIFY=y
CONFIG_NET_VENDOR_ALLWINNER=y
CONFIG_NLS=y
# CONFIG_NONPORTABLE is not set
CONFIG_NOP_USB_XCEIV=y
CONFIG_NR_CPUS=8
CONFIG_NVMEM=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_DMA_DEFAULT_COHERENT=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IOMMU=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OID_REGISTRY=y
CONFIG_PADATA=y
CONFIG_PAGE_OFFSET=0xff60000000000000
CONFIG_PAGE_POOL=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
# CONFIG_PAGE_TABLE_CHECK is not set
CONFIG_PANIC_TIMEOUT=0
CONFIG_PCPU_DEV_REFCNT=y
CONFIG_PGTABLE_LEVELS=5
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_SUN50I_USB3=y
# CONFIG_PHY_SUN6I_MIPI_DPHY is not set
# CONFIG_PHY_SUN9I_USB is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_SUN20I_D1=y
# CONFIG_PINCTRL_SUN4I_A10 is not set
# CONFIG_PINCTRL_SUN50I_A100 is not set
# CONFIG_PINCTRL_SUN50I_A100_R is not set
# CONFIG_PINCTRL_SUN50I_A64 is not set
# CONFIG_PINCTRL_SUN50I_A64_R is not set
# CONFIG_PINCTRL_SUN50I_H5 is not set
# CONFIG_PINCTRL_SUN50I_H6 is not set
# CONFIG_PINCTRL_SUN50I_H616 is not set
# CONFIG_PINCTRL_SUN50I_H616_R is not set
# CONFIG_PINCTRL_SUN50I_H6_R is not set
# CONFIG_PINCTRL_SUN5I is not set
# CONFIG_PINCTRL_SUN6I_A31 is not set
# CONFIG_PINCTRL_SUN6I_A31_R is not set
# CONFIG_PINCTRL_SUN8I_A23 is not set
# CONFIG_PINCTRL_SUN8I_A23_R is not set
# CONFIG_PINCTRL_SUN8I_A33 is not set
# CONFIG_PINCTRL_SUN8I_A83T is not set
# CONFIG_PINCTRL_SUN8I_A83T_R is not set
# CONFIG_PINCTRL_SUN8I_H3 is not set
# CONFIG_PINCTRL_SUN8I_H3_R is not set
# CONFIG_PINCTRL_SUN8I_V3S is not set
# CONFIG_PINCTRL_SUN9I_A80 is not set
# CONFIG_PINCTRL_SUN9I_A80_R is not set
CONFIG_PINCTRL_SUNXI=y
CONFIG_PORTABLE=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
CONFIG_POWER_SUPPLY=y
CONFIG_PPS=y
CONFIG_PREEMPT_NONE_BUILD=y
CONFIG_PRINTK_TIME=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_PWM=y
# CONFIG_PWM_CLK is not set
# CONFIG_PWM_SIFIVE is not set
# CONFIG_PWM_SUN4I is not set
# CONFIG_PWM_SUN8I_V536 is not set
CONFIG_PWM_SYSFS=y
# CONFIG_PWM_XILINX is not set
CONFIG_RATIONAL=y
CONFIG_RCU_TRACE=y
CONFIG_REALTEK_PHY=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_IRQ=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
# CONFIG_REGULATOR_AXP20X is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_SUN20I=y
# CONFIG_RESET_ATTACK_MITIGATION is not set
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_SIMPLE=y
CONFIG_RESET_SUNXI=y
CONFIG_RISCV=y
CONFIG_RISCV_ALTERNATIVE=y
CONFIG_RISCV_ALTERNATIVE_EARLY=y
CONFIG_RISCV_BOOT_SPINWAIT=y
CONFIG_RISCV_DMA_NONCOHERENT=y
CONFIG_RISCV_INTC=y
CONFIG_RISCV_ISA_C=y
CONFIG_RISCV_ISA_SVPBMT=y
CONFIG_RISCV_ISA_ZICBOM=y
CONFIG_RISCV_SBI=y
CONFIG_RISCV_SBI_V01=y
CONFIG_RISCV_TIMER=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_EFI is not set
CONFIG_RTC_DRV_GOLDFISH=y
CONFIG_RTC_DRV_SUN6I=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SCHED_DEBUG=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_DWLIB=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIO=y
CONFIG_SERIO_SERPORT=y
CONFIG_SG_POOL=y
CONFIG_SIFIVE_PLIC=y
CONFIG_SLUB_DEBUG=y
CONFIG_SMP=y
# CONFIG_SND_SUN20I_CODEC is not set
# CONFIG_SND_SUN4I_I2S is not set
# CONFIG_SND_SUN50I_DMIC is not set
CONFIG_SOCK_RX_QUEUE_MAPPING=y
# CONFIG_SOC_MICROCHIP_POLARFIRE is not set
# CONFIG_SOC_SIFIVE is not set
# CONFIG_SOC_STARFIVE is not set
# CONFIG_SOC_VIRT is not set
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
# CONFIG_SPI_SUN4I is not set
CONFIG_SPI_SUN6I=y
CONFIG_SRCU=y
CONFIG_STACKDEPOT=y
CONFIG_STACKTRACE=y
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
CONFIG_SUN20I_D1_CCU=y
CONFIG_SUN20I_D1_R_CCU=y
# CONFIG_SUN4I_EMAC is not set
CONFIG_SUN4I_TIMER=y
CONFIG_SUN50I_IOMMU=y
CONFIG_SUN6I_MSGBOX=y
CONFIG_SUN6I_RTC_CCU=y
CONFIG_SUN8I_DE2_CCU=y
# CONFIG_SUN8I_R_CCU is not set
# CONFIG_SUN8I_THERMAL is not set
CONFIG_SUNXI_CCU=y
# CONFIG_SUNXI_RSB is not set
CONFIG_SUNXI_SRAM=y
CONFIG_SUNXI_WATCHDOG=y
CONFIG_SWIOTLB=y
CONFIG_SWPHY=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
# CONFIG_SYSFB_SIMPLEFB is not set
CONFIG_SYSFS_SYSCALL=y
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TOOLCHAIN_HAS_ZICBOM=y
CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y
CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y
CONFIG_TRACE_CLOCK=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_TUNE_GENERIC=y
# CONFIG_UACCE is not set
CONFIG_UCS2_STRING=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_HID=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_HOST=y
CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB_NET_DRIVERS=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_PHY=y
CONFIG_USB_SUPPORT=y
# CONFIG_USB_UHCI_HCD is not set
CONFIG_USB_XHCI_HCD=y
# CONFIG_USB_XHCI_PLATFORM is not set
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
# CONFIG_VHOST_MENU is not set
# CONFIG_VIRTIO_MENU is not set
CONFIG_VMAP_STACK=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_WATCHDOG_CORE=y
CONFIG_XPS=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA32=y

View File

@ -0,0 +1,5 @@
config D1_SD_BOOT_PARTSIZE
int "Boot (SD Card) filesystem partition size (in MB)"
depends on TARGET_d1
default 32

View File

@ -0,0 +1,94 @@
#
# Copyright (C) 2023 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
FAT32_BLOCK_SIZE=1024
FAT32_BLOCKS=$(shell echo $$(($(CONFIG_D1_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
KERNEL_LOADADDR:=0x40200000
define Build/riscv-sdcard
rm -f $@.boot #$(KDIR_TMP)/$(IMG_PREFIX)-$(PROFILE)-boot.img
mkfs.fat $@.boot -C $(FAT32_BLOCKS)
mcopy -i $@.boot $(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-boot.scr ::boot.scr
mcopy -i $@.boot $(DTS_DIR)/$(DEVICE_DTS).dtb ::dtb
mcopy -i $@.boot $(IMAGE_KERNEL) ::Image
./gen_d1_sdcard_img.sh \
$@ \
$@.boot \
$(IMAGE_ROOTFS) \
$(CONFIG_D1_SD_BOOT_PARTSIZE) \
$(CONFIG_TARGET_ROOTFS_PARTSIZE) \
$(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-u-boot-sunxi-with-spl.bin
endef
define Device/Default
PROFILES := Default
KERNEL_NAME := Image
KERNEL := kernel-bin
IMAGES := sdcard.img.gz
IMAGE/sdcard.img.gz := riscv-sdcard | append-metadata | gzip
endef
define Device/FitImageGzip
KERNEL_SUFFIX := -fit-uImage.itb
KERNEL = kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb
KERNEL_NAME := Image
endef
define Device/FitImage
KERNEL_SUFFIX := -fit-uImage.itb
KERNEL = kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb
KERNEL_NAME := Image
endef
define Device/dongshan_nezha_stu
$(call Device/Default)
DEVICE_VENDOR := Dongshan
DEVICE_MODEL := Nezha STU devkit
DEVICE_DTS := allwinner/sun20i-d1-dongshan-nezha-stu
UBOOT := dongshan_nezha_stu
endef
TARGET_DEVICES += dongshan_nezha_stu
define Device/lichee_rv_dock
$(call Device/Default)
DEVICE_VENDOR := Sipeed
DEVICE_MODEL := LicheePi RV (dock)
DEVICE_DTS := allwinner/sun20i-d1-lichee-rv-dock
DEVICE_PACKAGES += kmod-rtl8723bs
UBOOT := lichee_rv_dock
endef
TARGET_DEVICES += lichee_rv_dock
define Device/mangopi_mq_pro
$(call Device/Default)
DEVICE_VENDOR := MangoPi
DEVICE_MODEL := MQ Pro
DEVICE_DTS := allwinner/sun20i-d1-mangopi-mq-pro
DEVICE_PACKAGES += kmod-rtl8723bs
UBOOT := mangopi_mq_pro
endef
TARGET_DEVICES += mangopi_mq_pro
define Device/nezha
$(call Device/Default)
DEVICE_VENDOR := Nezha
DEVICE_MODEL := D1
DEVICE_DTS := allwinner/sun20i-d1-nezha
UBOOT := nezha
endef
TARGET_DEVICES += nezha
define Image/Build
$(call Image/Build/$(1),$(1))
endef
$(eval $(call BuildImage))

View File

@ -0,0 +1,33 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2013 OpenWrt.org
set -ex
[ $# -eq 6 ] || {
echo "SYNTAX: $0 <file> <bootfs image> <rootfs image> <bootfs size> <rootfs size> <u-boot image>"
exit 1
}
OUTPUT="$1"
BOOTFS="$2"
ROOTFS="$3"
BOOTFSSIZE="$4"
ROOTFSSIZE="$5"
UBOOT="$6"
ROOTFSPTOFFSET=$(($BOOTFSSIZE + 20 + 1))
head=4
sect=63
set $(ptgen -o $OUTPUT -h $head -s $sect -l 1024 -t c -p ${BOOTFSSIZE}M@20M -t 83 -p ${ROOTFSSIZE}M@${ROOTFSPTOFFSET}M)
BOOTOFFSET="$(($1 / 512))"
BOOTSIZE="$(($2 / 512))"
ROOTFSOFFSET="$(($3 / 512))"
ROOTFSSIZE="$(($4 / 512))"
dd bs=512 if="$UBOOT" of="$OUTPUT" seek=256 conv=notrunc
dd bs=512 if="$BOOTFS" of="$OUTPUT" seek="$BOOTOFFSET" conv=notrunc
dd bs=512 if="$ROOTFS" of="$OUTPUT" seek="$ROOTFSOFFSET" conv=notrunc

View File

@ -0,0 +1,32 @@
From e663d510ae6a81694a8e9e1ce07bb80dd6b77558 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 24 Jul 2022 17:12:07 -0500
Subject: [PATCH 001/117] dt-bindings: net: bluetooth: realtek: Add RTL8723DS
RTL8723DS is another version of the RTL8723 WiFi + Bluetooth chip. It is
already supported by the hci_uart/btrtl driver. Document the compatible.
Series-to: Marcel Holtmann <marcel@holtmann.org>
Series-to: Johan Hedberg <johan.hedberg@gmail.com>
Series-to: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Series-to: David S. Miller <davem@davemloft.net>
Series-to: Eric Dumazet <edumazet@google.com>
Series-to: Jakub Kicinski <kuba@kernel.org>
Series-to: Paolo Abeni <pabeni@redhat.com>
Series-cc: linux-bluetooth@vger.kernel.org
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
Documentation/devicetree/bindings/net/realtek-bluetooth.yaml | 1 +
1 file changed, 1 insertion(+)
--- a/Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
+++ b/Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
@@ -20,6 +20,7 @@ properties:
enum:
- realtek,rtl8723bs-bt
- realtek,rtl8723cs-bt
+ - realtek,rtl8723ds-bt
- realtek,rtl8822cs-bt
device-wake-gpios:

View File

@ -0,0 +1,51 @@
From 74492b9ecd874496578693d9985649665b560308 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 7 Aug 2022 20:08:49 -0500
Subject: [PATCH 002/117] clk: sunxi-ng: mp: Avoid computing the rate twice
ccu_mp_find_best() already computes a best_rate at the same time as the
best m and p factors. Return it so the caller does not need to duplicate
the division.
Series-to: Chen-Yu Tsai <wens@csie.org>
Series-to: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/clk/sunxi-ng/ccu_mp.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -10,9 +10,9 @@
#include "ccu_gate.h"
#include "ccu_mp.h"
-static void ccu_mp_find_best(unsigned long parent, unsigned long rate,
- unsigned int max_m, unsigned int max_p,
- unsigned int *m, unsigned int *p)
+static unsigned long ccu_mp_find_best(unsigned long parent, unsigned long rate,
+ unsigned int max_m, unsigned int max_p,
+ unsigned int *m, unsigned int *p)
{
unsigned long best_rate = 0;
unsigned int best_m = 0, best_p = 0;
@@ -35,6 +35,8 @@ static void ccu_mp_find_best(unsigned lo
*m = best_m;
*p = best_p;
+
+ return best_rate;
}
static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
@@ -109,8 +111,7 @@ static unsigned long ccu_mp_round_rate(s
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
if (!clk_hw_can_set_rate_parent(&cmp->common.hw)) {
- ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
- rate = *parent_rate / p / m;
+ rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
} else {
rate = ccu_mp_find_best_with_parent_adj(hw, parent_rate, rate,
max_m, max_p);

View File

@ -0,0 +1,22 @@
From 7185f7b424dfd9082bf0859a60b98a2dbd784ed6 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Mon, 5 Sep 2022 16:45:44 -0500
Subject: [PATCH 003/117] dt-bindings: net: sun8i-emac: Add phy-supply property
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml | 3 +++
1 file changed, 3 insertions(+)
--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
+++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
@@ -40,6 +40,9 @@ properties:
clock-names:
const: stmmaceth
+ phy-supply:
+ description: PHY regulator
+
syscon:
$ref: /schemas/types.yaml#/definitions/phandle
description:

View File

@ -0,0 +1,32 @@
From d20bb97fac77e4d88424043627c769427fc0d35e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Mon, 5 Sep 2022 16:46:34 -0500
Subject: [PATCH 004/117] dt-bindings: net: sun8i-emac: Add properties from
dwmac binding
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml | 5 +++++
1 file changed, 5 insertions(+)
--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
+++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
@@ -40,6 +40,9 @@ properties:
clock-names:
const: stmmaceth
+ resets: true
+ reset-names: true
+
phy-supply:
description: PHY regulator
@@ -49,6 +52,8 @@ properties:
Phandle to the device containing the EMAC or GMAC clock
register
+ mdio: true
+
required:
- compatible
- reg

View File

@ -0,0 +1,28 @@
From c99d1e681dc460892004054a314fa7f929f43490 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 13 Aug 2022 10:45:59 -0500
Subject: [PATCH 005/117] dt-bindings: display: sun8i-a83t-dw-hdmi: Remove
#phy-cells
This device is not a PHY, and none of the nodes using this schema
contain a #phy-cells property. Likely this was a copy/paste error
introduced during the YAML conversion.
Fixes: f5a98bfe7b37 ("dt-bindings: display: Convert Allwinner display pipeline to schemas")
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml | 3 ---
1 file changed, 3 deletions(-)
--- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml
@@ -20,9 +20,6 @@ maintainers:
- Maxime Ripard <mripard@kernel.org>
properties:
- "#phy-cells":
- const: 0
-
compatible:
oneOf:
- const: allwinner,sun8i-a83t-dw-hdmi

View File

@ -0,0 +1,34 @@
From e214b79d45cccdd0cfe839e54da2b3c82b6c6be4 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 31 Mar 2022 23:43:15 -0500
Subject: [PATCH 006/117] dt-bindings: display: Add D1 HDMI compatibles
Allwinner D1 contains a DesignWare HDMI controller with some changes in
platform integration, and a new HDMI PHY. Add their compatibles.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml | 1 +
.../bindings/display/allwinner,sun8i-a83t-hdmi-phy.yaml | 1 +
2 files changed, 2 insertions(+)
--- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml
@@ -29,6 +29,7 @@ properties:
- enum:
- allwinner,sun8i-h3-dw-hdmi
- allwinner,sun8i-r40-dw-hdmi
+ - allwinner,sun20i-d1-dw-hdmi
- allwinner,sun50i-a64-dw-hdmi
- const: allwinner,sun8i-a83t-dw-hdmi
--- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-hdmi-phy.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-hdmi-phy.yaml
@@ -19,6 +19,7 @@ properties:
- allwinner,sun8i-a83t-hdmi-phy
- allwinner,sun8i-h3-hdmi-phy
- allwinner,sun8i-r40-hdmi-phy
+ - allwinner,sun20i-d1-hdmi-phy
- allwinner,sun50i-a64-hdmi-phy
- allwinner,sun50i-h6-hdmi-phy

View File

@ -0,0 +1,52 @@
From 75dc74ecc1bf5e270659c6c78877053b50e6ae19 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 30 Mar 2022 21:24:21 -0500
Subject: [PATCH 007/117] drm/sun4i: Add support for D1 HDMI
D1's HDMI controller contains some platform integration changes.
It now has no external TMDS clock. The controller also supports HDCP
without an external clock or reset.
While the maximum HDMI frequency is not explicity stated, the BSP PHY
driver provides PLL configurations only up to 297 MHz, so use that as
the max frequency.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -133,7 +133,7 @@ static int sun8i_dw_hdmi_bind(struct dev
return dev_err_probe(dev, PTR_ERR(hdmi->rst_ctrl),
"Could not get ctrl reset control\n");
- hdmi->clk_tmds = devm_clk_get(dev, "tmds");
+ hdmi->clk_tmds = devm_clk_get_optional(dev, "tmds");
if (IS_ERR(hdmi->clk_tmds))
return dev_err_probe(dev, PTR_ERR(hdmi->clk_tmds),
"Couldn't get the tmds clock\n");
@@ -246,6 +246,11 @@ static const struct sun8i_dw_hdmi_quirks
.mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
};
+static const struct sun8i_dw_hdmi_quirks sun20i_d1_quirks = {
+ .mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
+ .use_drm_infoframe = true,
+};
+
static const struct sun8i_dw_hdmi_quirks sun50i_h6_quirks = {
.mode_valid = sun8i_dw_hdmi_mode_valid_h6,
.use_drm_infoframe = true,
@@ -257,6 +262,10 @@ static const struct of_device_id sun8i_d
.data = &sun8i_a83t_quirks,
},
{
+ .compatible = "allwinner,sun20i-d1-dw-hdmi",
+ .data = &sun20i_d1_quirks,
+ },
+ {
.compatible = "allwinner,sun50i-h6-dw-hdmi",
.data = &sun50i_h6_quirks,
},

View File

@ -0,0 +1,251 @@
From 11f9765a8e6723bcb7243f6dbc48e6deaf17b097 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 3 Apr 2022 15:15:41 -0500
Subject: [PATCH 008/117] drm/sun4i: sun8i-hdmi-phy: Add support for D1 PHY
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 169 +++++++++++++++++++++++++
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 32 +++++
2 files changed, 201 insertions(+)
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -145,6 +145,175 @@
#define SUN8I_HDMI_PHY_CEC_REG 0x003c
+#define SUN20I_HDMI_PHY_CTL0_REG 0x0040
+#define SUN20I_HDMI_PHY_CTL0_PLL_LOCK_MODE_MAN BIT(31)
+#define SUN20I_HDMI_PHY_CTL0_PLL_LOCK_MODE BIT(30)
+#define SUN20I_HDMI_PHY_CTL0_FIFO_WORKC_EN BIT(29)
+#define SUN20I_HDMI_PHY_CTL0_FIFO_AUTOSYNC_DIS BIT(28)
+#define SUN20I_HDMI_PHY_CTL0_ENTX GENMASK(27, 24)
+#define SUN20I_HDMI_PHY_CTL0_ENBI GENMASK(23, 20)
+#define SUN20I_HDMI_PHY_CTL0_ENLDO BIT(18)
+#define SUN20I_HDMI_PHY_CTL0_ENLDO_FS BIT(17)
+#define SUN20I_HDMI_PHY_CTL0_ENCK BIT(16)
+#define SUN20I_HDMI_PHY_CTL0_REG_PLR GENMASK(15, 12)
+#define SUN20I_HDMI_PHY_CTL0_REG_DEN GENMASK(11, 8)
+#define SUN20I_HDMI_PHY_CTL0_REG_CSMPS GENMASK(7, 6)
+#define SUN20I_HDMI_PHY_CTL0_REG_CK_TEST_SEL BIT(5)
+#define SUN20I_HDMI_PHY_CTL0_REG_CK_SEL BIT(4)
+#define SUN20I_HDMI_PHY_CTL0_HPD_EN BIT(2)
+#define SUN20I_HDMI_PHY_CTL0_SCL_EN BIT(1)
+#define SUN20I_HDMI_PHY_CTL0_SDA_EN BIT(0)
+
+#define SUN20I_HDMI_PHY_CTL1_REG 0x0044
+#define SUN20I_HDMI_PHY_CTL1_RXSENSE_MODE_MAN BIT(31)
+#define SUN20I_HDMI_PHY_CTL1_RXSENSE_MODE BIT(30)
+#define SUN20I_HDMI_PHY_CTL1_RES_S GENMASK(29, 28)
+#define SUN20I_HDMI_PHY_CTL1_RES_SCKTMDS BIT(27)
+#define SUN20I_HDMI_PHY_CTL1_REG_SWI BIT(26)
+#define SUN20I_HDMI_PHY_CTL1_REG_SVR GENMASK(25, 24)
+#define SUN20I_HDMI_PHY_CTL1_REG_BST2 GENMASK(21, 20)
+#define SUN20I_HDMI_PHY_CTL1_REG_BST1 GENMASK(19, 18)
+#define SUN20I_HDMI_PHY_CTL1_REG_BST0 GENMASK(17, 16)
+#define SUN20I_HDMI_PHY_CTL1_REG_SP2_3 GENMASK(15, 12)
+#define SUN20I_HDMI_PHY_CTL1_REG_SP2_2 GENMASK(11, 8)
+#define SUN20I_HDMI_PHY_CTL1_REG_SP2_1 GENMASK(7, 4)
+#define SUN20I_HDMI_PHY_CTL1_REG_SP2_0 GENMASK(3, 0)
+
+#define SUN20I_HDMI_PHY_CTL2_REG 0x0048
+#define SUN20I_HDMI_PHY_CTL2_HPDO_MODE_MAN BIT(31)
+#define SUN20I_HDMI_PHY_CTL2_HPDO_MODE BIT(30)
+#define SUN20I_HDMI_PHY_CTL2_REG_RESDI GENMASK(29, 24)
+#define SUN20I_HDMI_PHY_CTL2_REG_SP1_3 GENMASK(23, 19)
+#define SUN20I_HDMI_PHY_CTL2_REG_SP1_2 GENMASK(18, 14)
+#define SUN20I_HDMI_PHY_CTL2_REG_SP1_1 GENMASK(13, 9)
+#define SUN20I_HDMI_PHY_CTL2_REG_SP1_0 GENMASK(8, 4)
+#define SUN20I_HDMI_PHY_CTL2_REG_P2OPT GENMASK(3, 0)
+
+#define SUN20I_HDMI_PHY_CTL3_REG 0x004c
+#define SUN20I_HDMI_PHY_CTL3_REG_P2_3 GENMASK(31, 28)
+#define SUN20I_HDMI_PHY_CTL3_REG_P2_2 GENMASK(27, 24)
+#define SUN20I_HDMI_PHY_CTL3_REG_P2_1 GENMASK(23, 20)
+#define SUN20I_HDMI_PHY_CTL3_REG_P2_0 GENMASK(19, 16)
+#define SUN20I_HDMI_PHY_CTL3_REG_MC3 GENMASK(15, 12)
+#define SUN20I_HDMI_PHY_CTL3_REG_MC2 GENMASK(11, 8)
+#define SUN20I_HDMI_PHY_CTL3_REG_MC1 GENMASK(7, 4)
+#define SUN20I_HDMI_PHY_CTL3_REG_MC0 GENMASK(3, 0)
+
+#define SUN20I_HDMI_PHY_CTL4_REG 0x0050
+#define SUN20I_HDMI_PHY_CTL4_REG_SLV GENMASK(31, 29)
+#define SUN20I_HDMI_PHY_CTL4_REG_P1_3 GENMASK(28, 24)
+#define SUN20I_HDMI_PHY_CTL4_REG_P1_2 GENMASK(20, 16)
+#define SUN20I_HDMI_PHY_CTL4_REG_P1_1 GENMASK(12, 8)
+#define SUN20I_HDMI_PHY_CTL4_REG_P1_0 GENMASK(4, 0)
+
+#define SUN20I_HDMI_PHY_CTL5_REG 0x0054
+#define SUN20I_HDMI_PHY_CTL5_REG_P1OPT GENMASK(19, 16)
+#define SUN20I_HDMI_PHY_CTL5_REG_CKPDLYOPT BIT(12)
+#define SUN20I_HDMI_PHY_CTL5_REG_CALSW BIT(11)
+#define SUN20I_HDMI_PHY_CTL5_ENRESCK BIT(10)
+#define SUN20I_HDMI_PHY_CTL5_ENRES BIT(9)
+#define SUN20I_HDMI_PHY_CTL5_ENRCAL BIT(8)
+#define SUN20I_HDMI_PHY_CTL5_ENP2S GENMASK(7, 4)
+#define SUN20I_HDMI_PHY_CTL5_ENIB BIT(1)
+#define SUN20I_HDMI_PHY_CTL5_ENCALOG BIT(0)
+
+#define SUN20I_HDMI_PLL_CTL0_REG 0x0058
+#define SUN20I_HDMI_PLL_CTL0_CKO_SEL GENMASK(31, 30)
+#define SUN20I_HDMI_PLL_CTL0_BYPASS_PPLL BIT(29)
+#define SUN20I_HDMI_PLL_CTL0_ENVBS BIT(28)
+#define SUN20I_HDMI_PLL_CTL0_SLV GENMASK(26, 24)
+#define SUN20I_HDMI_PLL_CTL0_BCR BIT(23)
+#define SUN20I_HDMI_PLL_CTL0_BYPASS_CLRDPTH BIT(22)
+#define SUN20I_HDMI_PLL_CTL0_CLR_DPTH GENMASK(21, 20)
+#define SUN20I_HDMI_PLL_CTL0_CUTFB BIT(18)
+#define SUN20I_HDMI_PLL_CTL0_DIV2_CKBIT BIT(17)
+#define SUN20I_HDMI_PLL_CTL0_DIV2_CKTMDS BIT(16)
+#define SUN20I_HDMI_PLL_CTL0_DIV_PRE GENMASK(15, 12)
+#define SUN20I_HDMI_PLL_CTL0_DIVX1 BIT(10)
+#define SUN20I_HDMI_PLL_CTL0_SDRVEN BIT(9)
+#define SUN20I_HDMI_PLL_CTL0_VCORANGE BIT(8)
+#define SUN20I_HDMI_PLL_CTL0_N_CNTRL GENMASK(7, 6)
+#define SUN20I_HDMI_PLL_CTL0_GMP_CNTRL GENMASK(5, 4)
+#define SUN20I_HDMI_PLL_CTL0_PROP_CNTRL GENMASK(2, 0)
+
+#define SUN20I_HDMI_PLL_CTL1_REG 0x005c
+#define SUN20I_HDMI_PLL_CTL1_CTRL_MODLE_CLKSRC BIT(31)
+#define SUN20I_HDMI_PLL_CTL1_PCNT_N GENMASK(27, 20)
+#define SUN20I_HDMI_PLL_CTL1_PCNT_EN BIT(19)
+#define SUN20I_HDMI_PLL_CTL1_SDM_EN BIT(18)
+#define SUN20I_HDMI_PLL_CTL1_PIXEL_REP GENMASK(17, 16)
+#define SUN20I_HDMI_PLL_CTL1_PWRON BIT(12)
+#define SUN20I_HDMI_PLL_CTL1_RESET BIT(11)
+#define SUN20I_HDMI_PLL_CTL1_SCKREF BIT(10)
+#define SUN20I_HDMI_PLL_CTL1_SCKFB BIT(9)
+#define SUN20I_HDMI_PLL_CTL1_DRV_ANA BIT(8)
+#define SUN20I_HDMI_PLL_CTL1_FAST_TECH BIT(7)
+#define SUN20I_HDMI_PLL_CTL1_GEAR_SHIFT BIT(6)
+#define SUN20I_HDMI_PLL_CTL1_REF_CNTRL GENMASK(5, 4)
+#define SUN20I_HDMI_PLL_CTL1_INT_CNTRL GENMASK(2, 0)
+
+#define SUN20I_HDMI_AFIFO_CFG_REG 0x0060
+#define SUN20I_HDMI_AFIFO_CFG_AFIFO_ERROR BIT(0)
+#define SUN20I_HDMI_AFIFO_CFG_AFIFO_ERROR_DET BIT(1)
+
+#define SUN20I_HDMI_MODULATOR_CFG0_REG 0x0064
+#define SUN20I_HDMI_MODULATOR_CFG1_REG 0x0068
+
+#define SUN20I_HDMI_INDEB_CTRL_REG 0x006c
+#define SUN20I_HDMI_INDEB_CTRL_HPDI_DEBUGMODE BIT(29)
+#define SUN20I_HDMI_INDEB_CTRL_HPDI_DEBUG BIT(28)
+#define SUN20I_HDMI_INDEB_CTRL_SDAI_DEBUGMODE BIT(25)
+#define SUN20I_HDMI_INDEB_CTRL_SDAI_DEBUG BIT(24)
+#define SUN20I_HDMI_INDEB_CTRL_SCLI_DEBUGMODE BIT(21)
+#define SUN20I_HDMI_INDEB_CTRL_SCLI_DEBUG BIT(20)
+#define SUN20I_HDMI_INDEB_CTRL_CECI_DEBUGMODE BIT(17)
+#define SUN20I_HDMI_INDEB_CTRL_CECI_DEBUG BIT(16)
+#define SUN20I_HDMI_INDEB_CTRL_TXDATA_DEBUGMODE GENMASK(1, 0)
+
+#define SUN20I_HDMI_INDBG_TXD0_REG 0x0070
+#define SUN20I_HDMI_INDBG_TXD1_REG 0x0074
+#define SUN20I_HDMI_INDBG_TXD2_REG 0x0078
+#define SUN20I_HDMI_INDBG_TXD3_REG 0x007c
+
+#define SUN20I_HDMI_PLL_STS_REG 0x0080
+#define SUN20I_HDMI_PLL_STS_PHY_CDETPCK_STATUS BIT(31)
+#define SUN20I_HDMI_PLL_STS_PHY_CDETP_STATUS GENMASK(30, 28)
+#define SUN20I_HDMI_PLL_STS_PHY_CDETNCK_STATUS BIT(27)
+#define SUN20I_HDMI_PLL_STS_PHY_CDETN_STATUS GENMASK(26, 24)
+#define SUN20I_HDMI_PLL_STS_PHY_HPDO_STATUS BIT(23)
+#define SUN20I_HDMI_PLL_STS_PHY_SCLO_STATUS BIT(22)
+#define SUN20I_HDMI_PLL_STS_PHY_SDAO_STATUS BIT(21)
+#define SUN20I_HDMI_PLL_STS_PHY_CECO_STATUS BIT(20)
+#define SUN20I_HDMI_PLL_STS_PHY_COUT2D_STATUS BIT(17)
+#define SUN20I_HDMI_PLL_STS_PHY_RCALEND2D_STS BIT(16)
+#define SUN20I_HDMI_PLL_STS_PHY_RESDO2D_STATUS GENMASK(13, 8)
+#define SUN20I_HDMI_PLL_STS_PLL_LOCK_STATUS BIT(4)
+#define SUN20I_HDMI_PLL_STS_RXSENSE_DLY_STATUS BIT(1)
+#define SUN20I_HDMI_PLL_STS_TX_READY_DLY_STATUS BIT(0)
+
+#define SUN20I_HDMI_PRBS_CTL_REG 0x0084
+#define SUN20I_HDMI_PRBS_SEED_GEN_REG 0x0088
+#define SUN20I_HDMI_PRBS_SEED_CHK_REG 0x008c
+#define SUN20I_HDMI_PRBS_SEED_NUM_REG 0x0090
+#define SUN20I_HDMI_PRBS_CYCLE_NUM_REG 0x0094
+
+#define SUN20I_HDMI_PLL_ODLY_REG 0x0098
+#define SUN20I_HDMI_PLL_ODLY_RXSENSE_DLY_RESET BIT(31)
+#define SUN20I_HDMI_PLL_ODLY_RXSENSE_DLY_COUNT GENMASK(30, 16)
+#define SUN20I_HDMI_PLL_ODLY_TX_READY_DLY_RESET BIT(15)
+#define SUN20I_HDMI_PLL_ODLY_TX_READY_DLY_COUNT GENMASK(14, 0)
+
+#define SUN20I_HDMI_PHY_CTL6_REG 0x009c
+#define SUN20I_HDMI_PHY_CTL6_SWITCH_CLKCH_DATA BIT(31)
+#define SUN20I_HDMI_PHY_CTL6_EN_CKDAT BIT(30)
+#define SUN20I_HDMI_PHY_CTL6_CLK_GREATE2_340M GENMASK(29, 20)
+#define SUN20I_HDMI_PHY_CTL6_CLK_GREATE1_340M GENMASK(19, 10)
+#define SUN20I_HDMI_PHY_CTL6_CLK_GREATE0_340M GENMASK(9, 0)
+
+#define SUN20I_HDMI_PHY_CTL7_REG 0x00a0
+#define SUN20I_HDMI_PHY_CTL7_CLK_LOW_340M GENMASK(21, 12)
+#define SUN20I_HDMI_PHY_CTL7_CLK_GREATE3_340M GENMASK(9, 0)
+
struct sun8i_hdmi_phy;
struct sun8i_hdmi_phy_variant {
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -398,6 +398,28 @@ static const struct dw_hdmi_phy_ops sun8
.setup_hpd = dw_hdmi_phy_setup_hpd,
};
+static int sun20i_d1_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
+ const struct drm_display_info *display,
+ const struct drm_display_mode *mode)
+{
+ struct sun8i_hdmi_phy *phy = data;
+
+ return 0;
+}
+
+static void sun20i_d1_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
+{
+ struct sun8i_hdmi_phy *phy = data;
+}
+
+static const struct dw_hdmi_phy_ops sun20i_d1_hdmi_phy_ops = {
+ .init = sun20i_d1_hdmi_phy_config,
+ .disable = sun20i_d1_hdmi_phy_disable,
+ .read_hpd = dw_hdmi_phy_read_hpd,
+ .update_hpd = dw_hdmi_phy_update_hpd,
+ .setup_hpd = dw_hdmi_phy_setup_hpd,
+};
+
static void sun8i_hdmi_phy_unlock(struct sun8i_hdmi_phy *phy)
{
/* enable read access to HDMI controller */
@@ -576,6 +598,7 @@ void sun8i_hdmi_phy_set_ops(struct sun8i
const struct sun8i_hdmi_phy_variant *variant = phy->variant;
if (variant->phy_ops) {
+ plat_data->phy_force_vendor = true;
plat_data->phy_ops = variant->phy_ops;
plat_data->phy_name = "sun8i_dw_hdmi_phy";
plat_data->phy_data = phy;
@@ -612,6 +635,11 @@ static const struct sun8i_hdmi_phy_varia
.phy_init = &sun8i_hdmi_phy_init_h3,
};
+static const struct sun8i_hdmi_phy_variant sun20i_d1_hdmi_phy = {
+ .phy_ops = &sun20i_d1_hdmi_phy_ops,
+ .phy_init = &sun50i_hdmi_phy_init_h6,
+};
+
static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
.has_phy_clk = true,
.phy_ops = &sun8i_h3_hdmi_phy_ops,
@@ -639,6 +667,10 @@ static const struct of_device_id sun8i_h
.data = &sun8i_r40_hdmi_phy,
},
{
+ .compatible = "allwinner,sun20i-d1-hdmi-phy",
+ .data = &sun20i_d1_hdmi_phy,
+ },
+ {
.compatible = "allwinner,sun50i-a64-hdmi-phy",
.data = &sun50i_a64_hdmi_phy,
},

View File

@ -0,0 +1,621 @@
From 7ea7d4abfd537230da58533803a2d0257addace8 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 30 Mar 2022 00:46:07 -0500
Subject: [PATCH 009/117] drm/sun4i: Copy in BSP code for D1 HDMI PHY
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/aw_phy.h | 411 +++++++++++++++++++++++++
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 1 +
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 156 ++++++++++
3 files changed, 568 insertions(+)
create mode 100644 drivers/gpu/drm/sun4i/aw_phy.h
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/aw_phy.h
@@ -0,0 +1,411 @@
+/*
+ * Allwinner SoCs hdmi2.0 driver.
+ *
+ * Copyright (C) 2016 Allwinner.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef AW_PHY_H_
+#define AW_PHY_H_
+
+#define AW_PHY_TIMEOUT 1000
+#define LOCK_TIMEOUT 100
+
+/* allwinner phy register offset */
+#define HDMI_PHY_CTL0 0x40
+#define HDMI_PHY_CTL1 0x44
+#define HDMI_PHY_CTL2 0x48
+#define HDMI_PHY_CTL3 0x4C
+#define HDMI_PHY_CTL4 0x50
+#define HDMI_PHY_CTL5 0x54
+#define HDMI_PLL_CTL0 0x58
+#define HDMI_PLL_CTL1 0x5C
+#define HDMI_AFIFO_CFG 0x60
+#define HDMI_MODULATOR_CFG0 0x64
+#define HDMI_MODULATOR_CFG1 0x68
+#define HDMI_PHY_INDEB_CTRL 0x6C
+#define HDMI_PHY_INDBG_TXD0 0x70
+#define HDMI_PHY_INDBG_TXD1 0x74
+#define HDMI_PHY_INDBG_TXD2 0x78
+#define HDMI_PHY_INDBG_TXD3 0x7C
+#define HDMI_PHY_PLL_STS 0x80
+#define HDMI_PRBS_CTL 0x84
+#define HDMI_PRBS_SEED_GEN 0x88
+#define HDMI_PRBS_SEED_CHK 0x8C
+#define HDMI_PRBS_SEED_NUM 0x90
+#define HDMI_PRBS_CYCLE_NUM 0x94
+#define HDMI_PHY_PLL_ODLY_CFG 0x98
+#define HDMI_PHY_CTL6 0x9C
+#define HDMI_PHY_CTL7 0xA0
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 sda_en :1; // Default: 0;
+ u32 scl_en :1; // Default: 0;
+ u32 hpd_en :1; // Default: 0;
+ u32 res0 :1; // Default: 0;
+ u32 reg_ck_sel :1; // Default: 1;
+ u32 reg_ck_test_sel :1; // Default: 1;
+ u32 reg_csmps :2; // Default: 0;
+ u32 reg_den :4; // Default: F;
+ u32 reg_plr :4; // Default: 0;
+ u32 enck :1; // Default: 1;
+ u32 enldo_fs :1; // Default: 1;
+ u32 enldo :1; // Default: 1;
+ u32 res1 :1; // Default: 1;
+ u32 enbi :4; // Default: F;
+ u32 entx :4; // Default: F;
+ u32 async_fifo_autosync_disable :1; // Default: 0;
+ u32 async_fifo_workc_enable :1; // Default: 1;
+ u32 phy_pll_lock_mode :1; // Default: 1;
+ u32 phy_pll_lock_mode_man :1; // Default: 1;
+ } bits;
+} HDMI_PHY_CTL0_t; //=========================== 0x0040
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 reg_sp2_0 : 4 ; // Default: 0;
+ u32 reg_sp2_1 : 4 ; // Default: 0;
+ u32 reg_sp2_2 : 4 ; // Default: 0;
+ u32 reg_sp2_3 : 4 ; // Default: 0;
+ u32 reg_bst0 : 2 ; // Default: 3;
+ u32 reg_bst1 : 2 ; // Default: 3;
+ u32 reg_bst2 : 2 ; // Default: 3;
+ u32 res0 : 2 ; // Default: 0;
+ u32 reg_svr : 2 ; // Default: 2;
+ u32 reg_swi : 1 ; // Default: 0;
+ u32 res_scktmds : 1 ; // Default: 0;
+ u32 res_res_s : 2 ; // Default: 3;
+ u32 phy_rxsense_mode : 1 ; // Default: 0;
+ u32 res_rxsense_mode_man : 1 ; // Default: 0;
+ } bits;
+} HDMI_PHY_CTL1_t; //===================================================== 0x0044
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 reg_p2opt : 4 ; // Default: 0;
+ u32 reg_sp1_0 : 5 ; // Default: 0;
+ u32 reg_sp1_1 : 5 ; // Default: 0;
+ u32 reg_sp1_2 : 5 ; // Default: 0;
+ u32 reg_sp1_3 : 5 ; // Default: 0;
+ u32 reg_resdi : 6 ; // Default: 18;
+ u32 phy_hpdo_mode : 1 ; // Default: 0;
+ u32 phy_hpdo_mode_man : 1 ; // Default: 0;
+ } bits;
+} HDMI_PHY_CTL2_t; //===================================================== 0x0048
+
+
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 reg_mc0 : 4 ; // Default: F;
+ u32 reg_mc1 : 4 ; // Default: F;
+ u32 reg_mc2 : 4 ; // Default: F;
+ u32 reg_mc3 : 4 ; // Default: F;
+ u32 reg_p2_0 : 4 ; // Default: F;
+ u32 reg_p2_1 : 4 ; // Default: F;
+ u32 reg_p2_2 : 4 ; // Default: F;
+ u32 reg_p2_3 : 4 ; // Default: F;
+ } bits;
+} HDMI_PHY_CTL3_t; //===================================================== 0x004C
+
+
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 reg_p1_0 : 5 ; // Default: 0x10;
+ u32 res0 : 3 ; // Default: 0;
+ u32 reg_p1_1 : 5 ; // Default: 0x10;
+ u32 res1 : 3 ; // Default: 0;
+ u32 reg_p1_2 : 5 ; // Default: 0x10;
+ u32 res2 : 3 ; // Default: 0;
+ u32 reg_p1_3 : 5 ; // Default: 0x10;
+ u32 reg_slv : 3 ; // Default: 0;
+ } bits;
+} HDMI_PHY_CTL4_t; //===================================================== 0x0050
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 encalog : 1 ; // Default: 0x1;
+ u32 enib : 1 ; // Default: 0x1;
+ u32 res0 : 2 ; // Default: 0;
+ u32 enp2s : 4 ; // Default: 0xF;
+ u32 enrcal : 1 ; // Default: 0x1;
+ u32 enres : 1 ; // Default: 1;
+ u32 enresck : 1 ; // Default: 1;
+ u32 reg_calsw : 1 ; // Default: 0;
+ u32 reg_ckpdlyopt : 1 ; // Default: 0;
+ u32 res1 : 3 ; // Default: 0;
+ u32 reg_p1opt : 4 ; // Default: 0;
+ u32 res2 : 12 ; // Default: 0;
+ } bits;
+} HDMI_PHY_CTL5_t; //===================================================== 0x0054
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 prop_cntrl : 3 ; // Default: 0x7;
+ u32 res0 : 1 ; // Default: 0;
+ u32 gmp_cntrl : 2 ; // Default: 1;
+ u32 n_cntrl : 2 ; // Default: 0;
+ u32 vcorange : 1 ; // Default: 0;
+ u32 sdrven : 1 ; // Default: 0;
+ u32 divx1 : 1 ; // Default: 0;
+ u32 res1 : 1 ; // Default: 0;
+ u32 div_pre : 4 ; // Default: 0;
+ u32 div2_cktmds : 1 ; // Default: 1;
+ u32 div2_ckbit : 1 ; // Default: 1;
+ u32 cutfb : 1 ; // Default: 0;
+ u32 res2 : 1 ; // Default: 0;
+ u32 clr_dpth : 2 ; // Default: 0;
+ u32 bypass_clrdpth : 1 ; // Default: 0;
+ u32 bcr : 1 ; // Default: 0;
+ u32 slv : 3 ; // Default: 4;
+ u32 res3 : 1 ; // Default: 0;
+ u32 envbs : 1 ; // Default: 0;
+ u32 bypass_ppll : 1 ; // Default: 0;
+ u32 cko_sel : 2 ; // Default: 0;
+ } bits;
+} HDMI_PLL_CTL0_t; //===================================================== 0x0058
+
+
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 int_cntrl : 3 ; // Default: 0x0;
+ u32 res0 : 1 ; // Default: 0;
+ u32 ref_cntrl : 2 ; // Default: 3;
+ u32 gear_shift : 1 ; // Default: 0;
+ u32 fast_tech : 1 ; // Default: 0;
+ u32 drv_ana : 1 ; // Default: 1;
+ u32 sckfb : 1 ; // Default: 0;
+ u32 sckref : 1 ; // Default: 0;
+ u32 reset : 1 ; // Default: 0;
+ u32 pwron : 1 ; // Default: 0;
+ u32 res1 : 3 ; // Default: 0;
+ u32 pixel_rep : 2 ; // Default: 0;
+ u32 sdm_en : 1 ; // Default: 0;
+ u32 pcnt_en : 1 ; // Default: 0;
+ u32 pcnt_n : 8 ; // Default: 0xE;
+ u32 res2 : 3 ; // Default: 0;
+ u32 ctrl_modle_clksrc : 1 ; // Default: 0;
+ } bits;
+} HDMI_PLL_CTL1_t; //===================================================== 0x005C
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 hdmi_afifo_error : 1 ; // Default: 0x0;
+ u32 hdmi_afifo_error_det : 1 ; // Default: 0x0;
+ u32 res0 : 30 ; // Default: 0;
+ } bits;
+} HDMI_AFIFO_CFG_t; //===================================================== 0x0060
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 fnpll_mash_en : 1 ; // Default: 0x0;
+ u32 fnpll_mash_mod : 2 ; // Default: 0x0;
+ u32 fnpll_mash_stp : 9 ; // Default: 0x0;
+ u32 fnpll_mash_m12 : 1 ; // Default: 0x0;
+ u32 fnpll_mash_frq : 2 ; // Default: 0x0;
+ u32 fnpll_mash_bot : 17 ; // Default: 0x0;
+ } bits;
+} HDMI_MODULATOR_CFG0_t; //===================================================== 0x0064
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 fnpll_mash_dth : 1 ; // Default: 0x0;
+ u32 fnpll_mash_fen : 1 ; // Default: 0x0;
+ u32 fnpll_mash_frc : 17 ; // Default: 0x0;
+ u32 fnpll_mash_fnv : 8 ; // Default: 0x0;
+ u32 res0 : 5 ; // Default: 0x0;
+ } bits;
+} HDMI_MODULATOR_CFG1_t; //===================================================== 0x0068
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 txdata_debugmode : 2 ; // Default: 0x0;
+ u32 res0 : 14 ; // Default: 0x0;
+ u32 ceci_debug : 1 ; // Default: 0x0;
+ u32 ceci_debugmode : 1 ; // Default: 0x0;
+ u32 res1 : 2 ; // Default: 0x0;
+ u32 sdai_debug : 1 ; // Default: 0x0;
+ u32 sdai_debugmode : 1 ; // Default: 0x0;
+ u32 res2 : 2 ; // Default: 0x0;
+ u32 scli_debug : 1 ; // Default: 0x0;
+ u32 scli_debugmode : 1 ; // Default: 0x0;
+ u32 res3 : 2 ; // Default: 0x0;
+ u32 hpdi_debug : 1 ; // Default: 0x0;
+ u32 hpdi_debugmode : 1 ; // Default: 0x0;
+ u32 res4 : 2 ; // Default: 0x0;
+ } bits;
+} HDMI_PHY_INDBG_CTRL_t; //================================================== 0x006C
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 txdata0_debug_data : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PHY_INDBG_TXD0_t; //================================================== 0x0070
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 txdata1_debug_data : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PHY_INDBG_TXD1_t; //================================================== 0x0074
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 txdata2_debug_data : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PHY_INDBG_TXD2_t; //================================================== 0x0078
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 txdata3_debug_data : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PHY_INDBG_TXD3_t; //================================================== 0x007C
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 tx_ready_dly_status : 1 ; // Default: 0x0;
+ u32 rxsense_dly_status : 1 ; // Default: 0x0;
+ u32 res0 : 2 ; // Default: 0x0;
+ u32 pll_lock_status : 1 ; // Default: 0x0;
+ u32 res1 : 3 ; // Default: 0x0;
+ u32 phy_resdo2d_status : 6 ; // Default: 0x0;
+ u32 res2 : 2 ; // Default: 0x0;
+ u32 phy_rcalend2d_status : 1 ; // Default: 0x0;
+ u32 phy_cout2d_status : 1 ; // Default: 0x0;
+ u32 res3 : 2 ; // Default: 0x0;
+ u32 phy_ceco_status : 1 ; // Default: 0x0;
+ u32 phy_sdao_status : 1 ; // Default: 0x0;
+ u32 phy_sclo_status : 1 ; // Default: 0x0;
+ u32 phy_hpdo_status : 1 ; // Default: 0x0;
+ u32 phy_cdetn_status : 3 ; // Default: 0x0;
+ u32 phy_cdetnck_status : 1 ; // Default: 0x0;
+ u32 phy_cdetp_status : 3 ; // Default: 0x0;
+ u32 phy_cdetpck_status : 1 ; // Default: 0x0;
+ } bits;
+} HDMI_PHY_PLL_STS_t; //===================================================== 0x0080
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 prbs_en : 1 ; // Default: 0x0;
+ u32 prbs_start : 1 ; // Default: 0x0;
+ u32 prbs_seq_gen : 1 ; // Default: 0x0;
+ u32 prbs_seq_chk : 1 ; // Default: 0x0;
+ u32 prbs_mode : 4 ; // Default: 0x0;
+ u32 prbs_type : 2 ; // Default: 0x0;
+ u32 prbs_clk_pol : 1 ; // Default: 0x0;
+ u32 res0 : 21 ; // Default: 0x0;
+ } bits;
+} HDMI_PRBS_CTL_t; //===================================================== 0x0084
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 prbs_seed_gen : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PRBS_SEED_GEN_t; //================================================= 0x0088
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 prbs_seed_chk : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PRBS_SEED_CHK_t; //================================================= 0x008C
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 prbs_seed_num : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PRBS_SEED_NUM_t; //================================================= 0x0090
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 prbs_cycle_num : 32 ; // Default: 0x0;
+ } bits;
+} HDMI_PRBS_CYCLE_NUM_t; //================================================= 0x0094
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 tx_ready_dly_count : 15 ; // Default: 0x0;
+ u32 tx_ready_dly_reset : 1 ; // Default: 0x0;
+ u32 rxsense_dly_count : 15 ; // Default: 0x0;
+ u32 rxsense_dly_reset : 1 ; // Default: 0x0;
+ } bits;
+} HDMI_PHY_PLL_ODLY_CFG_t; //================================================= 0x0098
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 clk_greate0_340m : 10 ; // Default: 0x3FF;
+ u32 clk_greate1_340m : 10 ; // Default: 0x3FF;
+ u32 clk_greate2_340m : 10 ; // Default: 0x3FF;
+ u32 en_ckdat : 1 ; // Default: 0x3FF;
+ u32 switch_clkch_data_corresponding : 1 ; // Default: 0x3FF;
+ } bits;
+} HDMI_PHY_CTL6_t; //========================================================= 0x009C
+
+typedef union {
+ u32 dwval;
+ struct {
+ u32 clk_greate3_340m : 10 ; // Default: 0x0;
+ u32 res0 : 2 ; // Default: 0x3FF;
+ u32 clk_low_340m : 10 ; // Default: 0x3FF;
+ u32 res1 : 10 ; // Default: 0x3FF;
+ } bits;
+} HDMI_PHY_CTL7_t; //========================================================= 0x00A0
+
+struct __aw_phy_reg_t {
+ u32 res[16]; /* 0x0 ~ 0x3c */
+ HDMI_PHY_CTL0_t phy_ctl0; /* 0x0040 */
+ HDMI_PHY_CTL1_t phy_ctl1; /* 0x0044 */
+ HDMI_PHY_CTL2_t phy_ctl2; /* 0x0048 */
+ HDMI_PHY_CTL3_t phy_ctl3; /* 0x004c */
+ HDMI_PHY_CTL4_t phy_ctl4; /* 0x0050 */
+ HDMI_PHY_CTL5_t phy_ctl5; /* 0x0054 */
+ HDMI_PLL_CTL0_t pll_ctl0; /* 0x0058 */
+ HDMI_PLL_CTL1_t pll_ctl1; /* 0x005c */
+ HDMI_AFIFO_CFG_t afifo_cfg; /* 0x0060 */
+ HDMI_MODULATOR_CFG0_t modulator_cfg0; /* 0x0064 */
+ HDMI_MODULATOR_CFG1_t modulator_cfg1; /* 0x0068 */
+ HDMI_PHY_INDBG_CTRL_t phy_indbg_ctrl; /* 0x006c */
+ HDMI_PHY_INDBG_TXD0_t phy_indbg_txd0; /* 0x0070 */
+ HDMI_PHY_INDBG_TXD1_t phy_indbg_txd1; /* 0x0074 */
+ HDMI_PHY_INDBG_TXD2_t phy_indbg_txd2; /* 0x0078 */
+ HDMI_PHY_INDBG_TXD3_t phy_indbg_txd3; /* 0x007c */
+ HDMI_PHY_PLL_STS_t phy_pll_sts; /* 0x0080 */
+ HDMI_PRBS_CTL_t prbs_ctl; /* 0x0084 */
+ HDMI_PRBS_SEED_GEN_t prbs_seed_gen; /* 0x0088 */
+ HDMI_PRBS_SEED_CHK_t prbs_seed_chk; /* 0x008c */
+ HDMI_PRBS_SEED_NUM_t prbs_seed_num; /* 0x0090 */
+ HDMI_PRBS_CYCLE_NUM_t prbs_cycle_num; /* 0x0094 */
+ HDMI_PHY_PLL_ODLY_CFG_t phy_pll_odly_cfg; /* 0x0098 */
+ HDMI_PHY_CTL6_t phy_ctl6; /* 0x009c */
+ HDMI_PHY_CTL7_t phy_ctl7; /* 0x00A0 */
+};
+
+#endif /* AW_PHY_H_ */
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -334,6 +334,7 @@ struct sun8i_hdmi_phy {
struct clk *clk_pll1;
struct device *dev;
unsigned int rcal;
+ void __iomem *base;
struct regmap *regs;
struct reset_control *rst_phy;
const struct sun8i_hdmi_phy_variant *variant;
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -9,6 +9,8 @@
#include "sun8i_dw_hdmi.h"
+#include "aw_phy.h"
+
/*
* Address can be actually any value. Here is set to same value as
* it is set in BSP driver.
@@ -398,11 +400,164 @@ static const struct dw_hdmi_phy_ops sun8
.setup_hpd = dw_hdmi_phy_setup_hpd,
};
+static int sun20i_d1_hdmi_phy_enable(volatile struct __aw_phy_reg_t __iomem *phy_base)
+{
+ int i = 0, status = 0;
+
+ pr_info("enter %s\n", __func__);
+
+ //enib -> enldo -> enrcal -> encalog -> enbi[3:0] -> enck -> enp2s[3:0] -> enres -> enresck -> entx[3:0]
+ phy_base->phy_ctl4.bits.reg_slv = 4; //low power voltage 1.08V, default is 3, set 4 as well as pll_ctl0 bit [24:26]
+ phy_base->phy_ctl5.bits.enib = 1;
+ phy_base->phy_ctl0.bits.enldo = 1;
+ phy_base->phy_ctl0.bits.enldo_fs = 1;
+ phy_base->phy_ctl5.bits.enrcal = 1;
+
+ phy_base->phy_ctl5.bits.encalog = 1;
+
+ for (i = 0; i < AW_PHY_TIMEOUT; i++) {
+ udelay(5);
+ status = phy_base->phy_pll_sts.bits.phy_rcalend2d_status;
+ if (status & 0x1) {
+ pr_info("[%s]:phy_rcalend2d_status\n", __func__);
+ break;
+ }
+ }
+ if ((i == AW_PHY_TIMEOUT) && !status) {
+ pr_err("phy_rcalend2d_status Timeout !\n");
+ return -1;
+ }
+
+ phy_base->phy_ctl0.bits.enbi = 0xF;
+ for (i = 0; i < AW_PHY_TIMEOUT; i++) {
+ udelay(5);
+ status = phy_base->phy_pll_sts.bits.pll_lock_status;
+ if (status & 0x1) {
+ pr_info("[%s]:pll_lock_status\n", __func__);
+ break;
+ }
+ }
+ if ((i == AW_PHY_TIMEOUT) && !status) {
+ pr_err("pll_lock_status Timeout! status = 0x%x\n", status);
+ return -1;
+ }
+
+ phy_base->phy_ctl0.bits.enck = 1;
+ phy_base->phy_ctl5.bits.enp2s = 0xF;
+ phy_base->phy_ctl5.bits.enres = 1;
+ phy_base->phy_ctl5.bits.enresck = 1;
+ phy_base->phy_ctl0.bits.entx = 0xF;
+
+ for (i = 0; i < AW_PHY_TIMEOUT; i++) {
+ udelay(5);
+ status = phy_base->phy_pll_sts.bits.tx_ready_dly_status;
+ if (status & 0x1) {
+ pr_info("[%s]:tx_ready_status\n", __func__);
+ break;
+ }
+ }
+ if ((i == AW_PHY_TIMEOUT) && !status) {
+ pr_err("tx_ready_status Timeout ! status = 0x%x\n", status);
+ return -1;
+ }
+
+ return 0;
+}
+
static int sun20i_d1_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
const struct drm_display_info *display,
const struct drm_display_mode *mode)
{
struct sun8i_hdmi_phy *phy = data;
+ volatile struct __aw_phy_reg_t __iomem *phy_base = phy->base;
+ int ret;
+
+ pr_info("enter %s\n", __func__);
+
+ /* enable all channel */
+ phy_base->phy_ctl5.bits.reg_p1opt = 0xF;
+
+ // phy_reset
+ phy_base->phy_ctl0.bits.entx = 0;
+ phy_base->phy_ctl5.bits.enresck = 0;
+ phy_base->phy_ctl5.bits.enres = 0;
+ phy_base->phy_ctl5.bits.enp2s = 0;
+ phy_base->phy_ctl0.bits.enck = 0;
+ phy_base->phy_ctl0.bits.enbi = 0;
+ phy_base->phy_ctl5.bits.encalog = 0;
+ phy_base->phy_ctl5.bits.enrcal = 0;
+ phy_base->phy_ctl0.bits.enldo_fs = 0;
+ phy_base->phy_ctl0.bits.enldo = 0;
+ phy_base->phy_ctl5.bits.enib = 0;
+ phy_base->pll_ctl1.bits.reset = 1;
+ phy_base->pll_ctl1.bits.pwron = 0;
+ phy_base->pll_ctl0.bits.envbs = 0;
+
+ // phy_set_mpll
+ phy_base->pll_ctl0.bits.cko_sel = 0x3;
+ phy_base->pll_ctl0.bits.bypass_ppll = 0x1;
+ phy_base->pll_ctl1.bits.drv_ana = 1;
+ phy_base->pll_ctl1.bits.ctrl_modle_clksrc = 0x0; //0: PLL_video 1: MPLL
+ phy_base->pll_ctl1.bits.sdm_en = 0x0; //mpll sdm jitter is very large, not used for the time being
+ phy_base->pll_ctl1.bits.sckref = 0; //default value is 1
+ phy_base->pll_ctl0.bits.slv = 4;
+ phy_base->pll_ctl0.bits.prop_cntrl = 7; //default value 7
+ phy_base->pll_ctl0.bits.gmp_cntrl = 3; //default value 1
+ phy_base->pll_ctl1.bits.ref_cntrl = 0;
+ phy_base->pll_ctl0.bits.vcorange = 1;
+
+ // phy_set_div
+ phy_base->pll_ctl0.bits.div_pre = 0; //div7 = n+1
+ phy_base->pll_ctl1.bits.pcnt_en = 0;
+ phy_base->pll_ctl1.bits.pcnt_n = 1; //div6 = 1 (pcnt_en=0) [div6 = n (pcnt_en = 1) note that some multiples are problematic] 4-256
+ phy_base->pll_ctl1.bits.pixel_rep = 0; //div5 = n+1
+ phy_base->pll_ctl0.bits.bypass_clrdpth = 0;
+ phy_base->pll_ctl0.bits.clr_dpth = 0; //div4 = 1 (bypass_clrdpth = 0)
+ //00: 2 01: 2.5 10: 3 11: 4
+ phy_base->pll_ctl0.bits.n_cntrl = 1; //div
+ phy_base->pll_ctl0.bits.div2_ckbit = 0; //div1 = n+1
+ phy_base->pll_ctl0.bits.div2_cktmds = 0; //div2 = n+1
+ phy_base->pll_ctl0.bits.bcr = 0; //div3 0: [1:10] 1: [1:40]
+ phy_base->pll_ctl1.bits.pwron = 1;
+ phy_base->pll_ctl1.bits.reset = 0;
+
+ // configure phy
+ /* config values taken from table */
+ phy_base->phy_ctl1.dwval = ((phy_base->phy_ctl1.dwval & 0xFFC0FFFF) | /* config->phy_ctl1 */ 0x0);
+ phy_base->phy_ctl2.dwval = ((phy_base->phy_ctl2.dwval & 0xFF000000) | /* config->phy_ctl2 */ 0x0);
+ phy_base->phy_ctl3.dwval = ((phy_base->phy_ctl3.dwval & 0xFFFF0000) | /* config->phy_ctl3 */ 0xFFFF);
+ phy_base->phy_ctl4.dwval = ((phy_base->phy_ctl4.dwval & 0xE0000000) | /* config->phy_ctl4 */ 0xC0D0D0D);
+ //phy_base->pll_ctl0.dwval |= config->pll_ctl0;
+ //phy_base->pll_ctl1.dwval |= config->pll_ctl1;
+
+ // phy_set_clk
+ phy_base->phy_ctl6.bits.switch_clkch_data_corresponding = 0;
+ phy_base->phy_ctl6.bits.clk_greate0_340m = 0x3FF;
+ phy_base->phy_ctl6.bits.clk_greate1_340m = 0x3FF;
+ phy_base->phy_ctl6.bits.clk_greate2_340m = 0x0;
+ phy_base->phy_ctl7.bits.clk_greate3_340m = 0x0;
+ phy_base->phy_ctl7.bits.clk_low_340m = 0x3E0;
+ phy_base->phy_ctl6.bits.en_ckdat = 1; //default value is 0
+
+ // phy_base->phy_ctl2.bits.reg_resdi = 0x18;
+ // phy_base->phy_ctl4.bits.reg_slv = 3; //low power voltage 1.08V, default value is 3
+
+ phy_base->phy_ctl1.bits.res_scktmds = 0; //
+ phy_base->phy_ctl0.bits.reg_csmps = 2;
+ phy_base->phy_ctl0.bits.reg_ck_test_sel = 0; //?
+ phy_base->phy_ctl0.bits.reg_ck_sel = 1;
+ phy_base->phy_indbg_ctrl.bits.txdata_debugmode = 0;
+
+ // phy_enable
+ ret = sun20i_d1_hdmi_phy_enable(phy_base);
+ if (ret)
+ return ret;
+
+ phy_base->phy_ctl0.bits.sda_en = 1;
+ phy_base->phy_ctl0.bits.scl_en = 1;
+ phy_base->phy_ctl0.bits.hpd_en = 1;
+ phy_base->phy_ctl0.bits.reg_den = 0xF;
+ phy_base->pll_ctl0.bits.envbs = 1;
return 0;
}
@@ -720,6 +875,7 @@ static int sun8i_hdmi_phy_probe(struct p
return dev_err_probe(dev, PTR_ERR(regs),
"Couldn't map the HDMI PHY registers\n");
+ phy->base = regs;
phy->regs = devm_regmap_init_mmio(dev, regs,
&sun8i_hdmi_phy_regmap_config);
if (IS_ERR(phy->regs))

View File

@ -0,0 +1,30 @@
From 02a412de18479449c87ed7a332e3fe33d2eff3a4 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 27 Apr 2022 18:47:53 -0500
Subject: [PATCH 010/117] riscv: mm: Use IOMMU for DMA when available
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/mm/dma-noncoherent.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/riscv/mm/dma-noncoherent.c
+++ b/arch/riscv/mm/dma-noncoherent.c
@@ -7,6 +7,7 @@
#include <linux/dma-direct.h>
#include <linux/dma-map-ops.h>
+#include <linux/iommu.h>
#include <linux/mm.h>
#include <asm/cacheflush.h>
@@ -70,6 +71,9 @@ void arch_setup_dma_ops(struct device *d
dev_driver_string(dev), dev_name(dev));
dev->dma_coherent = coherent;
+
+ if (iommu)
+ iommu_setup_dma_ops(dev, dma_base, dma_base + size - 1);
}
void riscv_noncoherent_supported(void)

View File

@ -0,0 +1,124 @@
From ee6459d60f24d91052f0288155f44e6a7f991050 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 7 May 2022 18:34:25 -0500
Subject: [PATCH 011/117] genirq: Add support for oneshot-safe threaded EOIs
irqchips can use the combination of flags IRQCHIP_ONESHOT_SAFE |
IRQCHIP_EOI_THREADED to elide mask operations.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
kernel/irq/chip.c | 36 +++++++++++++++++-------------------
kernel/irq/internals.h | 2 +-
kernel/irq/manage.c | 12 ++++++------
3 files changed, 24 insertions(+), 26 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -439,16 +439,6 @@ void unmask_irq(struct irq_desc *desc)
}
}
-void unmask_threaded_irq(struct irq_desc *desc)
-{
- struct irq_chip *chip = desc->irq_data.chip;
-
- if (chip->flags & IRQCHIP_EOI_THREADED)
- chip->irq_eoi(&desc->irq_data);
-
- unmask_irq(desc);
-}
-
/*
* handle_nested_irq - Handle a nested irq from a irq thread
* @irq: the interrupt number
@@ -656,25 +646,33 @@ out_unlock:
}
EXPORT_SYMBOL_GPL(handle_level_irq);
-static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
+void unmask_eoi_threaded_irq(struct irq_desc *desc)
{
- if (!(desc->istate & IRQS_ONESHOT)) {
+ struct irq_chip *chip = desc->irq_data.chip;
+
+ if (desc->istate & IRQS_ONESHOT)
+ unmask_irq(desc);
+
+ if (chip->flags & IRQCHIP_EOI_THREADED)
chip->irq_eoi(&desc->irq_data);
+}
+
+static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
+{
+ /* Do not send EOI if the thread will do it for us. */
+ if ((chip->flags & IRQCHIP_EOI_THREADED) && desc->threads_oneshot)
return;
- }
+
/*
* We need to unmask in the following cases:
* - Oneshot irq which did not wake the thread (caused by a
* spurious interrupt or a primary handler handling it
* completely).
*/
- if (!irqd_irq_disabled(&desc->irq_data) &&
- irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
- chip->irq_eoi(&desc->irq_data);
+ if ((desc->istate & IRQS_ONESHOT) && !desc->threads_oneshot)
unmask_irq(desc);
- } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
- chip->irq_eoi(&desc->irq_data);
- }
+
+ chip->irq_eoi(&desc->irq_data);
}
/**
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -93,7 +93,7 @@ extern void irq_percpu_enable(struct irq
extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
extern void mask_irq(struct irq_desc *desc);
extern void unmask_irq(struct irq_desc *desc);
-extern void unmask_threaded_irq(struct irq_desc *desc);
+extern void unmask_eoi_threaded_irq(struct irq_desc *desc);
#ifdef CONFIG_SPARSE_IRQ
static inline void irq_mark_irq(unsigned int irq) { }
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1074,9 +1074,9 @@ static int irq_wait_for_interrupt(struct
static void irq_finalize_oneshot(struct irq_desc *desc,
struct irqaction *action)
{
- if (!(desc->istate & IRQS_ONESHOT) ||
- action->handler == irq_forced_secondary_handler)
+ if (action->handler == irq_forced_secondary_handler)
return;
+
again:
chip_bus_lock(desc);
raw_spin_lock_irq(&desc->lock);
@@ -1112,9 +1112,8 @@ again:
desc->threads_oneshot &= ~action->thread_mask;
- if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
- irqd_irq_masked(&desc->irq_data))
- unmask_threaded_irq(desc);
+ if (!desc->threads_oneshot)
+ unmask_eoi_threaded_irq(desc);
out_unlock:
raw_spin_unlock_irq(&desc->lock);
@@ -1662,7 +1661,8 @@ __setup_irq(unsigned int irq, struct irq
* !ONESHOT irqs the thread mask is 0 so we can avoid a
* conditional in irq_wake_thread().
*/
- if (new->flags & IRQF_ONESHOT) {
+ if ((new->flags & IRQF_ONESHOT) ||
+ (desc->irq_data.chip->flags & (IRQCHIP_ONESHOT_SAFE | IRQCHIP_EOI_THREADED)) == (IRQCHIP_ONESHOT_SAFE | IRQCHIP_EOI_THREADED)) {
/*
* Unlikely to have 32 resp 64 irqs sharing one line,
* but who knows.

View File

@ -0,0 +1,24 @@
From 1fbe96ec05c41b313b4e7cc4b39b191b4a3f7540 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 7 May 2022 18:38:34 -0500
Subject: [PATCH 012/117] irqchip/sifive-plic: Enable oneshot-safe threaded
EOIs
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/irqchip/irq-sifive-plic.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -201,7 +201,9 @@ static struct irq_chip plic_chip = {
.irq_set_affinity = plic_set_affinity,
#endif
.irq_set_type = plic_irq_set_type,
- .flags = IRQCHIP_AFFINITY_PRE_STARTUP,
+ .flags = IRQCHIP_ONESHOT_SAFE |
+ IRQCHIP_EOI_THREADED |
+ IRQCHIP_AFFINITY_PRE_STARTUP,
};
static int plic_irq_set_type(struct irq_data *d, unsigned int type)

View File

@ -0,0 +1,32 @@
From d6cf6473b0aaec455e48bccefe318a98a87b789f Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 28 May 2022 19:04:56 -0500
Subject: [PATCH 013/117] irqchip/sifive-plic: Support wake IRQs
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/irqchip/irq-sifive-plic.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -187,7 +187,8 @@ static struct irq_chip plic_edge_chip =
.irq_set_affinity = plic_set_affinity,
#endif
.irq_set_type = plic_irq_set_type,
- .flags = IRQCHIP_AFFINITY_PRE_STARTUP,
+ .flags = IRQCHIP_SKIP_SET_WAKE |
+ IRQCHIP_AFFINITY_PRE_STARTUP,
};
static struct irq_chip plic_chip = {
@@ -201,7 +202,8 @@ static struct irq_chip plic_chip = {
.irq_set_affinity = plic_set_affinity,
#endif
.irq_set_type = plic_irq_set_type,
- .flags = IRQCHIP_ONESHOT_SAFE |
+ .flags = IRQCHIP_SKIP_SET_WAKE |
+ IRQCHIP_ONESHOT_SAFE |
IRQCHIP_EOI_THREADED |
IRQCHIP_AFFINITY_PRE_STARTUP,
};

View File

@ -0,0 +1,65 @@
From 0e871e791a2530562851109346affa1c0d9987e0 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 13 Jun 2021 23:15:56 -0500
Subject: [PATCH 014/117] mmc: sunxi-mmc: Correct the maximum segment size
According to the DMA descriptor documentation, the lowest two bits of
the size field are ignored, so the size must be rounded up to a multiple
of 4 bytes. Furthermore, 0 is not a valid buffer size; setting the size
to 0 will cause that DMA descriptor to be ignored.
Together, these restrictions limit the maximum DMA segment size to 4
less than the power-of-two width of the size field.
Series-to: Ulf Hansson <ulf.hansson@linaro.org>
Series-to: linux-mmc@vger.kernel.org
Fixes: 3cbcb16095f9 ("mmc: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs")
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/mmc/host/sunxi-mmc.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -214,6 +214,9 @@
#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */
#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */
+/* Buffer size must be a multiple of 4 bytes. */
+#define SDXC_IDMAC_SIZE_ALIGN 4
+
#define SDXC_CLK_400K 0
#define SDXC_CLK_25M 1
#define SDXC_CLK_50M 2
@@ -361,17 +364,15 @@ static void sunxi_mmc_init_idma_des(stru
{
struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
dma_addr_t next_desc = host->sg_dma;
- int i, max_len = (1 << host->cfg->idma_des_size_bits);
+ int i;
for (i = 0; i < data->sg_len; i++) {
pdes[i].config = cpu_to_le32(SDXC_IDMAC_DES0_CH |
SDXC_IDMAC_DES0_OWN |
SDXC_IDMAC_DES0_DIC);
- if (data->sg[i].length == max_len)
- pdes[i].buf_size = 0; /* 0 == max_len */
- else
- pdes[i].buf_size = cpu_to_le32(data->sg[i].length);
+ pdes[i].buf_size = cpu_to_le32(ALIGN(data->sg[i].length,
+ SDXC_IDMAC_SIZE_ALIGN));
next_desc += sizeof(struct sunxi_idma_des);
pdes[i].buf_addr_ptr1 =
@@ -1421,7 +1422,8 @@ static int sunxi_mmc_probe(struct platfo
mmc->max_blk_count = 8192;
mmc->max_blk_size = 4096;
mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des);
- mmc->max_seg_size = (1 << host->cfg->idma_des_size_bits);
+ mmc->max_seg_size = (1 << host->cfg->idma_des_size_bits) -
+ SDXC_IDMAC_SIZE_ALIGN;
mmc->max_req_size = mmc->max_seg_size * mmc->max_segs;
/* 400kHz ~ 52MHz */
mmc->f_min = 400000;

View File

@ -0,0 +1,82 @@
From a8e905fb3fd0d26f724646275b72a7363b2f03d8 Mon Sep 17 00:00:00 2001
From: Max Fierke <max@maxfierke.com>
Date: Wed, 1 Jun 2022 00:17:47 -0500
Subject: [PATCH 015/117] dt-bindings: display: Add bindings for ClockworkPi
CWD686
The CWD686 is a 6.86" IPS LCD panel used as the primary
display in the ClockworkPi DevTerm portable (all cores)
Signed-off-by: Max Fierke <max@maxfierke.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../display/panel/clockwork,cwd686.yaml | 62 +++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/panel/clockwork,cwd686.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/clockwork,cwd686.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/clockwork,cwd686.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Clockwork CWD686 6.86" IPS LCD panel
+
+maintainers:
+ - Max Fierke <max@maxfierke.com>
+
+description: |
+ The Clockwork CWD686 is a 6.86" ICNL9707-based IPS LCD panel used within the
+ Clockwork DevTerm series of portable devices. The panel has a 480x1280
+ resolution and uses 24 bit RGB per pixel.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ const: clockwork,cwd686
+
+ reg:
+ description: DSI virtual channel used by that screen
+ maxItems: 1
+
+ reset-gpios: true
+ rotation: true
+ backlight: true
+ iovcc-supply: true
+ vci-supply: true
+
+required:
+ - compatible
+ - reg
+ - backlight
+ - reset-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ backlight: backlight {
+ compatible = "gpio-backlight";
+ gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+ };
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "clockwork,cwd686";
+ reg = <0>;
+ backlight = <&backlight>;
+ reset-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>;
+ rotation = <90>;
+ };
+ };

View File

@ -0,0 +1,47 @@
From d290546a88694dde6d2f64a973cd62ff2c69e27e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Fri, 12 Aug 2022 01:59:35 -0500
Subject: [PATCH 016/117] dt-bindings: display: Add Sitronix ST7701s panel
binding
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../display/panel/sitronix,st7701s.yaml | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/panel/sitronix,st7701s.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7701s.yaml
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/sitronix,st7701s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sitronix ST7701 based LCD panels
+
+maintainers:
+ - Samuel Holland <samuel@sholland.org>
+
+description: |
+ Panel used on Lichee RV 86 Panel
+
+allOf:
+ - $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: sitronix,st7701s
+
+ backlight: true
+
+ reset-gpios: true
+
+required:
+ - compatible
+ - reset-gpios
+
+unevaluatedProperties: false

View File

@ -0,0 +1,487 @@
From 9d9b8bd567c30a821c82c27035243536c5234542 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Tue, 29 Mar 2022 22:47:57 -0500
Subject: [PATCH 017/117] drm/panel: Add driver for ST7701s DPI LCD panel
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/panel/Kconfig | 8 +
drivers/gpu/drm/panel/Makefile | 1 +
.../gpu/drm/panel/panel-sitronix-st7701s.c | 444 ++++++++++++++++++
3 files changed, 453 insertions(+)
create mode 100644 drivers/gpu/drm/panel/panel-sitronix-st7701s.c
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -608,6 +608,14 @@ config DRM_PANEL_SITRONIX_ST7701
ST7701 controller for 480X864 LCD panels with MIPI/RGB/SPI
system interfaces.
+config DRM_PANEL_SITRONIX_ST7701S
+ tristate "Sitronix ST7701s panel driver"
+ depends on OF
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for the Sitronix
+ ST7701s controller with a SPI interface.
+
config DRM_PANEL_SITRONIX_ST7703
tristate "Sitronix ST7703 based MIPI touchscreen panels"
depends on OF
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01
obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS060T1SX01) += panel-sharp-ls060t1sx01.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o
+obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701S) += panel-sitronix-st7701s.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7701s.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2017 Free Electrons
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct st7701s {
+ struct drm_panel panel;
+ struct gpio_desc *reset;
+ struct spi_device *spi;
+};
+
+enum {
+ ST7789V_COMMAND = 0 << 8,
+ ST7789V_DATA = 1 << 8,
+};
+
+#define LCD_WRITE_COMMAND(x) (ST7789V_COMMAND | (x))
+#define LCD_WRITE_DATA(x) (ST7789V_DATA | (x))
+
+static const u16 st7701s_init_sequence_1[] = {
+ LCD_WRITE_COMMAND(0xFF),
+ LCD_WRITE_DATA(0x77),
+ LCD_WRITE_DATA(0x01),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x10),
+
+ LCD_WRITE_COMMAND(0xC0),
+ LCD_WRITE_DATA(0x3B),
+ LCD_WRITE_DATA(0x00),
+
+ LCD_WRITE_COMMAND(0xC1),
+ LCD_WRITE_DATA(0x0D),
+ LCD_WRITE_DATA(0x02),
+
+ LCD_WRITE_COMMAND(0xC2),
+ LCD_WRITE_DATA(0x21),
+ LCD_WRITE_DATA(0x08),
+
+ // RGB Interface Setting
+ // LCD_WRITE_COMMAND(0xC3),
+ // LCD_WRITE_DATA(0x02),
+
+ LCD_WRITE_COMMAND(0xCD),
+ LCD_WRITE_DATA(0x18),//0F 08-OK D0-D18
+
+ LCD_WRITE_COMMAND(0xB0),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x18),
+ LCD_WRITE_DATA(0x0E),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x06),
+ LCD_WRITE_DATA(0x07),
+ LCD_WRITE_DATA(0x08),
+ LCD_WRITE_DATA(0x07),
+ LCD_WRITE_DATA(0x22),
+ LCD_WRITE_DATA(0x04),
+ LCD_WRITE_DATA(0x12),
+ LCD_WRITE_DATA(0x0F),
+ LCD_WRITE_DATA(0xAA),
+ LCD_WRITE_DATA(0x31),
+ LCD_WRITE_DATA(0x18),
+
+ LCD_WRITE_COMMAND(0xB1),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x19),
+ LCD_WRITE_DATA(0x0E),
+ LCD_WRITE_DATA(0x12),
+ LCD_WRITE_DATA(0x07),
+ LCD_WRITE_DATA(0x08),
+ LCD_WRITE_DATA(0x08),
+ LCD_WRITE_DATA(0x08),
+ LCD_WRITE_DATA(0x22),
+ LCD_WRITE_DATA(0x04),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0xA9),
+ LCD_WRITE_DATA(0x32),
+ LCD_WRITE_DATA(0x18),
+
+ LCD_WRITE_COMMAND(0xFF),
+ LCD_WRITE_DATA(0x77),
+ LCD_WRITE_DATA(0x01),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x11),
+
+ LCD_WRITE_COMMAND(0xB0),
+ LCD_WRITE_DATA(0x60),
+
+ LCD_WRITE_COMMAND(0xB1),
+ LCD_WRITE_DATA(0x30),
+
+ LCD_WRITE_COMMAND(0xB2),
+ LCD_WRITE_DATA(0x87),
+
+ LCD_WRITE_COMMAND(0xB3),
+ LCD_WRITE_DATA(0x80),
+
+ LCD_WRITE_COMMAND(0xB5),
+ LCD_WRITE_DATA(0x49),
+
+ LCD_WRITE_COMMAND(0xB7),
+ LCD_WRITE_DATA(0x85),
+
+ LCD_WRITE_COMMAND(0xB8),
+ LCD_WRITE_DATA(0x21),
+
+ LCD_WRITE_COMMAND(0xC1),
+ LCD_WRITE_DATA(0x78),
+
+ LCD_WRITE_COMMAND(0xC2),
+ LCD_WRITE_DATA(0x78),
+};
+
+static const u16 st7701s_init_sequence_2[] = {
+ LCD_WRITE_COMMAND(0xE0),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x1B),
+ LCD_WRITE_DATA(0x02),
+
+ LCD_WRITE_COMMAND(0xE1),
+ LCD_WRITE_DATA(0x08),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x07),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x44),
+ LCD_WRITE_DATA(0x44),
+
+ LCD_WRITE_COMMAND(0xE2),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x44),
+ LCD_WRITE_DATA(0x44),
+ LCD_WRITE_DATA(0xED),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0xEC),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+
+ LCD_WRITE_COMMAND(0xE3),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x11),
+
+ LCD_WRITE_COMMAND(0xE4),
+ LCD_WRITE_DATA(0x44),
+ LCD_WRITE_DATA(0x44),
+
+ LCD_WRITE_COMMAND(0xE5),
+ LCD_WRITE_DATA(0x0A),
+ LCD_WRITE_DATA(0xE9),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x0C),
+ LCD_WRITE_DATA(0xEB),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x0E),
+ LCD_WRITE_DATA(0xED),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x10),
+ LCD_WRITE_DATA(0xEF),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+
+ LCD_WRITE_COMMAND(0xE6),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x11),
+ LCD_WRITE_DATA(0x11),
+
+ LCD_WRITE_COMMAND(0xE7),
+ LCD_WRITE_DATA(0x44),
+ LCD_WRITE_DATA(0x44),
+
+ LCD_WRITE_COMMAND(0xE8),
+ LCD_WRITE_DATA(0x09),
+ LCD_WRITE_DATA(0xE8),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x0B),
+ LCD_WRITE_DATA(0xEA),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x0D),
+ LCD_WRITE_DATA(0xEC),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+ LCD_WRITE_DATA(0x0F),
+ LCD_WRITE_DATA(0xEE),
+ LCD_WRITE_DATA(0xD8),
+ LCD_WRITE_DATA(0xA0),
+
+ LCD_WRITE_COMMAND(0xEB),
+ LCD_WRITE_DATA(0x02),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0xE4),
+ LCD_WRITE_DATA(0xE4),
+ LCD_WRITE_DATA(0x88),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x40),
+
+ LCD_WRITE_COMMAND(0xEC),
+ LCD_WRITE_DATA(0x3C),
+ LCD_WRITE_DATA(0x00),
+
+ LCD_WRITE_COMMAND(0xED),
+ LCD_WRITE_DATA(0xAB),
+ LCD_WRITE_DATA(0x89),
+ LCD_WRITE_DATA(0x76),
+ LCD_WRITE_DATA(0x54),
+ LCD_WRITE_DATA(0x02),
+ LCD_WRITE_DATA(0xFF),
+ LCD_WRITE_DATA(0xFF),
+ LCD_WRITE_DATA(0xFF),
+ LCD_WRITE_DATA(0xFF),
+ LCD_WRITE_DATA(0xFF),
+ LCD_WRITE_DATA(0xFF),
+ LCD_WRITE_DATA(0x20),
+ LCD_WRITE_DATA(0x45),
+ LCD_WRITE_DATA(0x67),
+ LCD_WRITE_DATA(0x98),
+ LCD_WRITE_DATA(0xBA),
+
+ LCD_WRITE_COMMAND(0xFF),
+ LCD_WRITE_DATA(0x77),
+ LCD_WRITE_DATA(0x01),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+ LCD_WRITE_DATA(0x00),
+
+ LCD_WRITE_COMMAND(MIPI_DCS_SET_PIXEL_FORMAT),
+ LCD_WRITE_DATA(0x66),
+
+ LCD_WRITE_COMMAND(MIPI_DCS_SET_ADDRESS_MODE),
+ LCD_WRITE_DATA(0x00),
+
+ LCD_WRITE_COMMAND(MIPI_DCS_ENTER_INVERT_MODE),
+
+ LCD_WRITE_COMMAND(MIPI_DCS_EXIT_SLEEP_MODE),
+};
+
+static const u16 st7701s_enable_sequence[] = {
+ LCD_WRITE_COMMAND(MIPI_DCS_SET_DISPLAY_ON),
+};
+
+static const u16 st7701s_disable_sequence[] = {
+ LCD_WRITE_COMMAND(MIPI_DCS_SET_DISPLAY_OFF),
+};
+
+static inline struct st7701s *panel_to_st7701s(struct drm_panel *panel)
+{
+ return container_of(panel, struct st7701s, panel);
+}
+
+static int st7701s_spi_write(struct st7701s *ctx, const u16 *data, size_t size)
+{
+ struct spi_transfer xfer = { };
+ struct spi_message msg;
+
+ spi_message_init(&msg);
+
+ xfer.tx_buf = data;
+ xfer.bits_per_word = 9;
+ xfer.len = size;
+
+ spi_message_add_tail(&xfer, &msg);
+ return spi_sync(ctx->spi, &msg);
+}
+
+static const struct drm_display_mode default_mode = {
+ .clock = 19800,
+ .hdisplay = 480,
+ .hsync_start = 480 + 60,
+ .hsync_end = 480 + 60 + 12,
+ .htotal = 480 + 60 + 12 + 60,
+ .vdisplay = 480,
+ .vsync_start = 480 + 18,
+ .vsync_end = 480 + 18 + 4,
+ .vtotal = 480 + 18 + 4 + 18,
+};
+
+static int st7701s_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, &default_mode);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_probed_add(connector, mode);
+
+ connector->display_info.width_mm = 70;
+ connector->display_info.height_mm = 72;
+
+ return 1;
+}
+
+static int st7701s_prepare(struct drm_panel *panel)
+{
+ struct st7701s *ctx = panel_to_st7701s(panel);
+
+ gpiod_set_value_cansleep(ctx->reset, 1);
+ msleep(20);
+
+ gpiod_set_value_cansleep(ctx->reset, 0);
+ msleep(20);
+
+ st7701s_spi_write(ctx, st7701s_init_sequence_1,
+ sizeof(st7701s_init_sequence_1));
+ msleep(20);
+
+ st7701s_spi_write(ctx, st7701s_init_sequence_2,
+ sizeof(st7701s_init_sequence_2));
+ msleep(120);
+
+ return 0;
+}
+
+static int st7701s_enable(struct drm_panel *panel)
+{
+ struct st7701s *ctx = panel_to_st7701s(panel);
+
+ st7701s_spi_write(ctx, st7701s_enable_sequence,
+ sizeof(st7701s_enable_sequence));
+ msleep(20);
+
+ return 0;
+}
+
+static int st7701s_disable(struct drm_panel *panel)
+{
+ struct st7701s *ctx = panel_to_st7701s(panel);
+
+ st7701s_spi_write(ctx, st7701s_disable_sequence,
+ sizeof(st7701s_disable_sequence));
+
+ return 0;
+}
+
+static int st7701s_unprepare(struct drm_panel *panel)
+{
+ return 0;
+}
+
+static const struct drm_panel_funcs st7701s_drm_funcs = {
+ .disable = st7701s_disable,
+ .enable = st7701s_enable,
+ .get_modes = st7701s_get_modes,
+ .prepare = st7701s_prepare,
+ .unprepare = st7701s_unprepare,
+};
+
+static int st7701s_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct st7701s *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, ctx);
+ ctx->spi = spi;
+
+ ctx->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset)) {
+ dev_err(&spi->dev, "Couldn't get our reset line\n");
+ return PTR_ERR(ctx->reset);
+ }
+
+ drm_panel_init(&ctx->panel, dev, &st7701s_drm_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return ret;
+
+ drm_panel_add(&ctx->panel);
+
+ return 0;
+}
+
+static void st7701s_remove(struct spi_device *spi)
+{
+ struct st7701s *ctx = spi_get_drvdata(spi);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id st7701s_of_match[] = {
+ { .compatible = "sitronix,st7701s" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, st7701s_of_match);
+
+static const struct spi_device_id st7701s_ids[] = {
+ { "st7701s" },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, st7701s_ids);
+
+static struct spi_driver st7701s_driver = {
+ .probe = st7701s_probe,
+ .remove = st7701s_remove,
+ .driver = {
+ .name = "st7701s",
+ .of_match_table = st7701s_of_match,
+ },
+};
+module_spi_driver(st7701s_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Sitronix ST7701s LCD Driver");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,42 @@
From db71abf941d25b92b2117780d3771197417d1c81 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 31 Jul 2022 20:34:20 -0500
Subject: [PATCH 018/117] nvmem: sunxi_sid: Drop the workaround on A64
Now that the SRAM readout code is fixed by using 32-bit accesses, it
always returns the same values as register readout, so the A64 variant
no longer needs the workaround. This makes the D1 variant structure
redundant, so remove it.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/nvmem/sunxi_sid.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
--- a/drivers/nvmem/sunxi_sid.c
+++ b/drivers/nvmem/sunxi_sid.c
@@ -196,15 +196,9 @@ static const struct sunxi_sid_cfg sun8i_
.need_register_readout = true,
};
-static const struct sunxi_sid_cfg sun20i_d1_cfg = {
- .value_offset = 0x200,
- .size = 0x100,
-};
-
static const struct sunxi_sid_cfg sun50i_a64_cfg = {
.value_offset = 0x200,
.size = 0x100,
- .need_register_readout = true,
};
static const struct sunxi_sid_cfg sun50i_h6_cfg = {
@@ -217,7 +211,7 @@ static const struct of_device_id sunxi_s
{ .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg },
{ .compatible = "allwinner,sun8i-a83t-sid", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg },
- { .compatible = "allwinner,sun20i-d1-sid", .data = &sun20i_d1_cfg },
+ { .compatible = "allwinner,sun20i-d1-sid", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-h5-sid", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-h6-sid", .data = &sun50i_h6_cfg },

View File

@ -0,0 +1,30 @@
From d03341ef7acb64803ade6b173d24f49ffa6149a3 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Tue, 2 Aug 2022 00:29:32 -0500
Subject: [PATCH 019/117] dt-bindings: nvmem: Allow bit offsets greater than a
byte
Some NVMEM devices contain cells which do not start at a multiple of the
device's stride. However, the "reg" property of a cell must be aligned
to its provider device's stride.
These cells can be represented in the DT using the "bits" property if
that property allows offsets up to the full stride. 63 is chosen
assuming that NVMEM devices will not have strides larger than 8 bytes.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
Documentation/devicetree/bindings/nvmem/nvmem.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/nvmem/nvmem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
@@ -53,7 +53,7 @@ patternProperties:
$ref: /schemas/types.yaml#/definitions/uint32-array
items:
- minimum: 0
- maximum: 7
+ maximum: 63
description:
Offset in bit within the address range specified by reg.
- minimum: 1

View File

@ -0,0 +1,156 @@
From f666d95c1443854555044d3d4b52c463cf845ccc Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 17 Jul 2022 20:33:40 -0500
Subject: [PATCH 020/117] regulator: dt-bindings: Add Allwinner D1 LDOs
The Allwinner D1 SoC contains two pairs of in-package LDOs. One pair is
for general purpose use. LDOA generally powers the board's 1.8 V rail.
LDOB generally powers the in-package DRAM, where applicable.
The other pair of LDOs powers the analog power domains inside the SoC,
including the audio codec, thermal sensor, and ADCs. These LDOs require
a 0.9 V bandgap voltage reference. The calibration value for the voltage
reference is stored in an eFuse, accessed via an NVMEM cell.
Neither LDO control register is in its own MMIO range; instead, each
regulator device relies on a regmap/syscon exported by its parent.
Series-changes: 2
- Remove syscon property from bindings
- Update binding examples to fix warnings and provide context
Series-changes: 3
- Add "reg" property to bindings
- Add "unevaluatedProperties: true" to regulator nodes
- Minor changes to regulator node name patterns
- Remove system-ldos example (now added in patch 3)
Series-changes: 4
- Fix the order of the maintainer/description sections
- Replace unevaluatedProperties with "additionalProperties: false"
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../allwinner,sun20i-d1-analog-ldos.yaml | 74 +++++++++++++++++++
.../allwinner,sun20i-d1-system-ldos.yaml | 37 ++++++++++
2 files changed, 111 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-analog-ldos.yaml
create mode 100644 Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-analog-ldos.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/allwinner,sun20i-d1-analog-ldos.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner D1 Analog LDOs
+
+maintainers:
+ - Samuel Holland <samuel@sholland.org>
+
+description:
+ Allwinner D1 contains a set of LDOs which are designed to supply analog power
+ inside and outside the SoC. They are controlled by a register within the audio
+ codec MMIO space, but which is not part of the audio codec clock/reset domain.
+
+properties:
+ compatible:
+ enum:
+ - allwinner,sun20i-d1-analog-ldos
+
+ reg:
+ maxItems: 1
+
+ nvmem-cells:
+ items:
+ - description: NVMEM cell for the calibrated bandgap reference trim value
+
+ nvmem-cell-names:
+ items:
+ - const: bg_trim
+
+patternProperties:
+ "^(a|hp)ldo$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - nvmem-cells
+ - nvmem-cell-names
+
+additionalProperties: false
+
+examples:
+ - |
+ audio-codec@2030000 {
+ compatible = "simple-mfd", "syscon";
+ reg = <0x2030000 0x1000>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulators@2030348 {
+ compatible = "allwinner,sun20i-d1-analog-ldos";
+ reg = <0x2030348 0x4>;
+ nvmem-cells = <&bg_trim>;
+ nvmem-cell-names = "bg_trim";
+
+ reg_aldo: aldo {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_hpldo: hpldo {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ };
+ };
+
+...
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/allwinner,sun20i-d1-system-ldos.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner D1 System LDOs
+
+maintainers:
+ - Samuel Holland <samuel@sholland.org>
+
+description:
+ Allwinner D1 contains a pair of general-purpose LDOs which are designed to
+ supply power inside and outside the SoC. They are controlled by a register
+ within the system control MMIO space.
+
+properties:
+ compatible:
+ enum:
+ - allwinner,sun20i-d1-system-ldos
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ "^ldo[ab]$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+...

View File

@ -0,0 +1,294 @@
From ad842bfb2eb10a75050dd69145ca59de982eb0e9 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 17 Jul 2022 11:46:52 -0500
Subject: [PATCH 021/117] regulator: sun20i: Add support for Allwinner D1 LDOs
D1 contains two pairs of LDOs. Since they have similar bindings, and
they always exist together, put them in a single driver.
The analog LDOs are relatively boring, with a single linear range. Their
one quirk is that a bandgap reference must be calibrated for them to
produce the correct voltage.
The system LDOs have the complication that their voltage step is not an
integer, so a custom .list_voltage is needed to get the rounding right.
Series-changes: 2
- Use decimal numbers for .n_voltages instead of field widths
- Get the regmap from the parent device instead of a property/phandle
Series-changes: 3
- Adjust control flow in sun20i_regulator_get_regmap() for clarity
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/sun20i-regulator.c | 232 +++++++++++++++++++++++++++
3 files changed, 241 insertions(+)
create mode 100644 drivers/regulator/sun20i-regulator.c
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1280,6 +1280,14 @@ config REGULATOR_STW481X_VMMC
This driver supports the internal VMMC regulator in the STw481x
PMIC chips.
+config REGULATOR_SUN20I
+ tristate "Allwinner D1 internal LDOs"
+ depends on ARCH_SUNXI || COMPILE_TEST
+ depends on MFD_SYSCON && NVMEM
+ default ARCH_SUNXI
+ help
+ This driver supports the internal LDOs in the Allwinner D1 SoC.
+
config REGULATOR_SY7636A
tristate "Silergy SY7636A voltage regulator"
depends on MFD_SY7636A
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_REGULATOR_STM32_VREFBUF) +=
obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
+obj-$(CONFIG_REGULATOR_SUN20I) += sun20i-regulator.o
obj-$(CONFIG_REGULATOR_SY7636A) += sy7636a-regulator.o
obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
obj-$(CONFIG_REGULATOR_SY8824X) += sy8824x.o
--- /dev/null
+++ b/drivers/regulator/sun20i-regulator.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
+//
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define SUN20I_POWER_REG 0x348
+
+#define SUN20I_SYS_LDO_CTRL_REG 0x150
+
+struct sun20i_regulator_data {
+ int (*init)(struct device *dev,
+ struct regmap *regmap);
+ const struct regulator_desc *descs;
+ unsigned int ndescs;
+};
+
+static int sun20i_d1_analog_ldos_init(struct device *dev, struct regmap *regmap)
+{
+ u8 bg_trim;
+ int ret;
+
+ ret = nvmem_cell_read_u8(dev, "bg_trim", &bg_trim);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get bg_trim value\n");
+
+ /* The default value corresponds to 900 mV. */
+ if (!bg_trim)
+ bg_trim = 0x19;
+
+ return regmap_update_bits(regmap, SUN20I_POWER_REG,
+ GENMASK(7, 0), bg_trim);
+}
+
+static const struct regulator_ops sun20i_d1_analog_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_desc sun20i_d1_analog_ldo_descs[] = {
+ {
+ .name = "aldo",
+ .supply_name = "vdd33",
+ .of_match = "aldo",
+ .ops = &sun20i_d1_analog_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = 8,
+ .min_uV = 1650000,
+ .uV_step = 50000,
+ .vsel_reg = SUN20I_POWER_REG,
+ .vsel_mask = GENMASK(14, 12),
+ .enable_reg = SUN20I_POWER_REG,
+ .enable_mask = BIT(31),
+ },
+ {
+ .name = "hpldo",
+ .supply_name = "hpldoin",
+ .of_match = "hpldo",
+ .ops = &sun20i_d1_analog_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = 8,
+ .min_uV = 1650000,
+ .uV_step = 50000,
+ .vsel_reg = SUN20I_POWER_REG,
+ .vsel_mask = GENMASK(10, 8),
+ .enable_reg = SUN20I_POWER_REG,
+ .enable_mask = BIT(30),
+ },
+};
+
+static const struct sun20i_regulator_data sun20i_d1_analog_ldos = {
+ .init = sun20i_d1_analog_ldos_init,
+ .descs = sun20i_d1_analog_ldo_descs,
+ .ndescs = ARRAY_SIZE(sun20i_d1_analog_ldo_descs),
+};
+
+/* regulator_list_voltage_linear() modified for the non-integral uV_step. */
+static int sun20i_d1_system_ldo_list_voltage(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ const struct regulator_desc *desc = rdev->desc;
+ unsigned int uV;
+
+ if (selector >= desc->n_voltages)
+ return -EINVAL;
+
+ uV = desc->min_uV + (desc->uV_step * selector);
+
+ /* Produce correctly-rounded absolute voltages. */
+ return uV + ((selector + 1 + (desc->min_uV % 4)) / 3);
+}
+
+static const struct regulator_ops sun20i_d1_system_ldo_ops = {
+ .list_voltage = sun20i_d1_system_ldo_list_voltage,
+ .map_voltage = regulator_map_voltage_ascend,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_desc sun20i_d1_system_ldo_descs[] = {
+ {
+ .name = "ldoa",
+ .supply_name = "ldo-in",
+ .of_match = "ldoa",
+ .ops = &sun20i_d1_system_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = 32,
+ .min_uV = 1600000,
+ .uV_step = 13333, /* repeating */
+ .vsel_reg = SUN20I_SYS_LDO_CTRL_REG,
+ .vsel_mask = GENMASK(7, 0),
+ },
+ {
+ .name = "ldob",
+ .supply_name = "ldo-in",
+ .of_match = "ldob",
+ .ops = &sun20i_d1_system_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = 64,
+ .min_uV = 1166666,
+ .uV_step = 13333, /* repeating */
+ .vsel_reg = SUN20I_SYS_LDO_CTRL_REG,
+ .vsel_mask = GENMASK(15, 8),
+ },
+};
+
+static const struct sun20i_regulator_data sun20i_d1_system_ldos = {
+ .descs = sun20i_d1_system_ldo_descs,
+ .ndescs = ARRAY_SIZE(sun20i_d1_system_ldo_descs),
+};
+
+static const struct of_device_id sun20i_regulator_of_match[] = {
+ {
+ .compatible = "allwinner,sun20i-d1-analog-ldos",
+ .data = &sun20i_d1_analog_ldos,
+ },
+ {
+ .compatible = "allwinner,sun20i-d1-system-ldos",
+ .data = &sun20i_d1_system_ldos,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sun20i_regulator_of_match);
+
+static struct regmap *sun20i_regulator_get_regmap(struct device *dev)
+{
+ struct regmap *regmap;
+
+ /*
+ * First try the syscon interface. The system control device is not
+ * compatible with "syscon", so fall back to getting the regmap from
+ * its platform device. This is ugly, but required for devicetree
+ * backward compatibility.
+ */
+ regmap = syscon_node_to_regmap(dev->parent->of_node);
+ if (!IS_ERR(regmap))
+ return regmap;
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (regmap)
+ return regmap;
+
+ return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int sun20i_regulator_probe(struct platform_device *pdev)
+{
+ const struct sun20i_regulator_data *data;
+ struct device *dev = &pdev->dev;
+ struct regulator_config config;
+ struct regmap *regmap;
+ int ret;
+
+ data = of_device_get_match_data(dev);
+ if (!data)
+ return -EINVAL;
+
+ regmap = sun20i_regulator_get_regmap(dev);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap), "Failed to get regmap\n");
+
+ if (data->init) {
+ ret = data->init(dev, regmap);
+ if (ret)
+ return ret;
+ }
+
+ config = (struct regulator_config) {
+ .dev = dev,
+ .regmap = regmap,
+ };
+
+ for (unsigned int i = 0; i < data->ndescs; ++i) {
+ const struct regulator_desc *desc = &data->descs[i];
+ struct regulator_dev *rdev;
+
+ rdev = devm_regulator_register(dev, desc, &config);
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+static struct platform_driver sun20i_regulator_driver = {
+ .probe = sun20i_regulator_probe,
+ .driver = {
+ .name = "sun20i-regulator",
+ .of_match_table = sun20i_regulator_of_match,
+ },
+};
+module_platform_driver(sun20i_regulator_driver);
+
+MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
+MODULE_DESCRIPTION("Allwinner D1 internal LDO driver");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,68 @@
From 52c6979628d596018e9259767bff4def25e449dc Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Mon, 1 Aug 2022 23:57:19 -0500
Subject: [PATCH 022/117] dt-bindings: sram: sunxi-sram: Add optional
regulators child
Some sunxi SoCs have in-package regulators controlled by a register in
the system control MMIO block. Allow a child node for these regulators
in addition to SRAM child nodes.
Commit-changes: 2
- New patch for v2
Series-changes: 3
- Require the regulators node to have a unit address
- Reference the regulator schema from the SRAM controller schema
- Move the system LDOs example to the SRAM controller schema
- Reorder the patches so the example passes validation
Series-changes: 4
- Remove unevaluatedProperties from regulators schema reference
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../allwinner,sun4i-a10-system-control.yaml | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
--- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -56,6 +56,9 @@ properties:
ranges: true
patternProperties:
+ "^regulators@[0-9a-f]+$":
+ $ref: /schemas/regulator/allwinner,sun20i-d1-system-ldos.yaml#
+
"^sram@[a-z0-9]+":
type: object
@@ -130,3 +133,28 @@ examples:
};
};
};
+
+ - |
+ syscon@3000000 {
+ compatible = "allwinner,sun20i-d1-system-control";
+ reg = <0x3000000 0x1000>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulators@3000150 {
+ compatible = "allwinner,sun20i-d1-system-ldos";
+ reg = <0x3000150 0x4>;
+
+ reg_ldoa: ldoa {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_ldob: ldob {
+ regulator-name = "vcc-dram";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ };
+ };
+ };

View File

@ -0,0 +1,50 @@
From 1946ff7ee38c994ae3eb9968c5b51695c0df2cf7 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Tue, 2 Aug 2022 00:01:21 -0500
Subject: [PATCH 023/117] soc: sunxi: sram: Only iterate over SRAM children
Now that a "regulators" child is accepted by the controller binding, the
debugfs show routine must be explicitly limited to "sram" children.
Series-to: Liam Girdwood <lgirdwood@gmail.com>
Series-to: Mark Brown <broonie@kernel.org>
Series-to: Chen-Yu Tsai <wens@csie.org>
Series-to: Jernej Skrabec <jernej.skrabec@gmail.com>
Series-to: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Series-to: Rob Herring <robh+dt@kernel.org>
Commit-changes: 2
- New patch for v2
Series-version: 4
Cover-letter:
regulator: Add support for Allwinner D1 LDOs
This series adds bindings and a driver for the two pairs of LDOs
inside the Allwinner D1 SoC.
A binding and driver change is required for the SRAM controller, to
accept the regulators device as its child node. The new example in the
SRAM controller binding uses the compatible string added in this series:
https://lore.kernel.org/lkml/20220815041248.53268-1-samuel@sholland.org/
END
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/soc/sunxi/sunxi_sram.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -120,6 +120,9 @@ static int sunxi_sram_show(struct seq_fi
seq_puts(s, "--------------------\n\n");
for_each_child_of_node(sram_dev->of_node, sram_node) {
+ if (!of_node_name_eq(sram_node, "sram"))
+ continue;
+
sram_addr_p = of_get_address(sram_node, 0, NULL, NULL);
seq_printf(s, "sram@%08x\n",

View File

@ -0,0 +1,26 @@
From 25727569379b42593b55cfb743b7eff4cfa1cce2 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 14 Aug 2022 23:45:50 -0500
Subject: [PATCH 024/117] MAINTAINERS: Match the sun20i family of Allwinner
SoCs
Allwinner sunxi SoCs with a RISC-V CPU use the sun20i designator. Match
that pattern in addition to the designators for 32 and 64-bit ARM SoCs.
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1828,7 +1828,7 @@ F: drivers/pinctrl/sunxi/
F: drivers/soc/sunxi/
N: allwinner
N: sun[x456789]i
-N: sun50i
+N: sun[25]0i
ARM/Amlogic Meson SoC CLOCK FRAMEWORK
M: Neil Armstrong <neil.armstrong@linaro.org>

View File

@ -0,0 +1,27 @@
From 4ae663dbc373f5690581cee16d3667693eb9d73e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 16 May 2021 14:05:17 -0500
Subject: [PATCH 025/117] dt-bindings: riscv: Add T-HEAD C906 and C910
compatibles
The C906 and C910 are RISC-V CPU cores from T-HEAD Semiconductor.
Notably, the C906 core is used in the Allwinner D1 SoC.
Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
Documentation/devicetree/bindings/riscv/cpus.yaml | 2 ++
1 file changed, 2 insertions(+)
--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
+++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
@@ -39,6 +39,8 @@ properties:
- sifive,u5
- sifive,u7
- canaan,k210
+ - thead,c906
+ - thead,c910
- const: riscv
- items:
- enum:

View File

@ -0,0 +1,42 @@
From d0c24deb787a95515d355eea68e0402bfec77f75 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 17 Jul 2022 14:42:05 -0500
Subject: [PATCH 026/117] dt-bindings: vendor-prefixes: Add Allwinner D1 board
vendors
Some boards using the Allwinner D1 SoC are made by vendors not
previously documented.
Clockwork Tech LLC (https://www.clockworkpi.com/) manufactures the
ClockworkPi and DevTerm boards.
Beijing Widora Technology Co., Ltd. (https://mangopi.cc/) manufactures
the MangoPi family of boards.
Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
1 file changed, 4 insertions(+)
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -260,6 +260,8 @@ patternProperties:
description: Cirrus Logic, Inc.
"^cisco,.*":
description: Cisco Systems, Inc.
+ "^clockwork,.*":
+ description: Clockwork Tech LLC
"^cloudengines,.*":
description: Cloud Engines, Inc.
"^cnm,.*":
@@ -1424,6 +1426,8 @@ patternProperties:
description: Shenzhen whwave Electronics, Inc.
"^wi2wi,.*":
description: Wi2Wi, Inc.
+ "^widora,.*":
+ description: Beijing Widora Technology Co., Ltd.
"^wiligear,.*":
description: Wiligear, Ltd.
"^willsemi,.*":

View File

@ -0,0 +1,85 @@
From 4d7c04f210dd401f3560a7f53c78d6e058d182e2 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 29 Jun 2022 00:26:39 -0500
Subject: [PATCH 027/117] dt-bindings: riscv: Add Allwinner D1 board
compatibles
Several SoMs and boards are available that feature the Allwinner D1 SoC.
Document their compatible strings.
Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../devicetree/bindings/riscv/sunxi.yaml | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 Documentation/devicetree/bindings/riscv/sunxi.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/riscv/sunxi.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/riscv/sunxi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner RISC-V SoC-based boards
+
+maintainers:
+ - Chen-Yu Tsai <wens@csie.org>
+ - Jernej Skrabec <jernej.skrabec@gmail.com>
+ - Samuel Holland <samuel@sholland.org>
+
+description:
+ Allwinner RISC-V SoC-based boards
+
+properties:
+ $nodename:
+ const: '/'
+ compatible:
+ oneOf:
+ - description: Dongshan Nezha STU SoM
+ items:
+ - const: 100ask,dongshan-nezha-stu
+ - const: allwinner,sun20i-d1
+
+ - description: D1 Nezha board
+ items:
+ - const: allwinner,d1-nezha
+ - const: allwinner,sun20i-d1
+
+ - description: ClockworkPi R-01 SoM and v3.14 board
+ items:
+ - const: clockwork,r-01-clockworkpi-v3.14
+ - const: allwinner,sun20i-d1
+
+ - description: ClockworkPi R-01 SoM, v3.14 board, and DevTerm expansion
+ items:
+ - const: clockwork,r-01-devterm-v3.14
+ - const: clockwork,r-01-clockworkpi-v3.14
+ - const: allwinner,sun20i-d1
+
+ - description: Lichee RV SoM
+ items:
+ - const: sipeed,lichee-rv
+ - const: allwinner,sun20i-d1
+
+ - description: Carrier boards for the Lichee RV SoM
+ items:
+ - enum:
+ - sipeed,lichee-rv-86-panel-480p
+ - sipeed,lichee-rv-86-panel-720p
+ - sipeed,lichee-rv-dock
+ - const: sipeed,lichee-rv
+ - const: allwinner,sun20i-d1
+
+ - description: MangoPi MQ Pro board
+ items:
+ - const: widora,mangopi-mq-pro
+ - const: allwinner,sun20i-d1
+
+additionalProperties: true
+
+...

View File

@ -0,0 +1,936 @@
From 20d565fb9324b0d2791d10cb65560eddd2ef526e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Tue, 28 Jun 2022 23:20:33 -0500
Subject: [PATCH 028/117] riscv: dts: allwinner: Add the D1 SoC base devicetree
D1 is a SoC containing a single-core T-HEAD Xuantie C906 CPU, as well as
one HiFi 4 DSP. The SoC is based on a design that additionally contained
a pair of Cortex A7's. For that reason, some peripherals are duplicated.
This devicetree includes all of the peripherals that already have a
documented binding.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/Makefile | 1 +
arch/riscv/boot/dts/allwinner/Makefile | 1 +
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 900 +++++++++++++++++++
3 files changed, 902 insertions(+)
create mode 100644 arch/riscv/boot/dts/allwinner/Makefile
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+subdir-y += allwinner
subdir-y += sifive
subdir-y += starfive
subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/Makefile
@@ -0,0 +1 @@
+# SPDX-License-Identifier: GPL-2.0
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -0,0 +1,900 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
+#include <dt-bindings/clock/sun20i-d1-ccu.h>
+#include <dt-bindings/clock/sun20i-d1-r-ccu.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+#include <dt-bindings/reset/sun20i-d1-ccu.h>
+#include <dt-bindings/reset/sun20i-d1-r-ccu.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ timebase-frequency = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "thead,c906", "riscv";
+ device_type = "cpu";
+ reg = <0>;
+ clocks = <&ccu CLK_RISCV>;
+ clock-frequency = <24000000>;
+ d-cache-block-size = <64>;
+ d-cache-sets = <256>;
+ d-cache-size = <32768>;
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <32768>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdc";
+ #cooling-cells = <2>;
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ de: display-engine {
+ compatible = "allwinner,sun20i-d1-display-engine";
+ allwinner,pipelines = <&mixer0>, <&mixer1>;
+ status = "disabled";
+ };
+
+ osc24M: osc24M-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
+ #clock-cells = <0>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ ranges;
+ interrupt-parent = <&plic>;
+ dma-noncoherent;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ dsp_wdt: watchdog@1700400 {
+ compatible = "allwinner,sun20i-d1-wdt";
+ reg = <0x1700400 0x20>;
+ interrupts = <138 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ status = "reserved";
+ };
+
+ pio: pinctrl@2000000 {
+ compatible = "allwinner,sun20i-d1-pinctrl";
+ reg = <0x2000000 0x800>;
+ interrupts = <85 IRQ_TYPE_LEVEL_HIGH>,
+ <87 IRQ_TYPE_LEVEL_HIGH>,
+ <89 IRQ_TYPE_LEVEL_HIGH>,
+ <91 IRQ_TYPE_LEVEL_HIGH>,
+ <93 IRQ_TYPE_LEVEL_HIGH>,
+ <95 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_APB0>,
+ <&osc24M>,
+ <&rtc CLK_OSC32K>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ interrupt-controller;
+ #gpio-cells = <3>;
+ #interrupt-cells = <3>;
+
+ /omit-if-no-ref/
+ i2c0_pb10_pins: i2c0-pb10-pins {
+ pins = "PB10", "PB11";
+ function = "i2c0";
+ };
+
+ /omit-if-no-ref/
+ i2c2_pb0_pins: i2c2-pb0-pins {
+ pins = "PB0", "PB1";
+ function = "i2c2";
+ };
+
+ /omit-if-no-ref/
+ lcd_rgb666_pins: lcd-rgb666-pins {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+ "PD6", "PD7", "PD8", "PD9", "PD10", "PD11",
+ "PD12", "PD13", "PD14", "PD15", "PD16", "PD17",
+ "PD18", "PD19", "PD20", "PD21";
+ function = "lcd0";
+ };
+
+ /omit-if-no-ref/
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
+ function = "mmc0";
+ };
+
+ /omit-if-no-ref/
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5";
+ function = "mmc1";
+ };
+
+ /omit-if-no-ref/
+ mmc2_pins: mmc2-pins {
+ pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7";
+ function = "mmc2";
+ };
+
+ /omit-if-no-ref/
+ rgmii_pe_pins: rgmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9",
+ "PE11", "PE12", "PE13", "PE14", "PE15";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ rmii_pe_pins: rmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ uart0_pb8_pins: uart0-pb8-pins {
+ pins = "PB8", "PB9";
+ function = "uart0";
+ };
+
+ /omit-if-no-ref/
+ uart1_pg6_pins: uart1-pg6-pins {
+ pins = "PG6", "PG7";
+ function = "uart1";
+ };
+
+ /omit-if-no-ref/
+ uart1_pg8_rts_cts_pins: uart1-pg8-rts-cts-pins {
+ pins = "PG8", "PG9";
+ function = "uart1";
+ };
+ };
+
+ ccu: clock-controller@2001000 {
+ compatible = "allwinner,sun20i-d1-ccu";
+ reg = <0x2001000 0x1000>;
+ clocks = <&osc24M>,
+ <&rtc CLK_OSC32K>,
+ <&rtc CLK_IOSC>;
+ clock-names = "hosc", "losc", "iosc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ lradc: keys@2009800 {
+ compatible = "allwinner,sun20i-d1-lradc",
+ "allwinner,sun50i-r329-lradc";
+ reg = <0x2009800 0x400>;
+ interrupts = <77 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_LRADC>;
+ resets = <&ccu RST_BUS_LRADC>;
+ status = "disabled";
+ };
+
+ codec: audio-codec@2030000 {
+ compatible = "simple-mfd", "syscon";
+ reg = <0x2030000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulators@2030348 {
+ compatible = "allwinner,sun20i-d1-analog-ldos";
+ reg = <0x2030348 0x4>;
+ nvmem-cells = <&bg_trim>;
+ nvmem-cell-names = "bg_trim";
+
+ reg_aldo: aldo {
+ };
+
+ reg_hpldo: hpldo {
+ };
+ };
+ };
+
+ i2s0: i2s@2032000 {
+ compatible = "allwinner,sun20i-d1-i2s",
+ "allwinner,sun50i-r329-i2s";
+ reg = <0x2032000 0x1000>;
+ interrupts = <42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S0>,
+ <&ccu CLK_I2S0>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S0>;
+ dmas = <&dma 3>, <&dma 3>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ i2s1: i2s@2033000 {
+ compatible = "allwinner,sun20i-d1-i2s",
+ "allwinner,sun50i-r329-i2s";
+ reg = <0x2033000 0x1000>;
+ interrupts = <43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S1>,
+ <&ccu CLK_I2S1>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S1>;
+ dmas = <&dma 4>, <&dma 4>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ i2s2: i2s@2034000 {
+ compatible = "allwinner,sun20i-d1-i2s",
+ "allwinner,sun50i-r329-i2s";
+ reg = <0x2034000 0x1000>;
+ interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S2>,
+ <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S2>;
+ dmas = <&dma 5>, <&dma 5>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ timer: timer@2050000 {
+ compatible = "allwinner,sun20i-d1-timer",
+ "allwinner,sun8i-a23-timer";
+ reg = <0x2050000 0xa0>;
+ interrupts = <75 IRQ_TYPE_LEVEL_HIGH>,
+ <76 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
+ };
+
+ wdt: watchdog@20500a0 {
+ compatible = "allwinner,sun20i-d1-wdt-reset",
+ "allwinner,sun20i-d1-wdt";
+ reg = <0x20500a0 0x20>;
+ interrupts = <79 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ status = "reserved";
+ };
+
+ uart0: serial@2500000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500000 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART0>;
+ resets = <&ccu RST_BUS_UART0>;
+ dmas = <&dma 14>, <&dma 14>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart1: serial@2500400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500400 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART1>;
+ resets = <&ccu RST_BUS_UART1>;
+ dmas = <&dma 15>, <&dma 15>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart2: serial@2500800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500800 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART2>;
+ resets = <&ccu RST_BUS_UART2>;
+ dmas = <&dma 16>, <&dma 16>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart3: serial@2500c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500c00 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART3>;
+ resets = <&ccu RST_BUS_UART3>;
+ dmas = <&dma 17>, <&dma 17>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart4: serial@2501000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2501000 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART4>;
+ resets = <&ccu RST_BUS_UART4>;
+ dmas = <&dma 18>, <&dma 18>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart5: serial@2501400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2501400 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART5>;
+ resets = <&ccu RST_BUS_UART5>;
+ dmas = <&dma 19>, <&dma 19>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ i2c0: i2c@2502000 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502000 0x400>;
+ interrupts = <25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ dmas = <&dma 43>, <&dma 43>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@2502400 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502400 0x400>;
+ interrupts = <26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ dmas = <&dma 44>, <&dma 44>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@2502800 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502800 0x400>;
+ interrupts = <27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ dmas = <&dma 45>, <&dma 45>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c@2502c00 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502c00 0x400>;
+ interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C3>;
+ resets = <&ccu RST_BUS_I2C3>;
+ dmas = <&dma 46>, <&dma 46>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun20i-d1-system-control";
+ reg = <0x3000000 0x1000>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulators@3000150 {
+ compatible = "allwinner,sun20i-d1-system-ldos";
+ reg = <0x3000150 0x4>;
+
+ reg_ldoa: ldoa {
+ };
+
+ reg_ldob: ldob {
+ };
+ };
+ };
+
+ dma: dma-controller@3002000 {
+ compatible = "allwinner,sun20i-d1-dma";
+ reg = <0x3002000 0x1000>;
+ interrupts = <66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+ clock-names = "bus", "mbus";
+ resets = <&ccu RST_BUS_DMA>;
+ dma-channels = <16>;
+ dma-requests = <48>;
+ #dma-cells = <1>;
+ };
+
+ sid: efuse@3006000 {
+ compatible = "allwinner,sun20i-d1-sid";
+ reg = <0x3006000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ths_calib: ths-calib@14 {
+ reg = <0x14 0x4>;
+ };
+
+ bg_trim: bg-trim@28 {
+ reg = <0x28 0x4>;
+ bits = <16 8>;
+ };
+ };
+
+ mbus: dram-controller@3102000 {
+ compatible = "allwinner,sun20i-d1-mbus";
+ reg = <0x3102000 0x1000>,
+ <0x3103000 0x1000>;
+ reg-names = "mbus", "dram";
+ interrupts = <59 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_MBUS>,
+ <&ccu CLK_DRAM>,
+ <&ccu CLK_BUS_DRAM>;
+ clock-names = "mbus", "dram", "bus";
+ dma-ranges = <0 0x40000000 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interconnect-cells = <1>;
+ };
+
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4020000 0x1000>;
+ interrupts = <56 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ cap-sd-highspeed;
+ max-frequency = <150000000>;
+ no-mmc;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4021000 0x1000>;
+ interrupts = <57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ cap-sd-highspeed;
+ max-frequency = <150000000>;
+ no-mmc;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun20i-d1-emmc",
+ "allwinner,sun50i-a100-emmc";
+ reg = <0x4022000 0x1000>;
+ interrupts = <58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ cap-mmc-highspeed;
+ max-frequency = <150000000>;
+ mmc-ddr-1_8v;
+ mmc-ddr-3_3v;
+ no-sd;
+ no-sdio;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ usb_otg: usb@4100000 {
+ compatible = "allwinner,sun20i-d1-musb",
+ "allwinner,sun8i-a33-musb";
+ reg = <0x4100000 0x400>;
+ interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ extcon = <&usbphy 0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ usbphy: phy@4100400 {
+ compatible = "allwinner,sun20i-d1-usb-phy";
+ reg = <0x4100400 0x100>,
+ <0x4101800 0x100>,
+ <0x4200800 0x100>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1";
+ clocks = <&osc24M>,
+ <&osc24M>;
+ clock-names = "usb0_phy",
+ "usb1_phy";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>;
+ reset-names = "usb0_reset",
+ "usb1_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@4101000 {
+ compatible = "allwinner,sun20i-d1-ehci",
+ "generic-ehci";
+ reg = <0x4101000 0x100>;
+ interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_BUS_EHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>,
+ <&ccu RST_BUS_EHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@4101400 {
+ compatible = "allwinner,sun20i-d1-ohci",
+ "generic-ohci";
+ reg = <0x4101400 0x100>;
+ interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci1: usb@4200000 {
+ compatible = "allwinner,sun20i-d1-ehci",
+ "generic-ehci";
+ reg = <0x4200000 0x100>;
+ interrupts = <49 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_BUS_EHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>,
+ <&ccu RST_BUS_EHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@4200400 {
+ compatible = "allwinner,sun20i-d1-ohci",
+ "generic-ohci";
+ reg = <0x4200400 0x100>;
+ interrupts = <50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ emac: ethernet@4500000 {
+ compatible = "allwinner,sun20i-d1-emac",
+ "allwinner,sun50i-a64-emac";
+ reg = <0x4500000 0x10000>;
+ interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ syscon = <&syscon>;
+ status = "disabled";
+
+ mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ display_clocks: clock-controller@5000000 {
+ compatible = "allwinner,sun20i-d1-de2-clk",
+ "allwinner,sun50i-h5-de2-clk";
+ reg = <0x5000000 0x10000>;
+ clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ mixer0: mixer@5100000 {
+ compatible = "allwinner,sun20i-d1-de2-mixer-0";
+ reg = <0x5100000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER0>,
+ <&display_clocks CLK_MIXER0>;
+ clock-names = "bus", "mod";
+ resets = <&display_clocks RST_MIXER0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port@1 {
+ reg = <1>;
+
+ mixer0_out_tcon_top_mixer0: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+ };
+ };
+ };
+ };
+
+ mixer1: mixer@5200000 {
+ compatible = "allwinner,sun20i-d1-de2-mixer-1";
+ reg = <0x5200000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER1>,
+ <&display_clocks CLK_MIXER1>;
+ clock-names = "bus", "mod";
+ resets = <&display_clocks RST_MIXER1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer1_out: port@1 {
+ reg = <1>;
+
+ mixer1_out_tcon_top_mixer1: endpoint {
+ remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
+ };
+ };
+ };
+ };
+
+ tcon_top: tcon-top@5460000 {
+ compatible = "allwinner,sun20i-d1-tcon-top";
+ reg = <0x5460000 0x1000>;
+ clocks = <&ccu CLK_BUS_DPSS_TOP>,
+ <&ccu CLK_TCON_TV>,
+ <&ccu CLK_TVE>,
+ <&ccu CLK_TCON_LCD0>;
+ clock-names = "bus", "tcon-tv0", "tve0", "dsi";
+ clock-output-names = "tcon-top-tv0", "tcon-top-dsi";
+ resets = <&ccu RST_BUS_DPSS_TOP>;
+ #clock-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_in: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_in_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer0_out: port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer0>;
+ };
+
+ tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer1_in: port@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer1_in_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&mixer1_out_tcon_top_mixer1>;
+ };
+ };
+
+ tcon_top_mixer1_out: port@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer1>;
+ };
+
+ tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
+ };
+ };
+
+ tcon_top_hdmi_in: port@4 {
+ reg = <4>;
+
+ tcon_top_hdmi_in_tcon_tv0: endpoint {
+ remote-endpoint = <&tcon_tv0_out_tcon_top_hdmi>;
+ };
+ };
+
+ tcon_top_hdmi_out: port@5 {
+ reg = <5>;
+ };
+ };
+ };
+
+ tcon_lcd0: lcd-controller@5461000 {
+ compatible = "allwinner,sun20i-d1-tcon-lcd";
+ reg = <0x5461000 0x1000>;
+ interrupts = <106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_LCD0>,
+ <&ccu CLK_TCON_LCD0>;
+ clock-names = "ahb", "tcon-ch0";
+ clock-output-names = "tcon-pixel-clock";
+ resets = <&ccu RST_BUS_TCON_LCD0>,
+ <&ccu RST_BUS_LVDS0>;
+ reset-names = "lcd", "lvds";
+ #clock-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_in: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_lcd0>;
+ };
+
+ tcon_lcd0_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_lcd0>;
+ };
+ };
+
+ tcon_lcd0_out: port@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ tcon_tv0: lcd-controller@5470000 {
+ compatible = "allwinner,sun20i-d1-tcon-tv";
+ reg = <0x5470000 0x1000>;
+ interrupts = <107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_TV>,
+ <&tcon_top CLK_TCON_TOP_TV0>;
+ clock-names = "ahb", "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON_TV>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv0_in: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
+ };
+
+ tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
+ };
+ };
+
+ tcon_tv0_out: port@1 {
+ reg = <1>;
+
+ tcon_tv0_out_tcon_top_hdmi: endpoint {
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
+ };
+ };
+ };
+ };
+
+ riscv_wdt: watchdog@6011000 {
+ compatible = "allwinner,sun20i-d1-wdt";
+ reg = <0x6011000 0x20>;
+ interrupts = <147 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ };
+
+ r_ccu: clock-controller@7010000 {
+ compatible = "allwinner,sun20i-d1-r-ccu";
+ reg = <0x7010000 0x400>;
+ clocks = <&osc24M>,
+ <&rtc CLK_OSC32K>,
+ <&rtc CLK_IOSC>,
+ <&ccu CLK_PLL_PERIPH0_DIV3>;
+ clock-names = "hosc", "losc", "iosc", "pll-periph";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ rtc: rtc@7090000 {
+ compatible = "allwinner,sun20i-d1-rtc",
+ "allwinner,sun50i-r329-rtc";
+ reg = <0x7090000 0x400>;
+ interrupts = <160 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_BUS_R_RTC>,
+ <&osc24M>,
+ <&r_ccu CLK_R_AHB>;
+ clock-names = "bus", "hosc", "ahb";
+ #clock-cells = <1>;
+ };
+
+ plic: interrupt-controller@10000000 {
+ compatible = "allwinner,sun20i-d1-plic",
+ "thead,c900-plic";
+ reg = <0x10000000 0x4000000>;
+ interrupts-extended = <&cpu0_intc 11>,
+ <&cpu0_intc 9>;
+ interrupt-controller;
+ riscv,ndev = <176>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ };
+ };
+};

View File

@ -0,0 +1,263 @@
From 5da27190c54b7a51062786eb01246f6f4cf2ba98 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Tue, 28 Jun 2022 23:31:16 -0500
Subject: [PATCH 029/117] riscv: dts: allwinner: Add Allwinner D1 Nezha
devicetree
"D1 Nezha" is Allwinner's first-party development board for the D1 SoC.
It was shipped with 512M, 1G, or 2G of DDR3. It supports onboard audio,
HDMI, gigabit Ethernet, WiFi and Bluetooth, USB 2.0 host and OTG ports,
plus low-speed I/O from the SoC and a GPIO expander chip.
Most other D1 boards copied the Nezha's power tree, with the 1.8V rail
powered by the SoCs internal LDOA, analog domains powered by ALDO, and
the rest of the board powered by always-on fixed regulators. Some (but
not all) boards also copied the PWM CPU regulator. To avoid duplication,
factor out the out the regulator references that are common across all
known boards.
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Conor Dooley <conor.dooley@microchip.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/Makefile | 1 +
.../sun20i-d1-common-regulators.dtsi | 51 ++++++
.../boot/dts/allwinner/sun20i-d1-nezha.dts | 171 ++++++++++++++++++
3 files changed, 223 insertions(+)
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-common-regulators.dtsi
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
--- a/arch/riscv/boot/dts/allwinner/Makefile
+++ b/arch/riscv/boot/dts/allwinner/Makefile
@@ -1 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-nezha.dtb
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-common-regulators.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+/ {
+ reg_vcc: vcc {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_vcc_3v3: vcc-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&reg_vcc>;
+ };
+};
+
+&lradc {
+ vref-supply = <&reg_aldo>;
+};
+
+&pio {
+ vcc-pb-supply = <&reg_vcc_3v3>;
+ vcc-pc-supply = <&reg_vcc_3v3>;
+ vcc-pd-supply = <&reg_vcc_3v3>;
+ vcc-pe-supply = <&reg_vcc_3v3>;
+ vcc-pf-supply = <&reg_vcc_3v3>;
+ vcc-pg-supply = <&reg_vcc_3v3>;
+};
+
+&reg_aldo {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vdd33-supply = <&reg_vcc_3v3>;
+};
+
+&reg_hpldo {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ hpldoin-supply = <&reg_vcc_3v3>;
+};
+
+&reg_ldoa {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ ldo-in-supply = <&reg_vcc_3v3>;
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "sun20i-d1.dtsi"
+#include "sun20i-d1-common-regulators.dtsi"
+
+/ {
+ model = "Allwinner D1 Nezha";
+ compatible = "allwinner,d1-nezha", "allwinner,sun20i-d1";
+
+ aliases {
+ ethernet0 = &emac;
+ ethernet1 = &xr829;
+ mmc0 = &mmc0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reg_usbvbus: usbvbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usbvbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
+ enable-active-high;
+ vin-supply = <&reg_vcc>;
+ };
+
+ /*
+ * This regulator is PWM-controlled, but the PWM controller is not
+ * yet supported, so fix the regulator to its default voltage.
+ */
+ reg_vdd_cpu: vdd-cpu {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&reg_vcc>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpu>;
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&emac {
+ pinctrl-0 = <&rgmii_pe_pins>;
+ pinctrl-names = "default";
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii-id";
+ phy-supply = <&reg_vcc_3v3>;
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-0 = <&i2c2_pb0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ pcf8574a: gpio@38 {
+ compatible = "nxp,pcf8574a";
+ reg = <0x38>;
+ interrupt-parent = <&pio>;
+ interrupts = <1 2 IRQ_TYPE_LEVEL_LOW>; /* PB2 */
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+};
+
+&lradc {
+ status = "okay";
+
+ button-160 {
+ label = "OK";
+ linux,code = <KEY_OK>;
+ channel = <0>;
+ voltage = <160000>;
+ };
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&mmc0 {
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+ disable-wp;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&mmc1 {
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ xr829: wifi@1 {
+ reg = <1>;
+ };
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb8_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart1 {
+ uart-has-rtscts;
+ pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ /* XR829 bluetooth is connected here */
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 3 21 GPIO_ACTIVE_HIGH>; /* PD21 */
+ usb0_vbus_det-gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
+ usb0_vbus-supply = <&reg_usbvbus>;
+ usb1_vbus-supply = <&reg_vcc>;
+ status = "okay";
+};

View File

@ -0,0 +1,344 @@
From 3bf76e93011425ed64a69c462b9959ed2a8ccf46 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 29 Jun 2022 00:13:50 -0500
Subject: [PATCH 030/117] riscv: dts: allwinner: Add Sipeed Lichee RV
devicetrees
Sipeed manufactures a "Lichee RV" system-on-module, which provides a
minimal working system on its own, as well as a few carrier boards. The
"Dock" board provides audio, USB, and WiFi. The "86 Panel" additionally
provides 100M Ethernet and a built-in display panel.
The 86 Panel repurposes the USB ID and VBUS detection GPIOs for its RGB
panel interface, since the USB OTG port is inaccessible inside the case.
Co-developed-by: Jisheng Zhang <jszhang@kernel.org>
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/Makefile | 4 +
.../sun20i-d1-lichee-rv-86-panel-480p.dts | 29 ++++++
.../sun20i-d1-lichee-rv-86-panel-720p.dts | 10 ++
.../sun20i-d1-lichee-rv-86-panel.dtsi | 92 +++++++++++++++++++
.../allwinner/sun20i-d1-lichee-rv-dock.dts | 74 +++++++++++++++
.../dts/allwinner/sun20i-d1-lichee-rv.dts | 84 +++++++++++++++++
6 files changed, 293 insertions(+)
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-720p.dts
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts
--- a/arch/riscv/boot/dts/allwinner/Makefile
+++ b/arch/riscv/boot/dts/allwinner/Makefile
@@ -1,2 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-480p.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-720p.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-dock.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-nezha.dtb
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+#include "sun20i-d1-lichee-rv-86-panel.dtsi"
+
+/ {
+ model = "Sipeed Lichee RV 86 Panel (480p)";
+ compatible = "sipeed,lichee-rv-86-panel-480p", "sipeed,lichee-rv",
+ "allwinner,sun20i-d1";
+};
+
+&i2c2 {
+ pinctrl-0 = <&i2c2_pb0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ touchscreen@48 {
+ compatible = "focaltech,ft6236";
+ reg = <0x48>;
+ interrupt-parent = <&pio>;
+ interrupts = <6 14 IRQ_TYPE_LEVEL_LOW>; /* PG14 */
+ iovcc-supply = <&reg_vcc_3v3>;
+ reset-gpios = <&pio 6 15 GPIO_ACTIVE_LOW>; /* PG15 */
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <480>;
+ vcc-supply = <&reg_vcc_3v3>;
+ wakeup-source;
+ };
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-720p.dts
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+#include "sun20i-d1-lichee-rv-86-panel.dtsi"
+
+/ {
+ model = "Sipeed Lichee RV 86 Panel (720p)";
+ compatible = "sipeed,lichee-rv-86-panel-720p", "sipeed,lichee-rv",
+ "allwinner,sun20i-d1";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+#include "sun20i-d1-lichee-rv.dts"
+
+/ {
+ aliases {
+ ethernet0 = &emac;
+ ethernet1 = &xr829;
+ };
+
+ /* PC1 is repurposed as BT_WAKE_AP */
+ /delete-node/ leds;
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&ccu CLK_FANOUT1>;
+ clock-names = "ext_clock";
+ reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
+ assigned-clocks = <&ccu CLK_FANOUT1>;
+ assigned-clock-rates = <32768>;
+ pinctrl-0 = <&clk_pg11_pin>;
+ pinctrl-names = "default";
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&emac {
+ pinctrl-0 = <&rmii_pe_pins>;
+ pinctrl-names = "default";
+ phy-handle = <&ext_rmii_phy>;
+ phy-mode = "rmii";
+ phy-supply = <&reg_vcc_3v3>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ reset-gpios = <&pio 4 16 GPIO_ACTIVE_LOW>; /* PE16 */
+ };
+};
+
+&mmc1 {
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ xr829: wifi@1 {
+ reg = <1>;
+ };
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ clk_pg11_pin: clk-pg11-pin {
+ pins = "PG11";
+ function = "clk";
+ };
+};
+
+&uart1 {
+ uart-has-rtscts;
+ pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ /* XR829 bluetooth is connected here */
+};
+
+&usb_otg {
+ status = "disabled";
+};
+
+&usbphy {
+ /* PD20 and PD21 are repurposed for the LCD panel */
+ /delete-property/ usb0_id_det-gpios;
+ /delete-property/ usb0_vbus_det-gpios;
+ usb1_vbus-supply = <&reg_vcc>;
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+#include <dt-bindings/input/input.h>
+
+#include "sun20i-d1-lichee-rv.dts"
+
+/ {
+ model = "Sipeed Lichee RV Dock";
+ compatible = "sipeed,lichee-rv-dock", "sipeed,lichee-rv",
+ "allwinner,sun20i-d1";
+
+ aliases {
+ ethernet1 = &rtl8723ds;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&lradc {
+ status = "okay";
+
+ button-220 {
+ label = "OK";
+ linux,code = <KEY_OK>;
+ channel = <0>;
+ voltage = <220000>;
+ };
+};
+
+&mmc1 {
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ rtl8723ds: wifi@1 {
+ reg = <1>;
+ };
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&uart1 {
+ uart-has-rtscts;
+ pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ bluetooth {
+ compatible = "realtek,rtl8723ds-bt";
+ device-wake-gpios = <&pio 6 15 GPIO_ACTIVE_HIGH>; /* PG16 */
+ enable-gpios = <&pio 6 18 GPIO_ACTIVE_HIGH>; /* PG18 */
+ host-wake-gpios = <&pio 6 17 GPIO_ACTIVE_HIGH>; /* PG17 */
+ };
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_vcc>;
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+#include "sun20i-d1.dtsi"
+#include "sun20i-d1-common-regulators.dtsi"
+
+/ {
+ model = "Sipeed Lichee RV";
+ compatible = "sipeed,lichee-rv", "allwinner,sun20i-d1";
+
+ aliases {
+ mmc0 = &mmc0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&pio 2 1 GPIO_ACTIVE_HIGH>; /* PC1 */
+ };
+ };
+
+ reg_vdd_cpu: vdd-cpu {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ vin-supply = <&reg_vcc>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpu>;
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ disable-wp;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb8_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 3 21 GPIO_ACTIVE_HIGH>; /* PD21 */
+ usb0_vbus_det-gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
+ usb0_vbus-supply = <&reg_vcc>;
+ status = "okay";
+};

View File

@ -0,0 +1,159 @@
From 3cf55c25453517960d72b56d1ba8f12840b1990e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Jul 2022 17:43:17 -0500
Subject: [PATCH 031/117] riscv: dts: allwinner: Add MangoPi MQ Pro devicetree
The MangoPi MQ Pro is a tiny SBC with a layout compatible to the
Raspberry Pi Zero. It includes the Allwinner D1 SoC, 512M or 1G of DDR3,
and an RTL8723DS-based WiFi/Bluetooth module.
The board also exposes GPIO Port E via a connector on the end of the
board, which can support either a camera or an RMII Ethernet PHY. The
additional regulators supply that connector.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/Makefile | 1 +
.../allwinner/sun20i-d1-mangopi-mq-pro.dts | 128 ++++++++++++++++++
2 files changed, 129 insertions(+)
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts
--- a/arch/riscv/boot/dts/allwinner/Makefile
+++ b/arch/riscv/boot/dts/allwinner/Makefile
@@ -3,4 +3,5 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-li
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-720p.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-dock.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-mangopi-mq-pro.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-nezha.dtb
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "sun20i-d1.dtsi"
+#include "sun20i-d1-common-regulators.dtsi"
+
+/ {
+ model = "MangoPi MQ Pro";
+ compatible = "widora,mangopi-mq-pro", "allwinner,sun20i-d1";
+
+ aliases {
+ ethernet0 = &rtl8723ds;
+ mmc0 = &mmc0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reg_avdd2v8: avdd2v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "avdd2v8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ vin-supply = <&reg_vcc_3v3>;
+ };
+
+ reg_dvdd: dvdd {
+ compatible = "regulator-fixed";
+ regulator-name = "dvdd";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ vin-supply = <&reg_vcc_3v3>;
+ };
+
+ reg_vdd_cpu: vdd-cpu {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&reg_vcc>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pio 6 17 GPIO_ACTIVE_LOW>; /* PG17 */
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpu>;
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&mmc0 {
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+ disable-wp;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&mmc1 {
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ rtl8723ds: wifi@1 {
+ reg = <1>;
+ interrupt-parent = <&pio>;
+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 */
+ interrupt-names = "host-wake";
+ };
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ vcc-pe-supply = <&reg_avdd2v8>;
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb8_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart1 {
+ uart-has-rtscts;
+ pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ bluetooth {
+ compatible = "realtek,rtl8723ds-bt";
+ device-wake-gpios = <&pio 6 18 GPIO_ACTIVE_HIGH>; /* PG18 */
+ enable-gpios = <&pio 6 15 GPIO_ACTIVE_HIGH>; /* PG15 */
+ host-wake-gpios = <&pio 6 14 GPIO_ACTIVE_HIGH>; /* PG14 */
+ };
+};
+
+&usb_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_vbus-supply = <&reg_vcc>;
+ status = "okay";
+};

View File

@ -0,0 +1,146 @@
From 1f26c90ac9cbb60ff315c552368a3bca16562e51 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 10 Jul 2022 11:24:42 -0500
Subject: [PATCH 032/117] riscv: dts: allwinner: Add Dongshan Nezha STU
devicetree
The 100ask Dongshan Nezha STU is a system-on-module that can be used
standalone or with a carrier board. The SoM provides gigabit Ethernet,
HDMI, a USB peripheral port, and WiFi/Bluetooth via an RTL8723DS chip.
The "DIY" carrier board exposes almost every pin from the D1 SoC to 0.1"
headers, but contains no digital circuitry, so it does not have its own
devicetree.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/Makefile | 1 +
.../sun20i-d1-dongshan-nezha-stu.dts | 114 ++++++++++++++++++
2 files changed, 115 insertions(+)
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts
--- a/arch/riscv/boot/dts/allwinner/Makefile
+++ b/arch/riscv/boot/dts/allwinner/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-dongshan-nezha-stu.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-480p.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-720p.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-dock.dtb
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+#include "sun20i-d1.dtsi"
+#include "sun20i-d1-common-regulators.dtsi"
+
+/ {
+ model = "Dongshan Nezha STU";
+ compatible = "100ask,dongshan-nezha-stu", "allwinner,sun20i-d1";
+
+ aliases {
+ ethernet0 = &emac;
+ mmc0 = &mmc0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&pio 2 1 GPIO_ACTIVE_HIGH>; /* PC1 */
+ };
+ };
+
+ reg_usbvbus: usbvbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usbvbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
+ enable-active-high;
+ vin-supply = <&reg_vcc>;
+ };
+
+ /*
+ * This regulator is PWM-controlled, but the PWM controller is not
+ * yet supported, so fix the regulator to its default voltage.
+ */
+ reg_vdd_cpu: vdd-cpu {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&reg_vcc>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpu>;
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&emac {
+ pinctrl-0 = <&rgmii_pe_pins>;
+ pinctrl-names = "default";
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii-id";
+ phy-supply = <&reg_vcc_3v3>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ disable-wp;
+ vmmc-supply = <&reg_vcc_3v3>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb8_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 3 21 GPIO_ACTIVE_HIGH>; /* PD21 */
+ usb0_vbus_det-gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
+ usb0_vbus-supply = <&reg_usbvbus>;
+ status = "okay";
+};

View File

@ -0,0 +1,322 @@
From 11f692c6b009f36b9a91d5ceb5998ae15e57f18c Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 10 Jul 2022 23:43:49 -0500
Subject: [PATCH 033/117] riscv: dts: allwinner: Add ClockworkPi and DevTerm
devicetrees
Clockwork Tech manufactures several SoMs for their RasPi CM3-compatible
"ClockworkPi" mainboard. Their R-01 SoM features the Allwinner D1 SoC.
The R-01 contains only the CPU, DRAM, and always-on voltage regulation;
it does not merit a separate devicetree.
The ClockworkPi mainboard features analog audio, a MIPI-DSI panel, USB
host and peripheral ports, an Ampak AP6256 WiFi/Bluetooth module, and an
X-Powers AXP228 PMIC for managing a Li-ion battery.
The DevTerm is a complete system which extends the ClockworkPi mainboard
with a pair of expansion boards. These expansion boards provide a fan, a
keyboard, speakers, and a thermal printer.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/Makefile | 2 +
.../allwinner/sun20i-d1-clockworkpi-v3.14.dts | 242 ++++++++++++++++++
.../dts/allwinner/sun20i-d1-devterm-v3.14.dts | 37 +++
3 files changed, 281 insertions(+)
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
--- a/arch/riscv/boot/dts/allwinner/Makefile
+++ b/arch/riscv/boot/dts/allwinner/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-clockworkpi-v3.14.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-devterm-v3.14.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-dongshan-nezha-stu.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-480p.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-720p.dtb
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "sun20i-d1.dtsi"
+#include "sun20i-d1-common-regulators.dtsi"
+
+/ {
+ model = "ClockworkPi v3.14 (R-01)";
+ compatible = "clockwork,r-01-clockworkpi-v3.14", "allwinner,sun20i-d1";
+
+ aliases {
+ ethernet0 = &ap6256;
+ mmc0 = &mmc0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ /*
+ * This regulator is PWM-controlled, but the PWM controller is not
+ * yet supported, so fix the regulator to its default voltage.
+ */
+ reg_vdd_cpu: vdd-cpu {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&reg_vcc>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pio 6 11 GPIO_ACTIVE_LOW>; /* PG11/GPIO3 */
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpu>;
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-0 = <&i2c0_pb10_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ axp221: pmic@34 {
+ compatible = "x-powers,axp228", "x-powers,axp221";
+ reg = <0x34>;
+ interrupt-parent = <&pio>;
+ interrupts = <4 9 IRQ_TYPE_LEVEL_LOW>; /* PE9/GPIO2 */
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ ac_power_supply: ac-power {
+ compatible = "x-powers,axp221-ac-power-supply";
+ };
+
+ axp_adc: adc {
+ compatible = "x-powers,axp221-adc";
+ #io-channel-cells = <1>;
+ };
+
+ battery_power_supply: battery-power {
+ compatible = "x-powers,axp221-battery-power-supply";
+ };
+
+ regulators {
+ x-powers,dcdc-freq = <3000>;
+
+ reg_dcdc1: dcdc1 {
+ regulator-name = "sys-3v3";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-name = "sys-1v8";
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_aldo1: aldo1 {
+ regulator-name = "aud-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_aldo2: aldo2 {
+ regulator-name = "disp-3v3";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_aldo3: aldo3 {
+ regulator-name = "vdd-wifi";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ /* DLDO1 and ELDO1-3 are connected in parallel. */
+ reg_dldo1: dldo1 {
+ regulator-name = "vbat-wifi-a";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ /* DLDO2-DLDO4 are connected in parallel. */
+ reg_dldo2: dldo2 {
+ regulator-name = "vcc-3v3-ext-a";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_dldo3: dldo3 {
+ regulator-name = "vcc-3v3-ext-b";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_dldo4: dldo4 {
+ regulator-name = "vcc-3v3-ext-c";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_eldo1: eldo1 {
+ regulator-name = "vbat-wifi-b";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_eldo2: eldo2 {
+ regulator-name = "vbat-wifi-c";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_eldo3: eldo3 {
+ regulator-name = "vbat-wifi-d";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+
+ usb_power_supply: usb-power {
+ compatible = "x-powers,axp221-usb-power-supply";
+ status = "disabled";
+ };
+ };
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ disable-wp;
+ vmmc-supply = <&reg_dcdc1>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&mmc1 {
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ vmmc-supply = <&reg_dldo1>;
+ vqmmc-supply = <&reg_aldo3>;
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ ap6256: wifi@1 {
+ compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupt-parent = <&pio>;
+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10/GPIO4 */
+ interrupt-names = "host-wake";
+ };
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ vcc-pg-supply = <&reg_ldoa>;
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb8_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart1 {
+ uart-has-rtscts;
+ pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4345c5";
+ interrupt-parent = <&pio>;
+ interrupts = <6 17 IRQ_TYPE_LEVEL_HIGH>; /* PG17/GPIO6 */
+ device-wakeup-gpios = <&pio 6 16 GPIO_ACTIVE_HIGH>; /* PG16/GPIO7 */
+ shutdown-gpios = <&pio 6 18 GPIO_ACTIVE_HIGH>; /* PG18/GPIO5 */
+ max-speed = <1500000>;
+ vbat-supply = <&reg_dldo1>;
+ vddio-supply = <&reg_aldo3>;
+ };
+};
+
+&usb_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_vbus_power-supply = <&ac_power_supply>;
+ status = "okay";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
+
+/dts-v1/;
+
+#include "sun20i-d1-clockworkpi-v3.14.dts"
+
+/ {
+ model = "Clockwork DevTerm (R-01)";
+ compatible = "clockwork,r-01-devterm-v3.14",
+ "clockwork,r-01-clockworkpi-v3.14",
+ "allwinner,sun20i-d1";
+
+ fan {
+ compatible = "gpio-fan";
+ gpios = <&pio 3 10 GPIO_ACTIVE_HIGH>; /* PD10/GPIO41 */
+ gpio-fan,speed-map = <0 0>,
+ <6000 1>;
+ #cooling-cells = <2>;
+ };
+
+ i2c-gpio-0 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&pio 3 14 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; /* PD14/GPIO44 */
+ scl-gpios = <&pio 3 15 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; /* PD15/GPIO45 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@54 {
+ compatible = "ti,adc101c";
+ reg = <0x54>;
+ interrupt-parent = <&pio>;
+ interrupts = <4 12 IRQ_TYPE_LEVEL_LOW>; /* PE12/GPIO35 */
+ vref-supply = <&reg_dldo2>;
+ };
+ };
+};

View File

@ -0,0 +1,44 @@
From f648ec2a040efde432876ee04240cb71e4c24d6e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 16 May 2021 14:17:45 -0500
Subject: [PATCH 034/117] riscv: Add the Allwinner SoC family Kconfig option
Allwinner manufactures the sunxi family of application processors. This
includes the "sun8i" series of ARMv7 SoCs, the "sun50i" series of ARMv8
SoCs, and now the "sun20i" series of 64-bit RISC-V SoCs.
The first SoC in the sun20i series is D1, containing a single T-HEAD
C906 core. D1s is a low-pin-count variant of D1 with co-packaged DRAM.
Most peripherals are shared across the entire chip family. In fact, the
ARMv7 T113 SoC is pin-compatible and almost entirely register-compatible
with the D1s.
This means many existing device drivers can be reused. To facilitate
this reuse, name the symbol ARCH_SUNXI, since that is what the existing
drivers have as their dependency.
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/Kconfig.socs | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -1,5 +1,14 @@
menu "SoC selection"
+config ARCH_SUNXI
+ bool "Allwinner sun20i SoCs"
+ select ERRATA_THEAD if MMU && !XIP_KERNEL
+ select SIFIVE_PLIC
+ select SUN4I_TIMER
+ help
+ This enables support for Allwinner sun20i platform hardware,
+ including boards based on the D1 and D1s SoCs.
+
config SOC_MICROCHIP_POLARFIRE
bool "Microchip PolarFire SoCs"
select MCHP_CLK_MPFS

View File

@ -0,0 +1,127 @@
From 73f9cc8568b6b821107d5194fa868e922b159091 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Mon, 27 Jun 2022 01:33:05 -0500
Subject: [PATCH 035/117] riscv: defconfig: Enable the Allwinner D1 platform
and drivers
Now that several D1-based boards are supported, enable the platform in
our defconfig. Build in the drivers which are necessary to boot, such as
the pinctrl, MMC, RTC (which provides critical clocks), SPI (for flash),
and watchdog (which may be left enabled by the bootloader). Other common
onboard peripherals are enabled as modules.
Cover-letter:
riscv: Allwinner D1 platform support
This series adds the Kconfig/defconfig plumbing and devicetrees for a
range of Allwinner D1-based boards. Many features are already enabled,
including USB, Ethernet, and WiFi.
The SoC devicetree uses bindings from the following series which have
not yet been merged:
- SRAM controller:
https://lore.kernel.org/lkml/20220815041248.53268-1-samuel@sholland.org/
- NVMEM cell bits property change:
https://lore.kernel.org/lkml/20220814173656.11856-1-samuel@sholland.org/
- In-package LDO regulators:
https://lore.kernel.org/lkml/20220815043436.20170-1-samuel@sholland.org/
All three of these are required to set the correct I/O domain voltages
in the pin controller, which I would consider important to have in the
initial version of the devicetree.
The SoC devicetree does contain one small hack to avoid a dependency on
the audio codec binding, since that is not ready yet: the codec node
uses a bare "simple-mfd", "syscon" compatible.
END
Series-to: Chen-Yu Tsai <wens@csie.org>
Series-to: Jernej Skrabec <jernej.skrabec@gmail.com>
Series-to: linux-sunxi@lists.linux.dev
Series-to: Palmer Dabbelt <palmer@dabbelt.com>
Series-to: Paul Walmsley <paul.walmsley@sifive.com>
Series-to: Albert Ou <aou@eecs.berkeley.edu>
Series-to: linux-riscv@lists.infradead.org
Series-cc: Rob Herring <robh+dt@kernel.org>
Series-cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Series-cc: devicetree@vger.kernel.org
Series-cc: linux-kernel@vger.kernel.org
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/configs/defconfig | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -25,6 +25,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_EXPERT=y
# CONFIG_SYSFS_SYSCALL is not set
CONFIG_PROFILING=y
+CONFIG_ARCH_SUNXI=y
CONFIG_SOC_MICROCHIP_POLARFIRE=y
CONFIG_SOC_SIFIVE=y
CONFIG_SOC_STARFIVE=y
@@ -118,22 +119,31 @@ CONFIG_VIRTIO_NET=y
CONFIG_MACB=y
CONFIG_E1000E=y
CONFIG_R8169=y
+CONFIG_STMMAC_ETH=m
CONFIG_MICROSEMI_PHY=y
CONFIG_INPUT_MOUSEDEV=y
+CONFIG_KEYBOARD_SUN4I_LRADC=m
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_I2C_MV64XXX=m
CONFIG_SPI=y
CONFIG_SPI_SIFIVE=y
+CONFIG_SPI_SUN6I=y
# CONFIG_PTP_1588_CLOCK is not set
-CONFIG_GPIOLIB=y
CONFIG_GPIO_SIFIVE=y
+CONFIG_WATCHDOG=y
+CONFIG_SUNXI_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_DRM=m
CONFIG_DRM_RADEON=m
CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_SUN4I=m
CONFIG_DRM_VIRTIO_GPU=m
CONFIG_FB=y
CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -146,19 +156,30 @@ CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
+CONFIG_USB_MUSB_HDRC=m
+CONFIG_USB_MUSB_SUNXI=m
+CONFIG_NOP_USB_XCEIV=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SPI=y
+CONFIG_MMC_SUNXI=y
CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_SUN6I=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_SUN6I=m
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
+CONFIG_SUN8I_DE2_CCU=m
+CONFIG_SUN50I_IOMMU=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_CTRL=y
CONFIG_RPMSG_VIRTIO=y
+CONFIG_PHY_SUN4I_USB=m
+CONFIG_NVMEM_SUNXI_SID=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y

View File

@ -0,0 +1,80 @@
From bf83f1dc034111aac1f23b98d7205d08c7c83208 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 17 Aug 2022 02:33:25 -0500
Subject: [PATCH 036/117] riscv: dts: allwinner: Add Bluetooth PCM audio
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../allwinner/sun20i-d1-clockworkpi-v3.14.dts | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
@@ -22,6 +22,32 @@
stdout-path = "serial0:115200n8";
};
+ bt_sco_codec: bt-sco-codec {
+ #sound-dai-cells = <0>;
+ compatible = "linux,bt-sco";
+ };
+
+ bt-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "Bluetooth";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,dai-link@0 {
+ format = "dsp_a";
+ frame-master = <&bt_sound_cpu>;
+ bitclock-master = <&bt_sound_cpu>;
+
+ bt_sound_cpu: cpu {
+ sound-dai = <&i2s1>;
+ };
+
+ codec {
+ sound-dai = <&bt_sco_codec>;
+ };
+ };
+ };
+
/*
* This regulator is PWM-controlled, but the PWM controller is not
* yet supported, so fix the regulator to its default voltage.
@@ -169,6 +195,12 @@
};
};
+&i2s1 {
+ pinctrl-0 = <&i2s1_clk_pins>, <&i2s1_din_pin>, <&i2s1_dout_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&mmc0 {
broken-cd;
bus-width = <4>;
@@ -205,6 +237,21 @@
&pio {
vcc-pg-supply = <&reg_ldoa>;
+
+ i2s1_clk_pins: i2s1-clk-pins {
+ pins = "PG12", "PG13";
+ function = "i2s1";
+ };
+
+ i2s1_din_pin: i2s1-din-pin {
+ pins = "PG14";
+ function = "i2s1_din";
+ };
+
+ i2s1_dout_pin: i2s1-dout-pin {
+ pins = "PG15";
+ function = "i2s1_dout";
+ };
};
&uart0 {

View File

@ -0,0 +1,87 @@
From 690b8d708e0193d50522f70359bcab62a2f99742 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 14 Nov 2021 09:04:29 -0600
Subject: [PATCH 037/117] dt-bindings: crypto: sun8i-ce: Add compatible for D1
D1 has a crypto engine similar to the one in other Allwinner SoCs.
Like H6, it has a separate MBUS clock gate.
It also requires the internal RC oscillator to be enabled for the TRNG
to return data. This is likely the case for earlier variants as well,
but the clock drivers for earlier SoCs did not allow disabling the RC
oscillator.
Series-changes: 2
- Add TRNG clock
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../bindings/crypto/allwinner,sun8i-ce.yaml | 31 ++++++++++++++-----
1 file changed, 23 insertions(+), 8 deletions(-)
--- a/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml
+++ b/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml
@@ -14,6 +14,7 @@ properties:
enum:
- allwinner,sun8i-h3-crypto
- allwinner,sun8i-r40-crypto
+ - allwinner,sun20i-d1-crypto
- allwinner,sun50i-a64-crypto
- allwinner,sun50i-h5-crypto
- allwinner,sun50i-h6-crypto
@@ -29,6 +30,7 @@ properties:
- description: Bus clock
- description: Module clock
- description: MBus clock
+ - description: TRNG clock (RC oscillator)
minItems: 2
clock-names:
@@ -36,6 +38,7 @@ properties:
- const: bus
- const: mod
- const: ram
+ - const: trng
minItems: 2
resets:
@@ -44,19 +47,31 @@ properties:
if:
properties:
compatible:
- const: allwinner,sun50i-h6-crypto
+ enum:
+ - allwinner,sun20i-d1-crypto
then:
properties:
clocks:
- minItems: 3
+ minItems: 4
clock-names:
- minItems: 3
+ minItems: 4
else:
- properties:
- clocks:
- maxItems: 2
- clock-names:
- maxItems: 2
+ if:
+ properties:
+ compatible:
+ const: allwinner,sun50i-h6-crypto
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ clock-names:
+ minItems: 3
+ else:
+ properties:
+ clocks:
+ maxItems: 2
+ clock-names:
+ maxItems: 2
required:
- compatible

View File

@ -0,0 +1,47 @@
From d09357656ae3985095f562cf005fa94fd61ebfe6 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Tue, 1 Feb 2022 21:50:16 -0600
Subject: [PATCH 038/117] crypto: sun8i-ce - Add TRNG clock to D1 variant
At least the D1 variant requires a separate clock for the TRNG.
Without this clock enabled, reading from /dev/hwrng reports:
sun8i-ce 3040000.crypto: DMA timeout for TRNG (tm=96) on flow 3
Experimentation shows that the necessary clock is the SoC's internal
RC oscillator. This makes sense, as the oscillator's frequency
variations can be used as a source of randomness.
Since D1 does not yet have a device tree, we can update this variant
without breaking anything.
Series-changes: 2
- New patch
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c | 1 +
drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
@@ -118,6 +118,7 @@ static const struct ce_variant ce_d1_var
{ "bus", 0, 200000000 },
{ "mod", 300000000, 0 },
{ "ram", 0, 400000000 },
+ { "trng", 0, 0 },
},
.esr = ESR_D1,
.prng = CE_ALG_PRNG,
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h
@@ -105,7 +105,7 @@
#define MAX_SG 8
-#define CE_MAX_CLOCKS 3
+#define CE_MAX_CLOCKS 4
#define MAXFLOW 4

View File

@ -0,0 +1,31 @@
From 5dae72bf0e0fabb3164dbc4b5eee310c63f1975c Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 22:20:31 -0500
Subject: [PATCH 039/117] riscv: dts: allwinner: d1: Add crypto engine support
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -457,6 +457,18 @@
};
};
+ crypto: crypto@3040000 {
+ compatible = "allwinner,sun20i-d1-crypto";
+ reg = <0x3040000 0x800>;
+ interrupts = <68 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CE>,
+ <&ccu CLK_CE>,
+ <&ccu CLK_MBUS_CE>,
+ <&rtc CLK_IOSC>;
+ clock-names = "bus", "mod", "ram", "trng";
+ resets = <&ccu RST_BUS_CE>;
+ };
+
mbus: dram-controller@3102000 {
compatible = "allwinner,sun20i-d1-mbus";
reg = <0x3102000 0x1000>,

View File

@ -0,0 +1,27 @@
From 7a24e5ee94e0163801c8ab4c131ae1d530a420ea Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 17 Aug 2022 02:08:36 -0500
Subject: [PATCH 040/117] ASoC: sun50i-dmic: dt-bindings: Add D1 compatible
string
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../bindings/sound/allwinner,sun50i-h6-dmic.yaml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
@@ -11,7 +11,12 @@ maintainers:
properties:
compatible:
- const: allwinner,sun50i-h6-dmic
+ oneOf:
+ - items:
+ - enum:
+ - allwinner,sun20i-d1-dmic
+ - const: allwinner,sun50i-h6-dmic
+ - const: allwinner,sun50i-h6-dmic
"#sound-dai-cells":
const: 0

View File

@ -0,0 +1,34 @@
From d73f2176958e405e55c4e782c6d0f888e20080e5 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 17 Aug 2022 02:08:58 -0500
Subject: [PATCH 041/117] riscv: dts: allwinner: d1: Add DMIC node
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -208,6 +208,21 @@
};
};
+ dmic: dmic@2031000 {
+ compatible = "allwinner,sun20i-d1-dmic",
+ "allwinner,sun50i-h6-dmic";
+ reg = <0x2031000 0x400>;
+ interrupts = <40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMIC>,
+ <&ccu CLK_DMIC>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_DMIC>;
+ dmas = <&dma 8>;
+ dma-names = "rx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
i2s0: i2s@2032000 {
compatible = "allwinner,sun20i-d1-i2s",
"allwinner,sun50i-r329-i2s";

View File

@ -0,0 +1,144 @@
From 500a3fc1ce1b216ef4f4df73e4e048170764189e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 17 Aug 2022 02:20:49 -0500
Subject: [PATCH 042/117] riscv: dts: allwinner: Add DMIC sound cards
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../sun20i-d1-lichee-rv-86-panel.dtsi | 43 ++++++++++++++++++
.../allwinner/sun20i-d1-lichee-rv-dock.dts | 45 +++++++++++++++++++
2 files changed, 88 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
@@ -9,6 +9,33 @@
ethernet1 = &xr829;
};
+ dmic_codec: dmic-codec {
+ compatible = "dmic-codec";
+ num-channels = <2>;
+ #sound-dai-cells = <0>;
+ };
+
+ dmic-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "DMIC";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,dai-link@0 {
+ format = "pdm";
+ frame-master = <&link0_cpu>;
+ bitclock-master = <&link0_cpu>;
+
+ link0_cpu: cpu {
+ sound-dai = <&dmic>;
+ };
+
+ link0_codec: codec {
+ sound-dai = <&dmic_codec>;
+ };
+ };
+ };
+
/* PC1 is repurposed as BT_WAKE_AP */
/delete-node/ leds;
@@ -24,6 +51,12 @@
};
};
+&dmic {
+ pinctrl-0 = <&dmic_pb11_d0_pin>, <&dmic_pe17_clk_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -69,6 +102,16 @@
pins = "PG11";
function = "clk";
};
+
+ dmic_pb11_d0_pin: dmic-pb11-d0-pin {
+ pins = "PB11";
+ function = "dmic";
+ };
+
+ dmic_pe17_clk_pin: dmic-pe17-clk-pin {
+ pins = "PE17";
+ function = "dmic";
+ };
};
&uart1 {
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
@@ -15,12 +15,45 @@
ethernet1 = &rtl8723ds;
};
+ dmic_codec: dmic-codec {
+ compatible = "dmic-codec";
+ num-channels = <2>;
+ #sound-dai-cells = <0>;
+ };
+
+ dmic-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "DMIC";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,dai-link@0 {
+ format = "pdm";
+ frame-master = <&link0_cpu>;
+ bitclock-master = <&link0_cpu>;
+
+ link0_cpu: cpu {
+ sound-dai = <&dmic>;
+ };
+
+ link0_codec: codec {
+ sound-dai = <&dmic_codec>;
+ };
+ };
+ };
+
wifi_pwrseq: wifi-pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
};
};
+&dmic {
+ pinctrl-0 = <&dmic_pb11_d0_pin>, <&dmic_pe17_clk_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -55,6 +88,18 @@
status = "okay";
};
+&pio {
+ dmic_pb11_d0_pin: dmic-pb11-d0-pin {
+ pins = "PB11";
+ function = "dmic";
+ };
+
+ dmic_pe17_clk_pin: dmic-pe17-clk-pin {
+ pins = "PE17";
+ function = "dmic";
+ };
+};
+
&uart1 {
uart-has-rtscts;
pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>;

View File

@ -0,0 +1,64 @@
From 7708f7471ab45039e08237b42121d0372f9216a7 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 13 Jun 2021 23:42:19 -0500
Subject: [PATCH 043/117] hwspinlock: sun6i: Clarify bank counting logic
In some of the most recent datasheets, the register definition was
updated in a way that resolves the conflict here: the field is only two
bits wide, and a value of "4" really means a bit pattern of "0". Correct
the code to reflect this, but leave an updated comment because some
datasheets still have incorrect information in them.
Fixes: 3c881e05c814 ("hwspinlock: add sun6i hardware spinlock support")
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/hwspinlock/sun6i_hwspinlock.c | 36 +++++++++++----------------
1 file changed, 14 insertions(+), 22 deletions(-)
--- a/drivers/hwspinlock/sun6i_hwspinlock.c
+++ b/drivers/hwspinlock/sun6i_hwspinlock.c
@@ -129,30 +129,22 @@ static int sun6i_hwspinlock_probe(struct
}
/*
- * bit 28 and 29 represents the hwspinlock setup
+ * Bits 28 and 29 represent the number of available locks.
*
- * every datasheet (A64, A80, A83T, H3, H5, H6 ...) says the default value is 0x1 and 0x1
- * to 0x4 represent 32, 64, 128 and 256 locks
- * but later datasheets (H5, H6) say 00, 01, 10, 11 represent 32, 64, 128 and 256 locks,
- * but that would mean H5 and H6 have 64 locks, while their datasheets talk about 32 locks
- * all the time, not a single mentioning of 64 locks
- * the 0x4 value is also not representable by 2 bits alone, so some datasheets are not
- * correct
- * one thing have all in common, default value of the sysstatus register is 0x10000000,
- * which results in bit 28 being set
- * this is the reason 0x1 is considered being 32 locks and bit 30 is taken into account
- * verified on H2+ (datasheet 0x1 = 32 locks) and H5 (datasheet 01 = 64 locks)
+ * The datasheets have two conflicting interpretations for these bits:
+ * | 00 | 01 | 10 | 11 |
+ * +-----+----+-----+-----+
+ * | 256 | 32 | 64 | 128 | A80, A83T, H3, A64, A50, D1
+ * | 32 | 64 | 128 | 256 | H5, H6, R329
+ * where some datasheets use "4" instead of "0" for the first column.
+ *
+ * Experiments shows that the first interpretation is correct, as all
+ * known implementations report the value "1" and have 32 spinlocks.
*/
- num_banks = readl(io_base + SPINLOCK_SYSSTATUS_REG) >> 28;
- switch (num_banks) {
- case 1 ... 4:
- priv->nlocks = 1 << (4 + num_banks);
- break;
- default:
- err = -EINVAL;
- dev_err(&pdev->dev, "unsupported hwspinlock setup (%d)\n", num_banks);
- goto bank_fail;
- }
+ num_banks = readl(io_base + SPINLOCK_SYSSTATUS_REG) >> 28 & 0x3;
+ if (!num_banks)
+ num_banks = 4;
+ priv->nlocks = 1 << (4 + num_banks);
priv->bank = devm_kzalloc(&pdev->dev, struct_size(priv->bank, lock, priv->nlocks),
GFP_KERNEL);

View File

@ -0,0 +1,37 @@
From a19b55088945ce86051ea4eab22df27805a30c71 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 13 Jun 2021 23:41:44 -0500
Subject: [PATCH 044/117] hwspinlock: sun6i: Fix driver to match binding
The binding for this device does not allow using the clock-names and
reset-names properties, so the driver should not reference the clock or
reset by name.
Fixes: 3c881e05c814 ("hwspinlock: add sun6i hardware spinlock support")
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/hwspinlock/sun6i_hwspinlock.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
--- a/drivers/hwspinlock/sun6i_hwspinlock.c
+++ b/drivers/hwspinlock/sun6i_hwspinlock.c
@@ -104,14 +104,12 @@ static int sun6i_hwspinlock_probe(struct
if (!priv)
return -ENOMEM;
- priv->ahb_clk = devm_clk_get(&pdev->dev, "ahb");
- if (IS_ERR(priv->ahb_clk)) {
- err = PTR_ERR(priv->ahb_clk);
- dev_err(&pdev->dev, "unable to get AHB clock (%d)\n", err);
- return err;
- }
+ priv->ahb_clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->ahb_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->ahb_clk),
+ "unable to get AHB clock\n");
- priv->reset = devm_reset_control_get(&pdev->dev, "ahb");
+ priv->reset = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(priv->reset))
return dev_err_probe(&pdev->dev, PTR_ERR(priv->reset),
"unable to get reset control\n");

View File

@ -0,0 +1,51 @@
From f0c29c5d370507ca2106689e7e17b81e8b58f236 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 14 Nov 2021 11:37:34 -0600
Subject: [PATCH 045/117] dt-bindings: hwlock: sun6i: Add interrupts property
While it was not officially documented until recently (e.g. A50), the
hwspinlock block can trigger an interrupt when a lock is unlocked. This
capability is used by Allwinner's ARISC firmware, it has been verified
to work on A64, and the IRQ numbers are reserved as far back as A31.
So most likely this feature has always been available.
Even though the Linux hwspinlock framework cannot make use of the IRQ,
the capability should still be documented in the device tree.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml | 6 ++++++
1 file changed, 6 insertions(+)
--- a/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml
+++ b/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml
@@ -26,17 +26,22 @@ properties:
resets:
maxItems: 1
+ interrupts:
+ maxItems: 1
+
required:
- compatible
- reg
- clocks
- resets
+ - interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/sun8i-a23-a33-ccu.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/sun8i-a23-a33-ccu.h>
hwlock@1c18000 {
@@ -44,5 +49,6 @@ examples:
reg = <0x01c18000 0x1000>;
clocks = <&ccu CLK_BUS_SPINLOCK>;
resets = <&ccu RST_BUS_SPINLOCK>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
};
...

View File

@ -0,0 +1,39 @@
From e7b8c42c6bf02f4c2e24b015a12cd9edad094644 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 14 Nov 2021 12:36:52 -0600
Subject: [PATCH 046/117] dt-bindings: hwlock: sun6i: Add per-SoC compatibles
While all implementations of this hardware appear to be indentical, it
is possible that some difference exists. To be safe, add a compatible
for each SoC integration, using the A31 compatible only as a fallback.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../hwlock/allwinner,sun6i-a31-hwspinlock.yaml | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml
+++ b/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml
@@ -15,7 +15,21 @@ description:
properties:
compatible:
- const: allwinner,sun6i-a31-hwspinlock
+ oneOf:
+ - items:
+ - enum:
+ - allwinner,sun8i-a23-hwspinlock
+ - allwinner,sun8i-a33-hwspinlock
+ - allwinner,sun8i-a50-hwspinlock
+ - allwinner,sun8i-a83t-hwspinlock
+ - allwinner,sun8i-h3-hwspinlock
+ - allwinner,sun9i-a80-hwspinlock
+ - allwinner,sun20i-d1-hwspinlock
+ - allwinner,sun50i-a64-hwspinlock
+ - allwinner,sun50i-h6-hwspinlock
+ - allwinner,sun50i-r329-hwspinlock
+ - const: allwinner,sun6i-a31-hwspinlock
+ - const: allwinner,sun6i-a31-hwspinlock
reg:
maxItems: 1

View File

@ -0,0 +1,20 @@
From 419b337ac3e60126f9de0bc98892e54a8ffe3b6e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 13 Jun 2021 23:50:57 -0500
Subject: [PATCH 047/117] ASoC: sun4i-i2s: Also set capture DMA width
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun4i-i2s.c | 1 +
1 file changed, 1 insertion(+)
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -633,6 +633,7 @@ static int sun4i_i2s_hw_params(struct sn
params_physical_width(params));
return -EINVAL;
}
+ i2s->capture_dma_data.addr_width = width;
i2s->playback_dma_data.addr_width = width;
sr = i2s->variant->get_sr(word_size);

View File

@ -0,0 +1,19 @@
From dbad9a1f280b3c3e34cc133407ae057293b8aadf Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 17 Aug 2022 02:34:08 -0500
Subject: [PATCH 048/117] todo
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 1 +
1 file changed, 1 insertion(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -253,6 +253,7 @@
#sound-dai-cells = <0>;
};
+ // TODO: how to integrate ASRC? same or separate node?
i2s2: i2s@2034000 {
compatible = "allwinner,sun20i-d1-i2s",
"allwinner,sun50i-r329-i2s";

View File

@ -0,0 +1,46 @@
From 031deed1d755fc9f1e4908ef70969e1458203421 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 6 Jun 2021 10:20:38 -0500
Subject: [PATCH 049/117] dt-bindings: iommu: sun50i: Add compatible for
Allwinner D1
D1 contains an IOMMU similar to the one in the H6 SoC, but the D1
variant has no external reset signal.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../iommu/allwinner,sun50i-h6-iommu.yaml | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
--- a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
@@ -17,7 +17,9 @@ properties:
The content of the cell is the master ID.
compatible:
- const: allwinner,sun50i-h6-iommu
+ enum:
+ - allwinner,sun20i-d1-iommu
+ - allwinner,sun50i-h6-iommu
reg:
maxItems: 1
@@ -37,7 +39,17 @@ required:
- reg
- interrupts
- clocks
- - resets
+
+if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - allwinner,sun50i-h6-iommu
+
+then:
+ required:
+ - resets
additionalProperties: false

View File

@ -0,0 +1,69 @@
From 15a0487680cf506bb4b9bfee2c41b2c3176d4efa Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 27 Apr 2022 19:01:57 -0500
Subject: [PATCH 050/117] iommu/sun50i: Support variants without an external
reset
The IOMMU in the Allwinner D1 SoC does not have an external reset line.
Only attempt to get the reset on hardware variants which should have one
according to the binding. And switch from the deprecated function to the
explicit "exclusive" variant.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/iommu/sun50i-iommu.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -95,6 +95,10 @@
#define SPAGE_SIZE 4096
+struct sun50i_iommu_variant {
+ bool has_reset;
+};
+
struct sun50i_iommu {
struct iommu_device iommu;
@@ -979,9 +983,14 @@ static irqreturn_t sun50i_iommu_irq(int
static int sun50i_iommu_probe(struct platform_device *pdev)
{
+ const struct sun50i_iommu_variant *variant;
struct sun50i_iommu *iommu;
int ret, irq;
+ variant = of_device_get_match_data(&pdev->dev);
+ if (!variant)
+ return -EINVAL;
+
iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
if (!iommu)
return -ENOMEM;
@@ -1021,7 +1030,8 @@ static int sun50i_iommu_probe(struct pla
goto err_free_group;
}
- iommu->reset = devm_reset_control_get(&pdev->dev, NULL);
+ if (variant->has_reset)
+ iommu->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(iommu->reset)) {
dev_err(&pdev->dev, "Couldn't get our reset line.\n");
ret = PTR_ERR(iommu->reset);
@@ -1059,8 +1069,12 @@ err_free_cache:
return ret;
}
+static const struct sun50i_iommu_variant sun50i_h6_iommu = {
+ .has_reset = true,
+};
+
static const struct of_device_id sun50i_iommu_dt[] = {
- { .compatible = "allwinner,sun50i-h6-iommu", },
+ { .compatible = "allwinner,sun50i-h6-iommu", .data = &sun50i_h6_iommu },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, sun50i_iommu_dt);

View File

@ -0,0 +1,26 @@
From 384e2ca3c049fe36f4e679fc76fcc8dfdc9297f9 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 27 Apr 2022 19:06:28 -0500
Subject: [PATCH 051/117] iommu/sun50i: Ensure bypass is disabled
The H6 variant of the hardware disables bypass by default. The D1
variant of the hardware enables bypass for all masters by default.
Since the driver expects bypass to be disabled, ensure that is the case.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/iommu/sun50i-iommu.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -445,6 +445,8 @@ static int sun50i_iommu_enable(struct su
spin_lock_irqsave(&iommu->iommu_lock, flags);
+ iommu_write(iommu, IOMMU_BYPASS_REG, 0);
+
iommu_write(iommu, IOMMU_TTB_REG, sun50i_domain->dt_dma);
iommu_write(iommu, IOMMU_TLB_PREFETCH_REG,
IOMMU_TLB_PREFETCH_MASTER_ENABLE(0) |

View File

@ -0,0 +1,32 @@
From 5fdd5231c56d58f16a6cefa2bed4b8f331da2c92 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 27 Apr 2022 19:20:58 -0500
Subject: [PATCH 052/117] iommu/sun50i: Add support for the D1 variant
D1 contains an IOMMU similar to the one in the H6 SoC, but the D1
variant has no external reset signal. It also has some register
definition changes, but none that affect the current driver.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/iommu/sun50i-iommu.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -1071,11 +1071,15 @@ err_free_cache:
return ret;
}
+static const struct sun50i_iommu_variant sun20i_d1_iommu = {
+};
+
static const struct sun50i_iommu_variant sun50i_h6_iommu = {
.has_reset = true,
};
static const struct of_device_id sun50i_iommu_dt[] = {
+ { .compatible = "allwinner,sun20i-d1-iommu", .data = &sun20i_d1_iommu },
{ .compatible = "allwinner,sun50i-h6-iommu", .data = &sun50i_h6_iommu },
{ /* sentinel */ },
};

View File

@ -0,0 +1,43 @@
From 4c37ac95ee354857c8c662b6b7b4bc50eea23206 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 14 Aug 2022 11:20:37 -0500
Subject: [PATCH 053/117] riscv: dts: allwinner: d1: Add IOMMU node
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -188,6 +188,14 @@
status = "disabled";
};
+ iommu: iommu@2010000 {
+ compatible = "allwinner,sun20i-d1-iommu";
+ reg = <0x2010000 0x10000>;
+ interrupts = <80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_IOMMU>;
+ #iommu-cells = <1>;
+ };
+
codec: audio-codec@2030000 {
compatible = "simple-mfd", "syscon";
reg = <0x2030000 0x1000>;
@@ -681,6 +689,7 @@
<&display_clocks CLK_MIXER0>;
clock-names = "bus", "mod";
resets = <&display_clocks RST_MIXER0>;
+ iommus = <&iommu 2>;
ports {
#address-cells = <1>;
@@ -703,6 +712,7 @@
<&display_clocks CLK_MIXER1>;
clock-names = "bus", "mod";
resets = <&display_clocks RST_MIXER1>;
+ iommus = <&iommu 2>;
ports {
#address-cells = <1>;

View File

@ -0,0 +1,179 @@
From 31857adcc9db7244a047a3a3550219f7559d8846 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 4 Aug 2021 21:36:26 -0500
Subject: [PATCH 054/117] dt-bindings: leds: Add Allwinner A100 LED controller
The Allwinner A100, R329, and D1 SoCs contain an LED controller designed
to drive a series of RGB LED pixels. It supports PIO and DMA transfers,
and has configurable timing and pixel format. All three implementations
appear to be identical, so use the oldest as the fallback compatible.
Series-changes: 2
- Fixed typo leading to duplicate t1h-ns property
- Removed "items" layer in definition of dmas/dma-names
- Replaced uint32 type reference with maxItems in timing properties
Series-changes: 3
- Removed quotes from enumeration values
- Added vendor prefix to timing/format properties
- Renamed "format" property to "pixel-format" for clarity
- Dropped "vled-supply" as it is unrelated to the controller hardware
Series-changes: 4
- Use "default" instead of "maxItems" for timing properties
Series-changes: 5
- A100 contains the original implementation, so use that as the base
compatible string, and rename the binding to match
- Add "unevaluatedProperties: false" to the child multi-led binding
Acked-by: Maxime Ripard <maxime@cerno.tech>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../leds/allwinner,sun50i-a100-ledc.yaml | 139 ++++++++++++++++++
1 file changed, 139 insertions(+)
create mode 100644 Documentation/devicetree/bindings/leds/allwinner,sun50i-a100-ledc.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/allwinner,sun50i-a100-ledc.yaml
@@ -0,0 +1,139 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/allwinner,sun50i-a100-ledc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A100 LED Controller Bindings
+
+maintainers:
+ - Samuel Holland <samuel@sholland.org>
+
+description:
+ The LED controller found in Allwinner sunxi SoCs uses a one-wire serial
+ interface to drive up to 1024 RGB LEDs.
+
+properties:
+ compatible:
+ oneOf:
+ - const: allwinner,sun50i-a100-ledc
+ - items:
+ - enum:
+ - allwinner,sun20i-d1-ledc
+ - allwinner,sun50i-r329-ledc
+ - const: allwinner,sun50i-a100-ledc
+
+ reg:
+ maxItems: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Bus clock
+ - description: Module clock
+
+ clock-names:
+ items:
+ - const: bus
+ - const: mod
+
+ resets:
+ maxItems: 1
+
+ dmas:
+ maxItems: 1
+ description: TX DMA channel
+
+ dma-names:
+ const: tx
+
+ allwinner,pixel-format:
+ description: Pixel format (subpixel transmission order), default is "grb"
+ enum:
+ - bgr
+ - brg
+ - gbr
+ - grb
+ - rbg
+ - rgb
+
+ allwinner,t0h-ns:
+ default: 336
+ description: Length of high pulse when transmitting a "0" bit
+
+ allwinner,t0l-ns:
+ default: 840
+ description: Length of low pulse when transmitting a "0" bit
+
+ allwinner,t1h-ns:
+ default: 882
+ description: Length of high pulse when transmitting a "1" bit
+
+ allwinner,t1l-ns:
+ default: 294
+ description: Length of low pulse when transmitting a "1" bit
+
+ allwinner,treset-ns:
+ default: 300000
+ description: Minimum delay between transmission frames
+
+patternProperties:
+ "^multi-led@[0-9a-f]+$":
+ type: object
+ $ref: leds-class-multicolor.yaml#
+ unevaluatedProperties: false
+ properties:
+ reg:
+ minimum: 0
+ maximum: 1023
+ description: Index of the LED in the series (must be contiguous)
+
+ required:
+ - reg
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - dmas
+ - dma-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/leds/common.h>
+
+ ledc: led-controller@2008000 {
+ compatible = "allwinner,sun20i-d1-ledc",
+ "allwinner,sun50i-a100-ledc";
+ reg = <0x2008000 0x400>;
+ interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu 12>, <&ccu 34>;
+ clock-names = "bus", "mod";
+ resets = <&ccu 12>;
+ dmas = <&dma 42>;
+ dma-names = "tx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi-led@0 {
+ reg = <0x0>;
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_INDICATOR;
+ };
+ };
+
+...

View File

@ -0,0 +1,620 @@
From 352b296d30df06b880d2c7620910cd759dc2609d Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 26 Jun 2021 11:02:49 -0500
Subject: [PATCH 055/117] leds: sun50i-a100: New driver for the A100 LED
controller
Some Allwinner sunxi SoCs, starting with the A100, contain an LED
controller designed to drive RGB LED pixels. Add a driver for it using
the multicolor LED framework, and with LEDs defined in the device tree.
Series-changes: 2
- Renamed from sunxi-ledc to sun50i-r329-ledc
- Added missing "static" to functions/globals as reported by 0day bot
Series-changes: 3
- Added vendor prefix to timing/format properties
- Renamed "format" property to "pixel-format" for clarity
- Dropped "vled-supply" as it is unrelated to the controller hardware
- Changed "writesl" to "iowrite32_rep" so the driver builds on hppa
Series-changes: 4
- Depend on LEDS_CLASS_MULTICOLOR
Series-changes: 5
- Rename the driver R329 -> A100, since that is the actual original
implementation
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/leds/Kconfig | 9 +
drivers/leds/Makefile | 1 +
drivers/leds/leds-sun50i-a100.c | 554 ++++++++++++++++++++++++++++++++
3 files changed, 564 insertions(+)
create mode 100644 drivers/leds/leds-sun50i-a100.c
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -283,6 +283,15 @@ config LEDS_COBALT_RAQ
help
This option enables support for the Cobalt Raq series LEDs.
+config LEDS_SUN50I_A100
+ tristate "LED support for Allwinner A100 RGB LED controller"
+ depends on LEDS_CLASS_MULTICOLOR && OF
+ depends on ARCH_SUNXI || COMPILE_TEST
+ help
+ This option enables support for the RGB LED controller found
+ in some Allwinner sunxi SoCs, includeing A100, R329, and D1.
+ It uses a one-wire interface to control up to 1024 LEDs.
+
config LEDS_SUNFIRE
tristate "LED support for SunFire servers."
depends on LEDS_CLASS
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o
+obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o
obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o
obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
--- /dev/null
+++ b/drivers/leds/leds-sun50i-a100.c
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
+//
+// Partly based on drivers/leds/leds-turris-omnia.c, which is:
+// Copyright (c) 2020 by Marek Behún <kabel@kernel.org>
+//
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/led-class-multicolor.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#define LEDC_CTRL_REG 0x0000
+#define LEDC_CTRL_REG_DATA_LENGTH (0x1fff << 16)
+#define LEDC_CTRL_REG_RGB_MODE (0x7 << 6)
+#define LEDC_CTRL_REG_LEDC_EN BIT(0)
+#define LEDC_T01_TIMING_CTRL_REG 0x0004
+#define LEDC_T01_TIMING_CTRL_REG_T1H (0x3f << 21)
+#define LEDC_T01_TIMING_CTRL_REG_T1L (0x1f << 16)
+#define LEDC_T01_TIMING_CTRL_REG_T0H (0x1f << 6)
+#define LEDC_T01_TIMING_CTRL_REG_T0L (0x3f << 0)
+#define LEDC_RESET_TIMING_CTRL_REG 0x000c
+#define LEDC_RESET_TIMING_CTRL_REG_LED_NUM (0x3ff << 0)
+#define LEDC_DATA_REG 0x0014
+#define LEDC_DMA_CTRL_REG 0x0018
+#define LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL (0x1f << 0)
+#define LEDC_INT_CTRL_REG 0x001c
+#define LEDC_INT_CTRL_REG_GLOBAL_INT_EN BIT(5)
+#define LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN BIT(1)
+#define LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN BIT(0)
+#define LEDC_INT_STS_REG 0x0020
+#define LEDC_INT_STS_REG_FIFO_CPUREQ_INT BIT(1)
+#define LEDC_INT_STS_REG_TRANS_FINISH_INT BIT(0)
+
+#define LEDC_FIFO_DEPTH 32
+#define LEDC_MAX_LEDS 1024
+
+#define LEDS_TO_BYTES(n) ((n) * sizeof(u32))
+
+struct sun50i_a100_ledc_led {
+ struct led_classdev_mc mc_cdev;
+ struct mc_subled subled_info[3];
+};
+
+#define to_ledc_led(mc) container_of(mc, struct sun50i_a100_ledc_led, mc_cdev)
+
+struct sun50i_a100_ledc_timing {
+ u32 t0h_ns;
+ u32 t0l_ns;
+ u32 t1h_ns;
+ u32 t1l_ns;
+ u32 treset_ns;
+};
+
+struct sun50i_a100_ledc {
+ struct device *dev;
+ void __iomem *base;
+ struct clk *bus_clk;
+ struct clk *mod_clk;
+ struct reset_control *reset;
+
+ u32 *buffer;
+ struct dma_chan *dma_chan;
+ dma_addr_t dma_handle;
+ int pio_length;
+ int pio_offset;
+
+ spinlock_t lock;
+ int next_length;
+ bool xfer_active;
+
+ u32 format;
+ struct sun50i_a100_ledc_timing timing;
+
+ int num_leds;
+ struct sun50i_a100_ledc_led leds[];
+};
+
+static int sun50i_a100_ledc_dma_xfer(struct sun50i_a100_ledc *priv, int length)
+{
+ struct dma_async_tx_descriptor *desc;
+ dma_cookie_t cookie;
+
+ desc = dmaengine_prep_slave_single(priv->dma_chan, priv->dma_handle,
+ LEDS_TO_BYTES(length),
+ DMA_MEM_TO_DEV, 0);
+ if (!desc)
+ return -ENOMEM;
+
+ cookie = dmaengine_submit(desc);
+ if (dma_submit_error(cookie))
+ return -EIO;
+
+ dma_async_issue_pending(priv->dma_chan);
+
+ return 0;
+}
+
+static void sun50i_a100_ledc_pio_xfer(struct sun50i_a100_ledc *priv, int length)
+{
+ u32 burst, offset, val;
+
+ if (length) {
+ /* New transfer (FIFO is empty). */
+ offset = 0;
+ burst = min(length, LEDC_FIFO_DEPTH);
+ } else {
+ /* Existing transfer (FIFO is half-full). */
+ length = priv->pio_length;
+ offset = priv->pio_offset;
+ burst = min(length, LEDC_FIFO_DEPTH / 2);
+ }
+
+ iowrite32_rep(priv->base + LEDC_DATA_REG, priv->buffer + offset, burst);
+
+ if (burst < length) {
+ priv->pio_length = length - burst;
+ priv->pio_offset = offset + burst;
+
+ if (!offset) {
+ val = readl(priv->base + LEDC_INT_CTRL_REG);
+ val |= LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN;
+ writel(val, priv->base + LEDC_INT_CTRL_REG);
+ }
+ } else {
+ /* Disable the request IRQ once all data is written. */
+ val = readl(priv->base + LEDC_INT_CTRL_REG);
+ val &= ~LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN;
+ writel(val, priv->base + LEDC_INT_CTRL_REG);
+ }
+}
+
+static void sun50i_a100_ledc_start_xfer(struct sun50i_a100_ledc *priv,
+ int length)
+{
+ u32 val;
+
+ dev_dbg(priv->dev, "Updating %d LEDs\n", length);
+
+ val = readl(priv->base + LEDC_CTRL_REG);
+ val &= ~LEDC_CTRL_REG_DATA_LENGTH;
+ val |= length << 16 | LEDC_CTRL_REG_LEDC_EN;
+ writel(val, priv->base + LEDC_CTRL_REG);
+
+ if (length > LEDC_FIFO_DEPTH) {
+ int ret = sun50i_a100_ledc_dma_xfer(priv, length);
+
+ if (!ret)
+ return;
+
+ dev_warn(priv->dev, "Failed to set up DMA: %d\n", ret);
+ }
+
+ sun50i_a100_ledc_pio_xfer(priv, length);
+}
+
+static irqreturn_t sun50i_a100_ledc_irq(int irq, void *dev_id)
+{
+ struct sun50i_a100_ledc *priv = dev_id;
+ u32 val;
+
+ val = readl(priv->base + LEDC_INT_STS_REG);
+
+ if (val & LEDC_INT_STS_REG_TRANS_FINISH_INT) {
+ int next_length;
+
+ /* Start the next transfer if needed. */
+ spin_lock(&priv->lock);
+ next_length = priv->next_length;
+ if (next_length)
+ priv->next_length = 0;
+ else
+ priv->xfer_active = false;
+ spin_unlock(&priv->lock);
+
+ if (next_length)
+ sun50i_a100_ledc_start_xfer(priv, next_length);
+ } else if (val & LEDC_INT_STS_REG_FIFO_CPUREQ_INT) {
+ /* Continue the current transfer. */
+ sun50i_a100_ledc_pio_xfer(priv, 0);
+ }
+
+ writel(val, priv->base + LEDC_INT_STS_REG);
+
+ return IRQ_HANDLED;
+}
+
+static void sun50i_a100_ledc_brightness_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct sun50i_a100_ledc *priv = dev_get_drvdata(cdev->dev->parent);
+ struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
+ struct sun50i_a100_ledc_led *led = to_ledc_led(mc_cdev);
+ int addr = led - priv->leds;
+ unsigned long flags;
+ bool xfer_active;
+ int next_length;
+
+ led_mc_calc_color_components(mc_cdev, brightness);
+
+ priv->buffer[addr] = led->subled_info[0].brightness << 16 |
+ led->subled_info[1].brightness << 8 |
+ led->subled_info[2].brightness;
+
+ dev_dbg(priv->dev, "LED %d -> #%06x\n", addr, priv->buffer[addr]);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ next_length = max(priv->next_length, addr + 1);
+ xfer_active = priv->xfer_active;
+ if (xfer_active)
+ priv->next_length = next_length;
+ else
+ priv->xfer_active = true;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (!xfer_active)
+ sun50i_a100_ledc_start_xfer(priv, next_length);
+}
+
+static const char *const sun50i_a100_ledc_formats[] = {
+ "rgb",
+ "rbg",
+ "grb",
+ "gbr",
+ "brg",
+ "bgr",
+};
+
+static int sun50i_a100_ledc_parse_format(const struct device_node *np,
+ struct sun50i_a100_ledc *priv)
+{
+ const char *format = "grb";
+ u32 i;
+
+ of_property_read_string(np, "allwinner,pixel-format", &format);
+
+ for (i = 0; i < ARRAY_SIZE(sun50i_a100_ledc_formats); ++i) {
+ if (!strcmp(format, sun50i_a100_ledc_formats[i])) {
+ priv->format = i;
+ return 0;
+ }
+ }
+
+ dev_err(priv->dev, "Bad pixel format '%s'\n", format);
+
+ return -EINVAL;
+}
+
+static void sun50i_a100_ledc_set_format(struct sun50i_a100_ledc *priv)
+{
+ u32 val;
+
+ val = readl(priv->base + LEDC_CTRL_REG);
+ val &= ~LEDC_CTRL_REG_RGB_MODE;
+ val |= priv->format << 6;
+ writel(val, priv->base + LEDC_CTRL_REG);
+}
+
+static const struct sun50i_a100_ledc_timing sun50i_a100_ledc_default_timing = {
+ .t0h_ns = 336,
+ .t0l_ns = 840,
+ .t1h_ns = 882,
+ .t1l_ns = 294,
+ .treset_ns = 300000,
+};
+
+static int sun50i_a100_ledc_parse_timing(const struct device_node *np,
+ struct sun50i_a100_ledc *priv)
+{
+ struct sun50i_a100_ledc_timing *timing = &priv->timing;
+
+ *timing = sun50i_a100_ledc_default_timing;
+
+ of_property_read_u32(np, "allwinner,t0h-ns", &timing->t0h_ns);
+ of_property_read_u32(np, "allwinner,t0l-ns", &timing->t0l_ns);
+ of_property_read_u32(np, "allwinner,t1h-ns", &timing->t1h_ns);
+ of_property_read_u32(np, "allwinner,t1l-ns", &timing->t1l_ns);
+ of_property_read_u32(np, "allwinner,treset-ns", &timing->treset_ns);
+
+ return 0;
+}
+
+static void sun50i_a100_ledc_set_timing(struct sun50i_a100_ledc *priv)
+{
+ const struct sun50i_a100_ledc_timing *timing = &priv->timing;
+ unsigned long mod_freq = clk_get_rate(priv->mod_clk);
+ u32 cycle_ns = NSEC_PER_SEC / mod_freq;
+ u32 val;
+
+ val = (timing->t1h_ns / cycle_ns) << 21 |
+ (timing->t1l_ns / cycle_ns) << 16 |
+ (timing->t0h_ns / cycle_ns) << 6 |
+ (timing->t0l_ns / cycle_ns);
+ writel(val, priv->base + LEDC_T01_TIMING_CTRL_REG);
+
+ val = (timing->treset_ns / cycle_ns) << 16 |
+ (priv->num_leds - 1);
+ writel(val, priv->base + LEDC_RESET_TIMING_CTRL_REG);
+}
+
+static int sun50i_a100_ledc_resume(struct device *dev)
+{
+ struct sun50i_a100_ledc *priv = dev_get_drvdata(dev);
+ u32 val;
+ int ret;
+
+ ret = reset_control_deassert(priv->reset);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->bus_clk);
+ if (ret)
+ goto err_assert_reset;
+
+ ret = clk_prepare_enable(priv->mod_clk);
+ if (ret)
+ goto err_disable_bus_clk;
+
+ sun50i_a100_ledc_set_format(priv);
+ sun50i_a100_ledc_set_timing(priv);
+
+ /* The trigger level must be at least the burst length. */
+ val = readl(priv->base + LEDC_DMA_CTRL_REG);
+ val &= ~LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL;
+ val |= LEDC_FIFO_DEPTH / 2;
+ writel(val, priv->base + LEDC_DMA_CTRL_REG);
+
+ val = LEDC_INT_CTRL_REG_GLOBAL_INT_EN |
+ LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN;
+ writel(val, priv->base + LEDC_INT_CTRL_REG);
+
+ return 0;
+
+err_disable_bus_clk:
+ clk_disable_unprepare(priv->bus_clk);
+err_assert_reset:
+ reset_control_assert(priv->reset);
+
+ return ret;
+}
+
+static int sun50i_a100_ledc_suspend(struct device *dev)
+{
+ struct sun50i_a100_ledc *priv = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(priv->mod_clk);
+ clk_disable_unprepare(priv->bus_clk);
+ reset_control_assert(priv->reset);
+
+ return 0;
+}
+
+static void sun50i_a100_ledc_dma_cleanup(void *data)
+{
+ struct sun50i_a100_ledc *priv = data;
+ struct device *dma_dev = dmaengine_get_dma_device(priv->dma_chan);
+
+ if (priv->buffer)
+ dma_free_wc(dma_dev, LEDS_TO_BYTES(priv->num_leds),
+ priv->buffer, priv->dma_handle);
+ dma_release_channel(priv->dma_chan);
+}
+
+static int sun50i_a100_ledc_probe(struct platform_device *pdev)
+{
+ const struct device_node *np = pdev->dev.of_node;
+ struct dma_slave_config dma_cfg = {};
+ struct led_init_data init_data = {};
+ struct device *dev = &pdev->dev;
+ struct device_node *child;
+ struct sun50i_a100_ledc *priv;
+ struct resource *mem;
+ int count, irq, ret;
+
+ count = of_get_available_child_count(np);
+ if (!count)
+ return -ENODEV;
+ if (count > LEDC_MAX_LEDS) {
+ dev_err(dev, "Too many LEDs! (max is %d)\n", LEDC_MAX_LEDS);
+ return -EINVAL;
+ }
+
+ priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ priv->num_leds = count;
+ spin_lock_init(&priv->lock);
+ dev_set_drvdata(dev, priv);
+
+ ret = sun50i_a100_ledc_parse_format(np, priv);
+ if (ret)
+ return ret;
+
+ ret = sun50i_a100_ledc_parse_timing(np, priv);
+ if (ret)
+ return ret;
+
+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->bus_clk = devm_clk_get(dev, "bus");
+ if (IS_ERR(priv->bus_clk))
+ return PTR_ERR(priv->bus_clk);
+
+ priv->mod_clk = devm_clk_get(dev, "mod");
+ if (IS_ERR(priv->mod_clk))
+ return PTR_ERR(priv->mod_clk);
+
+ priv->reset = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(priv->reset))
+ return PTR_ERR(priv->reset);
+
+ priv->dma_chan = dma_request_chan(dev, "tx");
+ if (IS_ERR(priv->dma_chan))
+ return PTR_ERR(priv->dma_chan);
+
+ ret = devm_add_action_or_reset(dev, sun50i_a100_ledc_dma_cleanup, priv);
+ if (ret)
+ return ret;
+
+ dma_cfg.dst_addr = mem->start + LEDC_DATA_REG;
+ dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ dma_cfg.dst_maxburst = LEDC_FIFO_DEPTH / 2;
+ ret = dmaengine_slave_config(priv->dma_chan, &dma_cfg);
+ if (ret)
+ return ret;
+
+ priv->buffer = dma_alloc_wc(dmaengine_get_dma_device(priv->dma_chan),
+ LEDS_TO_BYTES(priv->num_leds),
+ &priv->dma_handle, GFP_KERNEL);
+ if (!priv->buffer)
+ return -ENOMEM;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(dev, irq, sun50i_a100_ledc_irq,
+ 0, dev_name(dev), priv);
+ if (ret)
+ return ret;
+
+ ret = sun50i_a100_ledc_resume(dev);
+ if (ret)
+ return ret;
+
+ for_each_available_child_of_node(np, child) {
+ struct sun50i_a100_ledc_led *led;
+ struct led_classdev *cdev;
+ u32 addr, color;
+
+ ret = of_property_read_u32(child, "reg", &addr);
+ if (ret || addr >= count) {
+ dev_err(dev, "LED 'reg' values must be from 0 to %d\n",
+ priv->num_leds - 1);
+ ret = -EINVAL;
+ goto err_put_child;
+ }
+
+ ret = of_property_read_u32(child, "color", &color);
+ if (ret || color != LED_COLOR_ID_RGB) {
+ dev_err(dev, "LED 'color' must be LED_COLOR_ID_RGB\n");
+ ret = -EINVAL;
+ goto err_put_child;
+ }
+
+ led = &priv->leds[addr];
+
+ led->subled_info[0].color_index = LED_COLOR_ID_RED;
+ led->subled_info[0].channel = 0;
+ led->subled_info[1].color_index = LED_COLOR_ID_GREEN;
+ led->subled_info[1].channel = 1;
+ led->subled_info[2].color_index = LED_COLOR_ID_BLUE;
+ led->subled_info[2].channel = 2;
+
+ led->mc_cdev.num_colors = ARRAY_SIZE(led->subled_info);
+ led->mc_cdev.subled_info = led->subled_info;
+
+ cdev = &led->mc_cdev.led_cdev;
+ cdev->max_brightness = U8_MAX;
+ cdev->brightness_set = sun50i_a100_ledc_brightness_set;
+
+ init_data.fwnode = of_fwnode_handle(child);
+
+ ret = devm_led_classdev_multicolor_register_ext(dev,
+ &led->mc_cdev,
+ &init_data);
+ if (ret) {
+ dev_err(dev, "Failed to register LED %u: %d\n",
+ addr, ret);
+ goto err_put_child;
+ }
+ }
+
+ dev_info(dev, "Registered %d LEDs\n", priv->num_leds);
+
+ return 0;
+
+err_put_child:
+ of_node_put(child);
+ sun50i_a100_ledc_suspend(&pdev->dev);
+
+ return ret;
+}
+
+static int sun50i_a100_ledc_remove(struct platform_device *pdev)
+{
+ sun50i_a100_ledc_suspend(&pdev->dev);
+
+ return 0;
+}
+
+static void sun50i_a100_ledc_shutdown(struct platform_device *pdev)
+{
+ sun50i_a100_ledc_suspend(&pdev->dev);
+}
+
+static const struct of_device_id sun50i_a100_ledc_of_match[] = {
+ { .compatible = "allwinner,sun50i-a100-ledc" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun50i_a100_ledc_of_match);
+
+static SIMPLE_DEV_PM_OPS(sun50i_a100_ledc_pm,
+ sun50i_a100_ledc_suspend, sun50i_a100_ledc_resume);
+
+static struct platform_driver sun50i_a100_ledc_driver = {
+ .probe = sun50i_a100_ledc_probe,
+ .remove = sun50i_a100_ledc_remove,
+ .shutdown = sun50i_a100_ledc_shutdown,
+ .driver = {
+ .name = "sun50i-a100-ledc",
+ .of_match_table = sun50i_a100_ledc_of_match,
+ .pm = pm_ptr(&sun50i_a100_ledc_pm),
+ },
+};
+module_platform_driver(sun50i_a100_ledc_driver);
+
+MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
+MODULE_DESCRIPTION("Allwinner A100 LED controller driver");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,38 @@
From 0040f071ab45d3098b2aad7e28e07593a5740782 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 25 Aug 2022 23:19:40 -0500
Subject: [PATCH 056/117] arm64: dts: allwinner: a100: Add LED controller node
Allwinner A100 contains an LED controller. Add it to the devicetree.
Commit-changes: 5
- New patch for v5
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -273,6 +273,20 @@
#size-cells = <0>;
};
+ ledc: led-controller@5018000 {
+ compatible = "allwinner,sun50i-a100-ledc";
+ reg = <0x5018000 0x400>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_LEDC>, <&ccu CLK_LEDC>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_LEDC>;
+ dmas = <&dma 42>;
+ dma-names = "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
ths: thermal-sensor@5070400 {
compatible = "allwinner,sun50i-a100-ths";
reg = <0x05070400 0x100>;

View File

@ -0,0 +1,53 @@
From 595f76548e1d51a76b1ab201293ef441233921cf Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 23:02:43 -0500
Subject: [PATCH 057/117] riscv: dts: allwinner: d1: Add LED controller node
Allwinner D1 contains an LED controller. Add its devicetree node, as
well as the pinmux used by the reference board design.
Commit-changes: 5
- New patch for v5
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 21 ++++++++++++++++++++
1 file changed, 21 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -116,6 +116,12 @@
};
/omit-if-no-ref/
+ ledc_pc0_pin: ledc-pc0-pin {
+ pins = "PC0";
+ function = "ledc";
+ };
+
+ /omit-if-no-ref/
mmc0_pins: mmc0-pins {
pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
function = "mmc0";
@@ -178,6 +184,21 @@
#reset-cells = <1>;
};
+ ledc: led-controller@2008000 {
+ compatible = "allwinner,sun20i-d1-ledc",
+ "allwinner,sun50i-a100-ledc";
+ reg = <0x2008000 0x400>;
+ interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_LEDC>, <&ccu CLK_LEDC>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_LEDC>;
+ dmas = <&dma 42>;
+ dma-names = "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
lradc: keys@2009800 {
compatible = "allwinner,sun20i-d1-lradc",
"allwinner,sun50i-r329-lradc";

View File

@ -0,0 +1,98 @@
From e6eb041b2099ec3d07a4ec391a06e86d7697c9d1 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 23:03:01 -0500
Subject: [PATCH 058/117] riscv: dts: allwinner: d1: Add RGB LEDs to boards
Some D1-based boards feature an onboard RGB LED. Enable them.
Commit-changes: 5
- New patch for v5
Series-version: 5
Series-to: Pavel Machek <pavel@ucw.cz>
Series-to: Chen-Yu Tsai <wens@csie.org>
Series-to: Jernej Skrabec <jernej.skrabec@gmail.com>
Series-to: linux-leds@vger.kernel.org
Series-cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Series-cc: Rob Herring <robh+dt@kernel.org>
Series-cc: devicetree@vger.kernel.org
Series-cc: linux-arm-kernel@lists.infradead.org
Series-cc: linux-kernel@vger.kernel.org
Series-cc: linux-riscv@lists.infradead.org
Series-cc: linux-sunxi@lists.linux.dev
Cover-letter:
leds: Allwinner A100 LED controller support
This series adds bindings and a driver for the RGB LED controller found
in some Allwinner SoCs, starting with A100. The hardware in the R329 and
D1 SoCs appears to be identical.
Patch 3 is included because the LED controller binding requires the DMA
properties. That patch was sent previously[1], but never got merged.
Patches 5-6 depend on the D1 devicetree series[2], but the rest of this
series can be merged without them.
This driver was tested on the D1 Nezha board.
[1]: https://lore.kernel.org/linux-arm-kernel/20201110040553.1381-7-frank@allwinnertech.com/
[2]: https://lore.kernel.org/linux-riscv/20220815050815.22340-1-samuel@sholland.org/
END
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts | 12 ++++++++++++
arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts | 13 +++++++++++++
2 files changed, 25 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
@@ -58,6 +58,18 @@
status = "okay";
};
+&ledc {
+ pinctrl-0 = <&ledc_pc0_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ multi-led@0 {
+ reg = <0x0>;
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_STATUS;
+ };
+};
+
&lradc {
status = "okay";
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
@@ -5,6 +5,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
#include "sun20i-d1.dtsi"
#include "sun20i-d1-common-regulators.dtsi"
@@ -90,6 +91,18 @@
};
};
+&ledc {
+ pinctrl-0 = <&ledc_pc0_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ multi-led@0 {
+ reg = <0x0>;
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_STATUS;
+ };
+};
+
&lradc {
status = "okay";

View File

@ -0,0 +1,40 @@
From effa2ef8717b0390e8fb0648e16df1b43610af53 Mon Sep 17 00:00:00 2001
From: Ban Tao <fengzheng923@gmail.com>
Date: Tue, 2 Mar 2021 20:40:23 +0800
Subject: [PATCH 059/117] pwm: sun8i-v536: document device tree bindings
This adds binding documentation for sun8i-v536 SoC PWM driver.
Signed-off-by: Ban Tao <fengzheng923@gmail.com>
---
.../bindings/pwm/pwm-sun8i-v536.txt | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/pwm-sun8i-v536.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-sun8i-v536.txt
@@ -0,0 +1,24 @@
+Allwinner sun8i-v536 SoC PWM controller
+
+Required properties:
+ - compatible: should be "allwinner,<name>-pwm"
+ "allwinner,sun8i-v833-pwm"
+ "allwinner,sun8i-v536-pwm"
+ "allwinner,sun50i-r818-pwm"
+ "allwinner,sun50i-a133-pwm"
+ "allwinner,sun50i-r329-pwm"
+ - reg: physical base address and length of the controller's registers
+ - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+ the cells format.
+ - clocks: From common clock binding, handle to the parent clock.
+ - resets: From reset clock binding, handle to the parent clock.
+
+Example:
+
+ pwm: pwm@300a0000 {
+ compatible = "allwinner,sun50i-r818-pwm";
+ reg = <0x0300a000 0x3ff>;
+ clocks = <&ccu CLK_BUS_PWM>;
+ resets = <&ccu RST_BUS_PWM>;
+ #pwm-cells = <3>;
+ };

View File

@ -0,0 +1,466 @@
From 4919e67557eaebb9f155950e7cac547a507b59e5 Mon Sep 17 00:00:00 2001
From: Ban Tao <fengzheng923@gmail.com>
Date: Tue, 2 Mar 2021 20:37:37 +0800
Subject: [PATCH 060/117] pwm: sunxi: Add Allwinner SoC PWM controller driver
The Allwinner R818, A133, R329, V536 and V833 has a new PWM controller
IP compared to the older Allwinner SoCs.
Signed-off-by: Ban Tao <fengzheng923@gmail.com>
---
MAINTAINERS | 6 +
drivers/pwm/Kconfig | 11 +
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-sun8i-v536.c | 401 +++++++++++++++++++++++++++++++++++
4 files changed, 419 insertions(+)
create mode 100644 drivers/pwm/pwm-sun8i-v536.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,12 @@ S: Maintained
F: Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml
F: drivers/hwspinlock/sun6i_hwspinlock.c
+ALLWINNER PWM DRIVER
+M: Ban Tao <fengzheng923@gmail.com>
+L: linux-pwm@vger.kernel.org
+S: Maintained
+F: drivers/pwm/pwm-sun8i-v536.c
+
ALLWINNER THERMAL DRIVER
M: Vasily Khoruzhick <anarsoul@gmail.com>
M: Yangtao Li <tiny.windzz@gmail.com>
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -582,6 +582,17 @@ config PWM_SUN4I
To compile this driver as a module, choose M here: the module
will be called pwm-sun4i.
+config PWM_SUN8I_V536
+ tristate "Allwinner SUN8I_V536 PWM support"
+ depends on ARCH_SUNXI || COMPILE_TEST
+ depends on HAS_IOMEM && COMMON_CLK
+ help
+ Enhanced PWM framework driver for Allwinner R818, A133, R329,
+ V536 and V833 SoCs.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-sun8i-v536.
+
config PWM_SUNPLUS
tristate "Sunplus PWM support"
depends on ARCH_SUNPLUS || COMPILE_TEST
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_PWM_STM32) += pwm-stm32.o
obj-$(CONFIG_PWM_STM32_LP) += pwm-stm32-lp.o
obj-$(CONFIG_PWM_STMPE) += pwm-stmpe.o
obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o
+obj-$(CONFIG_PWM_SUN8I_V536) += pwm-sun8i-v536.o
obj-$(CONFIG_PWM_SUNPLUS) += pwm-sunplus.o
obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
--- /dev/null
+++ b/drivers/pwm/pwm-sun8i-v536.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for Allwinner sun8i-v536 Pulse Width Modulation Controller
+ *
+ * Copyright (C) 2021 Ban Tao <fengzheng923@gmail.com>
+ *
+ *
+ * Limitations:
+ * - When PWM is disabled, the output is driven to inactive.
+ * - If the register is reconfigured while PWM is running,
+ * it does not complete the currently running period.
+ * - If the user input duty is beyond acceptible limits,
+ * -EINVAL is returned.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pwm.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define PWM_GET_CLK_OFFSET(chan) (0x20 + ((chan >> 1) * 0x4))
+#define PWM_CLK_APB_SCR BIT(7)
+#define PWM_DIV_M 0
+#define PWM_DIV_M_MASK GENMASK(3, PWM_DIV_M)
+
+#define PWM_CLK_REG 0x40
+#define PWM_CLK_GATING BIT(0)
+
+#define PWM_ENABLE_REG 0x80
+#define PWM_EN BIT(0)
+
+#define PWM_CTL_REG(chan) (0x100 + 0x20 * chan)
+#define PWM_ACT_STA BIT(8)
+#define PWM_PRESCAL_K 0
+#define PWM_PRESCAL_K_MASK GENMASK(7, PWM_PRESCAL_K)
+
+#define PWM_PERIOD_REG(chan) (0x104 + 0x20 * chan)
+#define PWM_ENTIRE_CYCLE 16
+#define PWM_ENTIRE_CYCLE_MASK GENMASK(31, PWM_ENTIRE_CYCLE)
+#define PWM_ACT_CYCLE 0
+#define PWM_ACT_CYCLE_MASK GENMASK(15, PWM_ACT_CYCLE)
+
+#define BIT_CH(bit, chan) ((bit) << (chan))
+#define SET_BITS(shift, mask, reg, val) \
+ (((reg) & ~mask) | (val << (shift)))
+
+#define PWM_OSC_CLK 24000000
+#define PWM_PRESCALER_MAX 256
+#define PWM_CLK_DIV_M__MAX 9
+#define PWM_ENTIRE_CYCLE_MAX 65536
+
+struct sun8i_pwm_data {
+ unsigned int npwm;
+};
+
+struct sun8i_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ struct reset_control *rst_clk;
+ void __iomem *base;
+ const struct sun8i_pwm_data *data;
+};
+
+static inline struct sun8i_pwm_chip *to_sun8i_pwm_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct sun8i_pwm_chip, chip);
+}
+
+static inline u32 sun8i_pwm_readl(struct sun8i_pwm_chip *chip,
+ unsigned long offset)
+{
+ return readl(chip->base + offset);
+}
+
+static inline void sun8i_pwm_writel(struct sun8i_pwm_chip *chip,
+ u32 val, unsigned long offset)
+{
+ writel(val, chip->base + offset);
+}
+
+static void sun8i_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip);
+ u64 clk_rate;
+ u32 tmp, entire_cycles, active_cycles;
+ unsigned int prescaler, div_m;
+
+ tmp = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+ if (tmp & PWM_CLK_APB_SCR)
+ clk_rate = clk_get_rate(pc->clk);
+ else
+ clk_rate = PWM_OSC_CLK;
+
+ tmp = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+ div_m = 0x1 << (tmp & PWM_DIV_M_MASK);
+
+ tmp = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm));
+ prescaler = (tmp & PWM_PRESCAL_K_MASK) + 1;
+
+ tmp = sun8i_pwm_readl(pc, PWM_PERIOD_REG(pwm->hwpwm));
+ entire_cycles = (tmp >> PWM_ENTIRE_CYCLE) + 1;
+ active_cycles = (tmp & PWM_ACT_CYCLE_MASK);
+
+ /* (clk / div_m / prescaler) / entire_cycles = NSEC_PER_SEC / period_ns. */
+ state->period = DIV_ROUND_CLOSEST_ULL(entire_cycles * NSEC_PER_SEC,
+ clk_rate) * div_m * prescaler;
+ /* duty_ns / period_ns = active_cycles / entire_cycles. */
+ state->duty_cycle = DIV_ROUND_CLOSEST_ULL(active_cycles * state->period,
+ entire_cycles);
+
+ /* parsing polarity */
+ tmp = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm));
+ if (tmp & PWM_ACT_STA)
+ state->polarity = PWM_POLARITY_NORMAL;
+ else
+ state->polarity = PWM_POLARITY_INVERSED;
+
+ /* parsing enabled */
+ tmp = sun8i_pwm_readl(pc, PWM_ENABLE_REG);
+ if (tmp & BIT_CH(PWM_EN, pwm->hwpwm))
+ state->enabled = true;
+ else
+ state->enabled = false;
+
+ dev_dbg(chip->dev, "duty_ns=%lld period_ns=%lld polarity=%s enabled=%s.\n",
+ state->duty_cycle, state->period,
+ state->polarity ? "inversed":"normal",
+ state->enabled ? "true":"false");
+}
+
+static void sun8i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+ enum pwm_polarity polarity)
+{
+ struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip);
+ u32 temp;
+
+ temp = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm));
+
+ if (polarity == PWM_POLARITY_NORMAL)
+ temp |= PWM_ACT_STA;
+ else
+ temp &= ~PWM_ACT_STA;
+
+ sun8i_pwm_writel(pc, temp, PWM_CTL_REG(pwm->hwpwm));
+}
+
+static int sun8i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip);
+ unsigned long long c;
+ unsigned long entire_cycles, active_cycles;
+ unsigned int div_m, prescaler;
+ u64 duty_ns = state->duty_cycle, period_ns = state->period;
+ u32 config;
+ int ret = 0;
+
+ if (period_ns > 334) {
+ /* if freq < 3M, then select 24M clock */
+ c = PWM_OSC_CLK;
+ config = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+ config &= ~PWM_CLK_APB_SCR;
+ sun8i_pwm_writel(pc, config, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+ } else {
+ /* if freq > 3M, then select APB as clock */
+ c = clk_get_rate(pc->clk);
+ config = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+ config |= PWM_CLK_APB_SCR;
+ sun8i_pwm_writel(pc, config, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+ }
+
+ dev_dbg(chip->dev, "duty_ns=%lld period_ns=%lld c =%llu.\n",
+ duty_ns, period_ns, c);
+
+ /*
+ * (clk / div_m / prescaler) / entire_cycles = NSEC_PER_SEC / period_ns.
+ * So, entire_cycles = clk * period_ns / NSEC_PER_SEC / div_m / prescaler.
+ */
+ c = c * period_ns;
+ c = DIV_ROUND_CLOSEST_ULL(c, NSEC_PER_SEC);
+ for (div_m = 0; div_m < PWM_CLK_DIV_M__MAX; div_m++) {
+ for (prescaler = 0; prescaler < PWM_PRESCALER_MAX; prescaler++) {
+ /*
+ * actual prescaler = prescaler(reg value) + 1.
+ * actual div_m = 0x1 << div_m(reg value).
+ */
+ entire_cycles = ((unsigned long)c >> div_m)/(prescaler + 1);
+ if (entire_cycles <= PWM_ENTIRE_CYCLE_MAX)
+ goto calc_end;
+ }
+ }
+ ret = -EINVAL;
+ goto exit;
+
+calc_end:
+ /*
+ * duty_ns / period_ns = active_cycles / entire_cycles.
+ * So, active_cycles = entire_cycles * duty_ns / period_ns.
+ */
+ c = (unsigned long long)entire_cycles * duty_ns;
+ c = DIV_ROUND_CLOSEST_ULL(c, period_ns);
+ active_cycles = c;
+ if (entire_cycles == 0)
+ entire_cycles++;
+
+ /* config clk div_m*/
+ config = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+ config = SET_BITS(PWM_DIV_M, PWM_DIV_M_MASK, config, div_m);
+ sun8i_pwm_writel(pc, config, PWM_GET_CLK_OFFSET(pwm->hwpwm));
+
+ /* config prescaler */
+ config = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm));
+ config = SET_BITS(PWM_PRESCAL_K, PWM_PRESCAL_K_MASK, config, prescaler);
+ sun8i_pwm_writel(pc, config, PWM_CTL_REG(pwm->hwpwm));
+
+ /* config active and period cycles */
+ config = sun8i_pwm_readl(pc, PWM_PERIOD_REG(pwm->hwpwm));
+ config = SET_BITS(PWM_ACT_CYCLE, PWM_ACT_CYCLE_MASK, config, active_cycles);
+ config = SET_BITS(PWM_ENTIRE_CYCLE, PWM_ENTIRE_CYCLE_MASK,
+ config, (entire_cycles - 1));
+ sun8i_pwm_writel(pc, config, PWM_PERIOD_REG(pwm->hwpwm));
+
+ dev_dbg(chip->dev, "active_cycles=%lu entire_cycles=%lu prescaler=%u div_m=%u\n",
+ active_cycles, entire_cycles, prescaler, div_m);
+
+exit:
+ return ret;
+}
+
+static void sun8i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm,
+ bool enable)
+{
+ struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip);
+ u32 clk, pwm_en;
+
+ clk = sun8i_pwm_readl(pc, PWM_CLK_REG);
+ pwm_en = sun8i_pwm_readl(pc, PWM_ENABLE_REG);
+
+ if (enable) {
+ clk |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
+ sun8i_pwm_writel(pc, clk, PWM_CLK_REG);
+
+ pwm_en |= BIT_CH(PWM_EN, pwm->hwpwm);
+ sun8i_pwm_writel(pc, pwm_en, PWM_ENABLE_REG);
+ } else {
+ pwm_en &= ~BIT_CH(PWM_EN, pwm->hwpwm);
+ sun8i_pwm_writel(pc, pwm_en, PWM_ENABLE_REG);
+
+ clk &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
+ sun8i_pwm_writel(pc, clk, PWM_CLK_REG);
+ }
+}
+
+static int sun8i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct pwm_state curstate;
+ int ret;
+
+ pwm_get_state(pwm, &curstate);
+
+ ret = sun8i_pwm_config(chip, pwm, state);
+
+ if (state->polarity != curstate.polarity)
+ sun8i_pwm_set_polarity(chip, pwm, state->polarity);
+
+ if (state->enabled != curstate.enabled)
+ sun8i_pwm_enable(chip, pwm, state->enabled);
+
+ return ret;
+}
+
+static const struct pwm_ops sun8i_pwm_ops = {
+ .get_state = sun8i_pwm_get_state,
+ .apply = sun8i_pwm_apply,
+ .owner = THIS_MODULE,
+};
+
+static const struct sun8i_pwm_data sun8i_pwm_data_c9 = {
+ .npwm = 9,
+};
+
+static const struct sun8i_pwm_data sun50i_pwm_data_c16 = {
+ .npwm = 16,
+};
+
+static const struct of_device_id sun8i_pwm_dt_ids[] = {
+ {
+ .compatible = "allwinner,sun8i-v536-pwm",
+ .data = &sun8i_pwm_data_c9,
+ }, {
+ .compatible = "allwinner,sun50i-r818-pwm",
+ .data = &sun50i_pwm_data_c16,
+ }, {
+ /* sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(of, sun8i_pwm_dt_ids);
+
+static int sun8i_pwm_probe(struct platform_device *pdev)
+{
+ struct sun8i_pwm_chip *pc;
+ int ret;
+
+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return dev_err_probe(&pdev->dev, -ENOMEM,
+ "memory allocation failed\n");
+
+ pc->data = of_device_get_match_data(&pdev->dev);
+ if (!pc->data)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "can't get match data\n");
+
+ pc->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pc->base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pc->base),
+ "can't remap pwm resource\n");
+
+ pc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pc->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk),
+ "get clock failed\n");
+
+ pc->rst_clk = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(pc->rst_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pc->rst_clk),
+ "get reset failed\n");
+
+ /* Deassert reset */
+ ret = reset_control_deassert(pc->rst_clk);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "cannot deassert reset control\n");
+
+ ret = clk_prepare_enable(pc->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot prepare and enable clk %pe\n",
+ ERR_PTR(ret));
+ goto err_clk;
+ }
+
+ pc->chip.dev = &pdev->dev;
+ pc->chip.ops = &sun8i_pwm_ops;
+ pc->chip.npwm = pc->data->npwm;
+ pc->chip.of_xlate = of_pwm_xlate_with_flags;
+ pc->chip.base = -1;
+ pc->chip.of_pwm_n_cells = 3;
+
+ ret = pwmchip_add(&pc->chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+ goto err_pwm_add;
+ }
+
+ platform_set_drvdata(pdev, pc);
+
+ return 0;
+
+err_pwm_add:
+ clk_disable_unprepare(pc->clk);
+err_clk:
+ reset_control_assert(pc->rst_clk);
+
+ return ret;
+}
+
+static int sun8i_pwm_remove(struct platform_device *pdev)
+{
+ struct sun8i_pwm_chip *pc = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = pwmchip_remove(&pc->chip);
+ if (ret)
+ return ret;
+
+ clk_disable_unprepare(pc->clk);
+ reset_control_assert(pc->rst_clk);
+
+ return 0;
+}
+
+static struct platform_driver sun8i_pwm_driver = {
+ .driver = {
+ .name = "sun8i-pwm-v536",
+ .of_match_table = sun8i_pwm_dt_ids,
+ },
+ .probe = sun8i_pwm_probe,
+ .remove = sun8i_pwm_remove,
+};
+module_platform_driver(sun8i_pwm_driver);
+
+MODULE_ALIAS("platform:sun8i-v536-pwm");
+MODULE_AUTHOR("Ban Tao <fengzheng923@gmail.com>");
+MODULE_DESCRIPTION("Allwinner sun8i-v536 PWM driver");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,43 @@
From 2f452dd6047126c42a0ad32ef0f10145c6047d66 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 6 Jun 2021 11:05:20 -0500
Subject: [PATCH 061/117] squash? pwm: sunxi: Add Allwinner SoC PWM controller
driver
---
drivers/pwm/Kconfig | 4 ++--
drivers/pwm/pwm-sun8i-v536.c | 6 +-----
2 files changed, 3 insertions(+), 7 deletions(-)
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -583,11 +583,11 @@ config PWM_SUN4I
will be called pwm-sun4i.
config PWM_SUN8I_V536
- tristate "Allwinner SUN8I_V536 PWM support"
+ tristate "Allwinner SUN8I V536 enhanced PWM support"
depends on ARCH_SUNXI || COMPILE_TEST
depends on HAS_IOMEM && COMMON_CLK
help
- Enhanced PWM framework driver for Allwinner R818, A133, R329,
+ Enhanced PWM framework driver for Allwinner A133, D1, R329, R818,
V536 and V833 SoCs.
To compile this driver as a module, choose M here: the module
--- a/drivers/pwm/pwm-sun8i-v536.c
+++ b/drivers/pwm/pwm-sun8i-v536.c
@@ -373,12 +373,8 @@ err_clk:
static int sun8i_pwm_remove(struct platform_device *pdev)
{
struct sun8i_pwm_chip *pc = platform_get_drvdata(pdev);
- int ret;
-
- ret = pwmchip_remove(&pc->chip);
- if (ret)
- return ret;
+ pwmchip_remove(&pc->chip);
clk_disable_unprepare(pc->clk);
reset_control_assert(pc->rst_clk);

View File

@ -0,0 +1,33 @@
From 8bb576d8640fdf896650a4d4a1b2e60254d75eb2 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 6 Jun 2021 10:56:25 -0500
Subject: [PATCH 062/117] pwm: sun8i-v536: Add support for the Allwinner D1
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/pwm/pwm-sun8i-v536.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/pwm/pwm-sun8i-v536.c
+++ b/drivers/pwm/pwm-sun8i-v536.c
@@ -285,6 +285,10 @@ static const struct sun8i_pwm_data sun8i
.npwm = 9,
};
+static const struct sun8i_pwm_data sun20i_pwm_data_c8 = {
+ .npwm = 8,
+};
+
static const struct sun8i_pwm_data sun50i_pwm_data_c16 = {
.npwm = 16,
};
@@ -294,6 +298,9 @@ static const struct of_device_id sun8i_p
.compatible = "allwinner,sun8i-v536-pwm",
.data = &sun8i_pwm_data_c9,
}, {
+ .compatible = "allwinner,sun20i-d1-pwm",
+ .data = &sun20i_pwm_data_c8,
+ }, {
.compatible = "allwinner,sun50i-r818-pwm",
.data = &sun50i_pwm_data_c16,
}, {

View File

@ -0,0 +1,61 @@
From 2ee8994e4db3978261e6c644e897400c4df5edeb Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 22:24:52 -0500
Subject: [PATCH 063/117] riscv: dts: allwinner: d1: Add PWM support
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 35 ++++++++++++++++++++
1 file changed, 35 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -155,6 +155,30 @@
};
/omit-if-no-ref/
+ pwm0_pd16_pin: pwm0-pd16-pin {
+ pins = "PD16";
+ function = "pwm0";
+ };
+
+ /omit-if-no-ref/
+ pwm2_pd18_pin: pwm2-pd18-pin {
+ pins = "PD18";
+ function = "pwm2";
+ };
+
+ /omit-if-no-ref/
+ pwm4_pd20_pin: pwm4-pd20-pin {
+ pins = "PD20";
+ function = "pwm4";
+ };
+
+ /omit-if-no-ref/
+ pwm7_pd22_pin: pwm7-pd22-pin {
+ pins = "PD22";
+ function = "pwm7";
+ };
+
+ /omit-if-no-ref/
uart0_pb8_pins: uart0-pb8-pins {
pins = "PB8", "PB9";
function = "uart0";
@@ -173,6 +197,17 @@
};
};
+ pwm: pwm@2000c00 {
+ compatible = "allwinner,sun20i-d1-pwm";
+ reg = <0x2000c00 0x400>;
+ interrupts = <34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_PWM>, <&osc24M>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_PWM>;
+ status = "disabled";
+ #pwm-cells = <3>;
+ };
+
ccu: clock-controller@2001000 {
compatible = "allwinner,sun20i-d1-ccu";
reg = <0x2001000 0x1000>;

View File

@ -0,0 +1,124 @@
From 5479c8efb6ffbbc8b7fd1068337037faf9c20a36 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 22:25:40 -0500
Subject: [PATCH 064/117] riscv: dts: allwinner: d1: Hook up PWM-controlled CPU
voltage regulators
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../allwinner/sun20i-d1-clockworkpi-v3.14.dts | 19 +++++++++++--------
.../sun20i-d1-dongshan-nezha-stu.dts | 19 +++++++++++--------
.../boot/dts/allwinner/sun20i-d1-nezha.dts | 19 +++++++++++--------
3 files changed, 33 insertions(+), 24 deletions(-)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
@@ -48,16 +48,13 @@
};
};
- /*
- * This regulator is PWM-controlled, but the PWM controller is not
- * yet supported, so fix the regulator to its default voltage.
- */
reg_vdd_cpu: vdd-cpu {
- compatible = "regulator-fixed";
+ compatible = "pwm-regulator";
+ pwms = <&pwm 0 50000 0>;
+ pwm-supply = <&reg_vcc>;
regulator-name = "vdd-cpu";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- vin-supply = <&reg_vcc>;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1160000>;
};
wifi_pwrseq: wifi-pwrseq {
@@ -254,6 +251,12 @@
};
};
+&pwm {
+ pinctrl-0 = <&pwm0_pd16_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&uart0 {
pinctrl-0 = <&uart0_pb8_pins>;
pinctrl-names = "default";
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-dongshan-nezha-stu.dts
@@ -43,16 +43,13 @@
vin-supply = <&reg_vcc>;
};
- /*
- * This regulator is PWM-controlled, but the PWM controller is not
- * yet supported, so fix the regulator to its default voltage.
- */
reg_vdd_cpu: vdd-cpu {
- compatible = "regulator-fixed";
+ compatible = "pwm-regulator";
+ pwms = <&pwm 0 50000 0>;
+ pwm-supply = <&reg_vcc>;
regulator-name = "vdd-cpu";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- vin-supply = <&reg_vcc>;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1160000>;
};
};
@@ -95,6 +92,12 @@
status = "okay";
};
+&pwm {
+ pinctrl-0 = <&pwm0_pd16_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&uart0 {
pinctrl-0 = <&uart0_pb8_pins>;
pinctrl-names = "default";
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
@@ -35,16 +35,13 @@
vin-supply = <&reg_vcc>;
};
- /*
- * This regulator is PWM-controlled, but the PWM controller is not
- * yet supported, so fix the regulator to its default voltage.
- */
reg_vdd_cpu: vdd-cpu {
- compatible = "regulator-fixed";
+ compatible = "pwm-regulator";
+ pwms = <&pwm 0 50000 0>;
+ pwm-supply = <&reg_vcc>;
regulator-name = "vdd-cpu";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- vin-supply = <&reg_vcc>;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1160000>;
};
wifi_pwrseq: wifi-pwrseq {
@@ -155,6 +152,12 @@
status = "okay";
};
+&pwm {
+ pinctrl-0 = <&pwm0_pd16_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&uart0 {
pinctrl-0 = <&uart0_pb8_pins>;
pinctrl-names = "default";

View File

@ -0,0 +1,38 @@
From 29360e65c326ea8bbac6e63b42aa91fb8f14d3bf Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 22:57:13 -0500
Subject: [PATCH 065/117] riscv: dts: allwinner: mangopi-mq-pro: Add PWM LED
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-mangopi-mq-pro.dts
@@ -4,6 +4,7 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
#include "sun20i-d1.dtsi"
#include "sun20i-d1-common-regulators.dtsi"
@@ -22,6 +23,17 @@
stdout-path = "serial0:115200n8";
};
+ leds {
+ compatible = "pwm-leds";
+
+ led {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_STATUS;
+ max-brightness = <255>;
+ pwms = <&pwm 2 50000 0>;
+ };
+ };
+
reg_avdd2v8: avdd2v8 {
compatible = "regulator-fixed";
regulator-name = "avdd2v8";

View File

@ -0,0 +1,24 @@
From bccb19038038c7377275d74bb815f5f9363ba2e3 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 13 Nov 2021 10:08:41 -0600
Subject: [PATCH 066/117] ASoC: dt-bindings: sun4i-spdif: Require resets for H6
The H6 variant has a module reset, and it is used by the driver. So the
resets property should be required in the binding for this variant.
Fixes: b20453031472 ("dt-bindings: sound: sun4i-spdif: Add Allwinner H6 compatible")
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml | 1 +
1 file changed, 1 insertion(+)
--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
@@ -61,6 +61,7 @@ allOf:
enum:
- allwinner,sun6i-a31-spdif
- allwinner,sun8i-h3-spdif
+ - allwinner,sun50i-h6-spdif
then:
required:

View File

@ -0,0 +1,94 @@
From 4e72722bfb7dec028e11278a924bb8bef3e10897 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 13 Nov 2021 10:48:24 -0600
Subject: [PATCH 067/117] ASoC: dt-bindings: sun4i-spdif: Add compatible for D1
D1 mostly keeps the existing register layout, but it separates the
module clock into separate clocks for the RX block and the TX block.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../sound/allwinner,sun4i-a10-spdif.yaml | 54 +++++++++++++++----
1 file changed, 44 insertions(+), 10 deletions(-)
--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
@@ -18,10 +18,12 @@ properties:
compatible:
oneOf:
- - const: allwinner,sun4i-a10-spdif
- - const: allwinner,sun6i-a31-spdif
- - const: allwinner,sun8i-h3-spdif
- - const: allwinner,sun50i-h6-spdif
+ - enum:
+ - allwinner,sun4i-a10-spdif
+ - allwinner,sun6i-a31-spdif
+ - allwinner,sun8i-h3-spdif
+ - allwinner,sun20i-d1-spdif
+ - allwinner,sun50i-h6-spdif
- items:
- const: allwinner,sun8i-a83t-spdif
- const: allwinner,sun8i-h3-spdif
@@ -36,14 +38,12 @@ properties:
maxItems: 1
clocks:
- items:
- - description: Bus Clock
- - description: Module Clock
+ minItems: 2
+ maxItems: 3
clock-names:
- items:
- - const: apb
- - const: spdif
+ minItems: 2
+ maxItems: 3
# Even though it only applies to subschemas under the conditionals,
# not listing them here will trigger a warning because of the
@@ -59,8 +59,42 @@ allOf:
compatible:
contains:
enum:
+ - allwinner,sun20i-d1-spdif
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: Bus Clock
+ - description: RX Module Clock
+ - description: TX Module Clock
+
+ clock-names:
+ items:
+ - const: apb
+ - const: rx
+ - const: tx
+
+ else:
+ properties:
+ clocks:
+ items:
+ - description: Bus Clock
+ - description: Module Clock
+
+ clock-names:
+ items:
+ - const: apb
+ - const: spdif
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- allwinner,sun6i-a31-spdif
- allwinner,sun8i-h3-spdif
+ - allwinner,sun20i-d1-spdif
- allwinner,sun50i-h6-spdif
then:

View File

@ -0,0 +1,30 @@
From 1d85b3609cf4239f7e971b839f1ab985413cd560 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 13 Nov 2021 11:12:14 -0600
Subject: [PATCH 068/117] ASoC: sun4i-spdif: Assert reset when removing the
device
This completes reversing the process done in the probe function.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun4i-spdif.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -705,10 +705,14 @@ err_unregister:
static int sun4i_spdif_remove(struct platform_device *pdev)
{
+ struct sun4i_spdif_dev *host = dev_get_drvdata(&pdev->dev);
+
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
sun4i_spdif_runtime_suspend(&pdev->dev);
+ reset_control_assert(host->rst);
+
return 0;
}

View File

@ -0,0 +1,78 @@
From 0efd742482dbe4b17a441eab5c57231d65f9a852 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 13 Nov 2021 11:14:30 -0600
Subject: [PATCH 069/117] ASoC: sun4i-spdif: Simplify code around optional
resets
The driver does not need to care about which variants have a reset;
the devicetree binding already enforces that the necessary resources are
provided. Simplify the logic by always calling the optional getter,
which will return NULL if no reset reference is found.
Also clean up the error handling, which should not print a misleading
error in the EPROBE_DEFER case.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun4i-spdif.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -170,12 +170,10 @@
* struct sun4i_spdif_quirks - Differences between SoC variants.
*
* @reg_dac_txdata: TX FIFO offset for DMA config.
- * @has_reset: SoC needs reset deasserted.
* @val_fctl_ftx: TX FIFO flush bitmask.
*/
struct sun4i_spdif_quirks {
unsigned int reg_dac_txdata;
- bool has_reset;
unsigned int val_fctl_ftx;
};
@@ -546,19 +544,16 @@ static const struct sun4i_spdif_quirks s
static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = {
.reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
.val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
- .has_reset = true,
};
static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = {
.reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
.val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
- .has_reset = true,
};
static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = {
.reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
.val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX,
- .has_reset = true,
};
static const struct of_device_id sun4i_spdif_of_match[] = {
@@ -667,17 +662,12 @@ static int sun4i_spdif_probe(struct plat
platform_set_drvdata(pdev, host);
- if (quirks->has_reset) {
- host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
- NULL);
- if (PTR_ERR(host->rst) == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
- dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
- return ret;
- }
- if (!IS_ERR(host->rst))
- reset_control_deassert(host->rst);
- }
+ host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(host->rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(host->rst),
+ "Failed to get reset\n");
+
+ reset_control_deassert(host->rst);
ret = devm_snd_soc_register_component(&pdev->dev,
&sun4i_spdif_component, &sun4i_spdif_dai, 1);

View File

@ -0,0 +1,116 @@
From b42a9e0cf6b0ca78b4ef5310de967d515a3cca03 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 13 Jun 2021 23:53:16 -0500
Subject: [PATCH 070/117] ASoC: sun4i-spdif: Add support for separate RX/TX
clocks
On older variants of the hardware, the RX and TX blocks share a single
module clock, named "spdif" in the DT binding. The D1 variant has
separate RX and TX clocks, so the TX module clock is named "tx" in the
binding. To support this, supply the clock name in the quirks structure.
Since the driver supports only TX, only the TX clock name is needed.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun4i-spdif.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -169,18 +169,20 @@
/**
* struct sun4i_spdif_quirks - Differences between SoC variants.
*
+ * @tx_clk_name: firmware name for the TX clock reference.
* @reg_dac_txdata: TX FIFO offset for DMA config.
* @val_fctl_ftx: TX FIFO flush bitmask.
*/
struct sun4i_spdif_quirks {
+ const char *tx_clk_name;
unsigned int reg_dac_txdata;
unsigned int val_fctl_ftx;
};
struct sun4i_spdif_dev {
struct platform_device *pdev;
- struct clk *spdif_clk;
struct clk *apb_clk;
+ struct clk *tx_clk;
struct reset_control *rst;
struct snd_soc_dai_driver cpu_dai_drv;
struct regmap *regmap;
@@ -313,7 +315,7 @@ static int sun4i_spdif_hw_params(struct
return -EINVAL;
}
- ret = clk_set_rate(host->spdif_clk, mclk);
+ ret = clk_set_rate(host->tx_clk, mclk);
if (ret < 0) {
dev_err(&pdev->dev,
"Setting SPDIF clock rate for %d Hz failed!\n", mclk);
@@ -537,21 +539,25 @@ static struct snd_soc_dai_driver sun4i_s
};
static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = {
+ .tx_clk_name = "spdif",
.reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
.val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
};
static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = {
+ .tx_clk_name = "spdif",
.reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
.val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
};
static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = {
+ .tx_clk_name = "spdif",
.reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
.val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
};
static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = {
+ .tx_clk_name = "spdif",
.reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
.val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX,
};
@@ -586,7 +592,7 @@ static int sun4i_spdif_runtime_suspend(s
{
struct sun4i_spdif_dev *host = dev_get_drvdata(dev);
- clk_disable_unprepare(host->spdif_clk);
+ clk_disable_unprepare(host->tx_clk);
clk_disable_unprepare(host->apb_clk);
return 0;
@@ -597,12 +603,12 @@ static int sun4i_spdif_runtime_resume(st
struct sun4i_spdif_dev *host = dev_get_drvdata(dev);
int ret;
- ret = clk_prepare_enable(host->spdif_clk);
+ ret = clk_prepare_enable(host->tx_clk);
if (ret)
return ret;
ret = clk_prepare_enable(host->apb_clk);
if (ret)
- clk_disable_unprepare(host->spdif_clk);
+ clk_disable_unprepare(host->tx_clk);
return ret;
}
@@ -650,10 +656,10 @@ static int sun4i_spdif_probe(struct plat
return PTR_ERR(host->apb_clk);
}
- host->spdif_clk = devm_clk_get(&pdev->dev, "spdif");
- if (IS_ERR(host->spdif_clk)) {
- dev_err(&pdev->dev, "failed to get a spdif clock.\n");
- return PTR_ERR(host->spdif_clk);
+ host->tx_clk = devm_clk_get(&pdev->dev, quirks->tx_clk_name);
+ if (IS_ERR(host->tx_clk)) {
+ dev_err(&pdev->dev, "failed to get TX module clock.\n");
+ return PTR_ERR(host->tx_clk);
}
host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata;

View File

@ -0,0 +1,40 @@
From af01261bf4e334cad158519291e5bc38765c955f Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 13 Jun 2021 23:53:26 -0500
Subject: [PATCH 071/117] ASoC: sun4i-spdif: Add support for the D1 variant
The D1 variant is similar to the H6 variant, except for its clock setup.
The clock tree changes impact some register fields on the RX side, but
those are not yet relevant, because RX is not supported by this driver.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun4i-spdif.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -556,6 +556,12 @@ static const struct sun4i_spdif_quirks s
.val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
};
+static const struct sun4i_spdif_quirks sun20i_d1_spdif_quirks = {
+ .tx_clk_name = "tx",
+ .reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
+ .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX,
+};
+
static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = {
.tx_clk_name = "spdif",
.reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
@@ -576,6 +582,10 @@ static const struct of_device_id sun4i_s
.data = &sun8i_h3_spdif_quirks,
},
{
+ .compatible = "allwinner,sun20i-d1-spdif",
+ .data = &sun20i_d1_spdif_quirks,
+ },
+ {
.compatible = "allwinner,sun50i-h6-spdif",
.data = &sun50i_h6_spdif_quirks,
},

View File

@ -0,0 +1,35 @@
From 36153e325aa912268a5a5d4574dc7092e67c8008 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 17 Aug 2022 01:54:46 -0500
Subject: [PATCH 072/117] riscv: dts: allwinner: d1: Add SPDIF support
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -333,6 +333,22 @@
#sound-dai-cells = <0>;
};
+ // TODO: add receive functionality
+ spdif: spdif@2036000 {
+ compatible = "allwinner,sun20i-d1-spdif";
+ reg = <0x2036000 0x400>;
+ interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPDIF>,
+ <&ccu CLK_SPDIF_RX>,
+ <&ccu CLK_SPDIF_TX>;
+ clock-names = "apb", "rx", "tx";
+ resets = <&ccu RST_BUS_SPDIF>;
+ dmas = <&dma 2>, <&dma 2>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
timer: timer@2050000 {
compatible = "allwinner,sun20i-d1-timer",
"allwinner,sun8i-a23-timer";

View File

@ -0,0 +1,34 @@
From c2b3f2c723e1b558afe5661bb91669e3b68154f7 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 13 Jun 2021 23:52:47 -0500
Subject: [PATCH 073/117] ASoC: sun4i-spdif: Add support for separate resets
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun4i-spdif.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -28,10 +28,11 @@
#include <sound/soc.h>
#define SUN4I_SPDIF_CTL (0x00)
+ #define SUN4I_SPDIF_CTL_RST_RX BIT(12)
#define SUN4I_SPDIF_CTL_MCLKDIV(v) ((v) << 4) /* v even */
#define SUN4I_SPDIF_CTL_MCLKOUTEN BIT(2)
#define SUN4I_SPDIF_CTL_GEN BIT(1)
- #define SUN4I_SPDIF_CTL_RESET BIT(0)
+ #define SUN4I_SPDIF_CTL_RST_TX BIT(0)
#define SUN4I_SPDIF_TXCFG (0x04)
#define SUN4I_SPDIF_TXCFG_SINGLEMOD BIT(31)
@@ -196,7 +197,7 @@ static void sun4i_spdif_configure(struct
const struct sun4i_spdif_quirks *quirks = host->quirks;
/* soft reset SPDIF */
- regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET);
+ regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RST_TX);
/* flush TX FIFO */
regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL,

View File

@ -0,0 +1,34 @@
From e8e8a9490b2d4acc8670256dd3ba7d2a77346c4d Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 22:23:05 -0500
Subject: [PATCH 074/117] dt-bindings: spi: sun6i: Add R329 variant
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
@@ -21,6 +21,7 @@ properties:
oneOf:
- const: allwinner,sun6i-a31-spi
- const: allwinner,sun8i-h3-spi
+ - const: allwinner,sun50i-r329-spi
- items:
- enum:
- allwinner,sun8i-r40-spi
@@ -28,6 +29,13 @@ properties:
- allwinner,sun50i-h616-spi
- allwinner,suniv-f1c100s-spi
- const: allwinner,sun8i-h3-spi
+ - items:
+ - const: allwinner,sun20i-d1-spi
+ - const: allwinner,sun50i-r329-spi
+ - items:
+ - const: allwinner,sun20i-d1-spi-dbi
+ - const: allwinner,sun50i-r329-spi-dbi
+ - const: allwinner,sun50i-r329-spi
reg:
maxItems: 1

View File

@ -0,0 +1,109 @@
From dbc9e83cefe51d19877a4a7349ebbeafa31c0e06 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Fri, 16 Jul 2021 21:33:16 -0500
Subject: [PATCH 075/117] spi: spi-sun6i: Use a struct for quirks
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/spi/spi-sun6i.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -85,7 +85,12 @@
#define SUN6I_TXDATA_REG 0x200
#define SUN6I_RXDATA_REG 0x300
+struct sun6i_spi_quirks {
+ unsigned long fifo_depth;
+};
+
struct sun6i_spi {
+ const struct sun6i_spi_quirks *quirks;
struct spi_master *master;
void __iomem *base_addr;
dma_addr_t dma_addr_rx;
@@ -100,7 +105,6 @@ struct sun6i_spi {
const u8 *tx_buf;
u8 *rx_buf;
int len;
- unsigned long fifo_depth;
};
static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
@@ -157,7 +161,7 @@ static inline void sun6i_spi_fill_fifo(s
u8 byte;
/* See how much data we can fit */
- cnt = sspi->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
+ cnt = sspi->quirks->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
len = min((int)cnt, sspi->len);
@@ -300,14 +304,14 @@ static int sun6i_spi_transfer_one(struct
* the hardcoded value used in old generation of Allwinner
* SPI controller. (See spi-sun4i.c)
*/
- trig_level = sspi->fifo_depth / 4 * 3;
+ trig_level = sspi->quirks->fifo_depth / 4 * 3;
} else {
/*
* Setup FIFO DMA request trigger level
* We choose 1/2 of the full fifo depth, that value will
* be used as DMA burst length.
*/
- trig_level = sspi->fifo_depth / 2;
+ trig_level = sspi->quirks->fifo_depth / 2;
if (tfr->tx_buf)
reg |= SUN6I_FIFO_CTL_TF_DRQ_EN;
@@ -421,9 +425,9 @@ static int sun6i_spi_transfer_one(struct
reg = SUN6I_INT_CTL_TC;
if (!use_dma) {
- if (rx_len > sspi->fifo_depth)
+ if (rx_len > sspi->quirks->fifo_depth)
reg |= SUN6I_INT_CTL_RF_RDY;
- if (tx_len > sspi->fifo_depth)
+ if (tx_len > sspi->quirks->fifo_depth)
reg |= SUN6I_INT_CTL_TF_ERQ;
}
@@ -569,7 +573,7 @@ static bool sun6i_spi_can_dma(struct spi
* the fifo length we can just fill the fifo and wait for a single
* irq, so don't bother setting up dma
*/
- return xfer->len > sspi->fifo_depth;
+ return xfer->len > sspi->quirks->fifo_depth;
}
static int sun6i_spi_probe(struct platform_device *pdev)
@@ -608,7 +612,7 @@ static int sun6i_spi_probe(struct platfo
}
sspi->master = master;
- sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev);
+ sspi->quirks = of_device_get_match_data(&pdev->dev);
master->max_speed_hz = 100 * 1000 * 1000;
master->min_speed_hz = 3 * 1000;
@@ -723,9 +727,17 @@ static int sun6i_spi_remove(struct platf
return 0;
}
+static const struct sun6i_spi_quirks sun6i_a31_spi_quirks = {
+ .fifo_depth = SUN6I_FIFO_DEPTH,
+};
+
+static const struct sun6i_spi_quirks sun8i_h3_spi_quirks = {
+ .fifo_depth = SUN8I_FIFO_DEPTH,
+};
+
static const struct of_device_id sun6i_spi_match[] = {
- { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH },
- { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH },
+ { .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_quirks },
+ { .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_quirks },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);

View File

@ -0,0 +1,146 @@
From ec8dfb455da3822451129257ab21e2f0d03a6ae3 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Fri, 16 Jul 2021 21:46:31 -0500
Subject: [PATCH 076/117] spi: spi-sun6i: Add Allwinner R329 support
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/spi/spi-sun6i.c | 78 ++++++++++++++++++++++++++---------------
1 file changed, 49 insertions(+), 29 deletions(-)
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -30,6 +30,7 @@
#define SUN6I_GBL_CTL_REG 0x04
#define SUN6I_GBL_CTL_BUS_ENABLE BIT(0)
#define SUN6I_GBL_CTL_MASTER BIT(1)
+#define SUN6I_GBL_CTL_SAMPLE_MODE BIT(2)
#define SUN6I_GBL_CTL_TP BIT(7)
#define SUN6I_GBL_CTL_RST BIT(31)
@@ -87,6 +88,8 @@
struct sun6i_spi_quirks {
unsigned long fifo_depth;
+ bool has_divider : 1;
+ bool has_new_sample_mode : 1;
};
struct sun6i_spi {
@@ -362,38 +365,44 @@ static int sun6i_spi_transfer_one(struct
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
/* Ensure that we have a parent clock fast enough */
- mclk_rate = clk_get_rate(sspi->mclk);
- if (mclk_rate < (2 * tfr->speed_hz)) {
- clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
+ if (sspi->quirks->has_divider) {
mclk_rate = clk_get_rate(sspi->mclk);
- }
+ if (mclk_rate < (2 * tfr->speed_hz)) {
+ clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
+ mclk_rate = clk_get_rate(sspi->mclk);
+ }
- /*
- * Setup clock divider.
- *
- * We have two choices there. Either we can use the clock
- * divide rate 1, which is calculated thanks to this formula:
- * SPI_CLK = MOD_CLK / (2 ^ cdr)
- * Or we can use CDR2, which is calculated with the formula:
- * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
- * Wether we use the former or the latter is set through the
- * DRS bit.
- *
- * First try CDR2, and if we can't reach the expected
- * frequency, fall back to CDR1.
- */
- div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
- div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
- if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
- reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
- tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2);
+ /*
+ * Setup clock divider.
+ *
+ * We have two choices there. Either we can use the clock
+ * divide rate 1, which is calculated thanks to this formula:
+ * SPI_CLK = MOD_CLK / (2 ^ cdr)
+ * Or we can use CDR2, which is calculated with the formula:
+ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+ * Wether we use the former or the latter is set through the
+ * DRS bit.
+ *
+ * First try CDR2, and if we can't reach the expected
+ * frequency, fall back to CDR1.
+ */
+ div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
+ div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
+ if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+ reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
+ tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2);
+ } else {
+ div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
+ reg = SUN6I_CLK_CTL_CDR1(div);
+ tfr->effective_speed_hz = mclk_rate / (1 << div);
+ }
+ sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
} else {
- div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
- reg = SUN6I_CLK_CTL_CDR1(div);
- tfr->effective_speed_hz = mclk_rate / (1 << div);
+ clk_set_rate(sspi->mclk, tfr->speed_hz);
+ mclk_rate = clk_get_rate(sspi->mclk);
+ tfr->effective_speed_hz = mclk_rate;
}
- sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
/* Finally enable the bus - doing so before might raise SCK to HIGH */
reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG);
reg |= SUN6I_GBL_CTL_BUS_ENABLE;
@@ -518,6 +527,7 @@ static int sun6i_spi_runtime_resume(stru
struct spi_master *master = dev_get_drvdata(dev);
struct sun6i_spi *sspi = spi_master_get_devdata(master);
int ret;
+ u32 reg;
ret = clk_prepare_enable(sspi->hclk);
if (ret) {
@@ -537,8 +547,10 @@ static int sun6i_spi_runtime_resume(stru
goto err2;
}
- sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
- SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
+ reg = SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP;
+ if (sspi->quirks->has_new_sample_mode)
+ reg |= SUN6I_GBL_CTL_SAMPLE_MODE;
+ sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg);
return 0;
@@ -729,15 +741,23 @@ static int sun6i_spi_remove(struct platf
static const struct sun6i_spi_quirks sun6i_a31_spi_quirks = {
.fifo_depth = SUN6I_FIFO_DEPTH,
+ .has_divider = true,
};
static const struct sun6i_spi_quirks sun8i_h3_spi_quirks = {
.fifo_depth = SUN8I_FIFO_DEPTH,
+ .has_divider = true,
+};
+
+static const struct sun6i_spi_quirks sun50i_r329_spi_quirks = {
+ .fifo_depth = SUN8I_FIFO_DEPTH,
+ .has_new_sample_mode = true,
};
static const struct of_device_id sun6i_spi_match[] = {
{ .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_quirks },
{ .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_quirks },
+ { .compatible = "allwinner,sun50i-r329-spi", .data = &sun50i_r329_spi_quirks },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);

View File

@ -0,0 +1,50 @@
From b300b013de16109f833782d9f4e7ee8cc204780f Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 17 Jul 2021 11:19:29 -0500
Subject: [PATCH 077/117] spi: spi-sun6i: Dual/Quad RX Support
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/spi/spi-sun6i.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -82,6 +82,8 @@
#define SUN6I_XMIT_CNT_REG 0x34
#define SUN6I_BURST_CTL_CNT_REG 0x38
+#define SUN6I_BURST_CTL_CNT_QUAD_EN BIT(29)
+#define SUN6I_BURST_CTL_CNT_DUAL_EN BIT(28)
#define SUN6I_TXDATA_REG 0x200
#define SUN6I_RXDATA_REG 0x300
@@ -415,7 +417,17 @@ static int sun6i_spi_transfer_one(struct
/* Setup the counters */
sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len);
sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len);
- sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len);
+
+ reg = tx_len;
+ switch (tfr->rx_nbits) {
+ case SPI_NBITS_QUAD:
+ reg |= SUN6I_BURST_CTL_CNT_QUAD_EN;
+ break;
+ case SPI_NBITS_DUAL:
+ reg |= SUN6I_BURST_CTL_CNT_DUAL_EN;
+ break;
+ }
+ sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, reg);
if (!use_dma) {
/* Fill the TX FIFO */
@@ -632,7 +644,8 @@ static int sun6i_spi_probe(struct platfo
master->set_cs = sun6i_spi_set_cs;
master->transfer_one = sun6i_spi_transfer_one;
master->num_chipselect = 4;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST
+ | SPI_RX_DUAL | SPI_RX_QUAD;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true;

View File

@ -0,0 +1,154 @@
From aaabd3cf8c041b5122ca252f51fa616833e18749 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 00:54:01 -0500
Subject: [PATCH 078/117] riscv: dts: allwinner: Add SPI support
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../dts/allwinner/sun20i-d1-lichee-rv.dts | 6 +++
.../boot/dts/allwinner/sun20i-d1-nezha.dts | 44 ++++++++++++++++
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 51 +++++++++++++++++++
3 files changed, 101 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv.dts
@@ -65,6 +65,12 @@
status = "okay";
};
+&spi0 {
+ pinctrl-0 = <&spi0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&uart0 {
pinctrl-0 = <&uart0_pb8_pins>;
pinctrl-names = "default";
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
@@ -19,6 +19,7 @@
ethernet1 = &xr829;
mmc0 = &mmc0;
serial0 = &uart0;
+ spi0 = &spi0;
};
chosen {
@@ -157,6 +158,49 @@
pinctrl-names = "default";
status = "okay";
};
+
+&spi0 {
+ pinctrl-0 = <&spi0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ flash@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "boot0";
+ reg = <0x00000000 0x00100000>;
+ };
+
+ partition@100000 {
+ label = "uboot";
+ reg = <0x00100000 0x00300000>;
+ };
+
+ partition@400000 {
+ label = "secure_storage";
+ reg = <0x00400000 0x00100000>;
+ };
+
+ partition@500000 {
+ label = "sys";
+ reg = <0x00500000 0x0fb00000>;
+ };
+ };
+ };
+};
+
+&spi1 {
+ pinctrl-0 = <&spi1_pd_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
&uart0 {
pinctrl-0 = <&uart0_pb8_pins>;
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -179,6 +179,24 @@
};
/omit-if-no-ref/
+ spi0_pins: spi0-pins {
+ pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7";
+ function = "spi0";
+ };
+
+ /omit-if-no-ref/
+ spi1_pb_pins: spi1-pb-pins {
+ pins = "PB0", "PB8", "PB9", "PB10", "PB11", "PB12";
+ function = "spi1";
+ };
+
+ /omit-if-no-ref/
+ spi1_pd_pins: spi1-pd-pins {
+ pins = "PD10", "PD11", "PD12", "PD13", "PD14", "PD15";
+ function = "spi1";
+ };
+
+ /omit-if-no-ref/
uart0_pb8_pins: uart0-pb8-pins {
pins = "PB8", "PB9";
function = "uart0";
@@ -631,6 +649,39 @@
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
+ };
+
+ spi0: spi@4025000 {
+ compatible = "allwinner,sun20i-d1-spi",
+ "allwinner,sun50i-r329-spi";
+ reg = <0x4025000 0x1000>;
+ interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI0>;
+ dmas = <&dma 22>, <&dma 22>;
+ dma-names = "rx", "tx";
+ num-cs = <1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@4026000 {
+ compatible = "allwinner,sun20i-d1-spi-dbi",
+ "allwinner,sun50i-r329-spi-dbi",
+ "allwinner,sun50i-r329-spi";
+ reg = <0x4026000 0x1000>;
+ interrupts = <32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI1>;
+ dmas = <&dma 23>, <&dma 23>;
+ dma-names = "rx", "tx";
+ num-cs = <1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
usb_otg: usb@4100000 {

View File

@ -0,0 +1,80 @@
From 68c6f452bf42d6c5cbaf40537d8a17a7f3f5481e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 6 Jun 2021 10:03:12 -0500
Subject: [PATCH 079/117] dt-bindings: thermal: sun8i: Add compatible for D1
D1 contains a thermal sensor similar to other Allwinner SoCs. Like the
H3 variant, it contains only one channel.
D1's thermal sensor gets a reference voltage from AVCC. This may always
have been the case; it is explicitly documented in the SoC user manuals
since at least H616. However, it was not as important on earlier SoCs,
because those reference designs foreced AVCC always-on by connecting it
to the PLL power supply.
Now, since D1 only uses AVCC for other optional peripherals, this supply
could be turned off at runtime, so it must be made explicit in the DTS.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../thermal/allwinner,sun8i-a83t-ths.yaml | 21 ++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml
+++ b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml
@@ -16,6 +16,7 @@ properties:
- allwinner,sun8i-a83t-ths
- allwinner,sun8i-h3-ths
- allwinner,sun8i-r40-ths
+ - allwinner,sun20i-d1-ths
- allwinner,sun50i-a64-ths
- allwinner,sun50i-a100-ths
- allwinner,sun50i-h5-ths
@@ -55,6 +56,10 @@ properties:
- 0
- 1
+ vref-supply:
+ description:
+ Regulator for the analog reference voltage
+
allOf:
- if:
properties:
@@ -84,7 +89,9 @@ allOf:
properties:
compatible:
contains:
- const: allwinner,sun8i-h3-ths
+ enum:
+ - allwinner,sun8i-h3-ths
+ - allwinner,sun20i-d1-ths
then:
properties:
@@ -103,6 +110,7 @@ allOf:
enum:
- allwinner,sun8i-h3-ths
- allwinner,sun8i-r40-ths
+ - allwinner,sun20i-d1-ths
- allwinner,sun50i-a64-ths
- allwinner,sun50i-a100-ths
- allwinner,sun50i-h5-ths
@@ -114,6 +122,17 @@ allOf:
- clock-names
- resets
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - allwinner,sun20i-d1-ths
+
+ then:
+ required:
+ - vref-supply
+
required:
- compatible
- reg

View File

@ -0,0 +1,79 @@
From c225b48d2cf5f5a824b5b0a4144511bdc5f65ab5 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 14 Aug 2022 11:18:11 -0500
Subject: [PATCH 080/117] riscv: dts: allwinner: d1: Add thermal sensor and
zone
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../sun20i-d1-common-regulators.dtsi | 4 ++
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 41 +++++++++++++++++++
2 files changed, 45 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-common-regulators.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-common-regulators.dtsi
@@ -49,3 +49,7 @@
regulator-max-microvolt = <1800000>;
ldo-in-supply = <&reg_vcc_3v3>;
};
+
+&ths {
+ vref-supply = <&reg_aldo>;
+};
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -59,6 +59,35 @@
#clock-cells = <0>;
};
+ thermal-zones {
+ cpu-thermal {
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&ths>;
+
+ trips {
+ cpu_target: cpu-target {
+ hysteresis = <3000>;
+ temperature = <85000>;
+ type = "passive";
+ };
+
+ cpu-crit {
+ hysteresis = <0>;
+ temperature = <110000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_target>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
soc {
compatible = "simple-bus";
ranges;
@@ -252,6 +281,18 @@
#size-cells = <0>;
};
+ ths: temperature-sensor@2009400 {
+ compatible = "allwinner,sun20i-d1-ths";
+ reg = <0x2009400 0x400>;
+ interrupts = <74 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_THS>, <&osc24M>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_THS>;
+ nvmem-cells = <&ths_calib>;
+ nvmem-cell-names = "calibration";
+ #thermal-sensor-cells = <0>;
+ };
+
lradc: keys@2009800 {
compatible = "allwinner,sun20i-d1-lradc",
"allwinner,sun50i-r329-lradc";

View File

@ -0,0 +1,927 @@
From 9b6a07cacab9300c261b1f7e25857f96cfeae9cf Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 12 Jun 2021 23:42:48 -0500
Subject: [PATCH 081/117] ASoC: sun20i-codec: New driver for D1 internal codec
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/Kconfig | 6 +
sound/soc/sunxi/Makefile | 1 +
sound/soc/sunxi/sun20i-codec.c | 886 +++++++++++++++++++++++++++++++++
3 files changed, 893 insertions(+)
create mode 100644 sound/soc/sunxi/sun20i-codec.c
--- a/sound/soc/sunxi/Kconfig
+++ b/sound/soc/sunxi/Kconfig
@@ -30,6 +30,12 @@ config SND_SUN8I_CODEC_ANALOG
Say Y or M if you want to add support for the analog controls for
the codec embedded in newer Allwinner SoCs.
+config SND_SUN20I_CODEC
+ tristate "Allwinner D1 (sun20i) Audio Codec"
+ depends on ARCH_SUNXI || COMPILE_TEST
+ help
+ Say Y or M to add support for the audio codec in Allwinner D1 SoC.
+
config SND_SUN50I_CODEC_ANALOG
tristate "Allwinner sun50i Codec Analog Controls Support"
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
--- a/sound/soc/sunxi/Makefile
+++ b/sound/soc/sunxi/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-c
obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o
obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o
+obj-$(CONFIG_SND_SUN20I_CODEC) += sun20i-codec.o
obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) += sun50i-codec-analog.o
obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o
obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) += sun8i-adda-pr-regmap.o
--- /dev/null
+++ b/sound/soc/sunxi/sun20i-codec.c
@@ -0,0 +1,886 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/simple_card_utils.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#define SUN20I_CODEC_DAC_DPC 0x0000
+#define SUN20I_CODEC_DAC_DPC_EN_DA 31
+#define SUN20I_CODEC_DAC_DPC_HPF_EN 18
+#define SUN20I_CODEC_DAC_DPC_DVOL 12
+#define SUN20I_CODEC_DAC_VOL_CTRL 0x0004
+#define SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_SEL 16
+#define SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_L 8
+#define SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_R 0
+#define SUN20I_CODEC_DAC_FIFOC 0x0010
+#define SUN20I_CODEC_DAC_FIFOC_FS 29
+#define SUN20I_CODEC_DAC_FIFOC_FIFO_MODE 24
+#define SUN20I_CODEC_DAC_FIFOC_DRQ_CLR_CNT 21
+#define SUN20I_CODEC_DAC_FIFOC_TRIG_LEVEL 8
+#define SUN20I_CODEC_DAC_FIFOC_MONO_EN 6
+#define SUN20I_CODEC_DAC_FIFOC_SAMPLE_BITS 5
+#define SUN20I_CODEC_DAC_FIFOC_DRQ_EN 4
+#define SUN20I_CODEC_DAC_FIFOC_FIFO_FLUSH 0
+#define SUN20I_CODEC_DAC_TXDATA 0x0020
+#define SUN20I_CODEC_DAC_DEBUG 0x0028
+#define SUN20I_CODEC_DAC_DEBUG_DA_SWP 6
+#define SUN20I_CODEC_DAC_ADDA_LOOP_MODE 0
+
+#define SUN20I_CODEC_ADC_FIFOC 0x0030
+#define SUN20I_CODEC_ADC_FIFOC_FS 29
+#define SUN20I_CODEC_ADC_FIFOC_EN_AD 28
+#define SUN20I_CODEC_ADC_FIFOC_FIFO_MODE 24
+#define SUN20I_CODEC_ADC_FIFOC_SAMPLE_BITS 16
+#define SUN20I_CODEC_ADC_FIFOC_TRIG_LEVEL 4
+#define SUN20I_CODEC_ADC_FIFOC_DRQ_EN 3
+#define SUN20I_CODEC_ADC_FIFOC_FIFO_FLUSH 0
+#define SUN20I_CODEC_ADC_VOL_CTRL 0x0034
+#define SUN20I_CODEC_ADC_VOL_CTRL_ADC3_VOL 16
+#define SUN20I_CODEC_ADC_VOL_CTRL_ADC2_VOL 8
+#define SUN20I_CODEC_ADC_VOL_CTRL_ADC1_VOL 0
+#define SUN20I_CODEC_ADC_RXDATA 0x0040
+#define SUN20I_CODEC_ADC_DEBUG 0x004c
+#define SUN20I_CODEC_ADC_DEBUG_AD_SWP1 24
+#define SUN20I_CODEC_ADC_DIG_CTRL 0x0050
+#define SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN 16
+#define SUN20I_CODEC_ADC_DIG_CTRL_ADC_EN 0
+
+#define SUN20I_CODEC_DAC_DAP_CTRL 0x00f0
+#define SUN20I_CODEC_DAC_DAP_CTRL_DAP_EN 31
+#define SUN20I_CODEC_DAC_DAP_CTRL_DAP_DRC_EN 29
+#define SUN20I_CODEC_DAC_DAP_CTRL_DAP_HPF_EN 28
+
+#define SUN20I_CODEC_ADC_DAP_CTRL 0x00f8
+#define SUN20I_CODEC_ADC_DAP_CTRL_DAP0_EN 31
+#define SUN20I_CODEC_ADC_DAP_CTRL_DAP0_DRC_EN 29
+#define SUN20I_CODEC_ADC_DAP_CTRL_DAP0_HPF_EN 28
+#define SUN20I_CODEC_ADC_DAP_CTRL_DAP1_EN 27
+#define SUN20I_CODEC_ADC_DAP_CTRL_DAP1_DRC_EN 25
+#define SUN20I_CODEC_ADC_DAP_CTRL_DAP1_HPF_EN 24
+
+#define SUN20I_CODEC_ADC1 0x0300
+#define SUN20I_CODEC_ADC1_ADC1_EN 31
+#define SUN20I_CODEC_ADC1_MICIN1_PGA_EN 30
+#define SUN20I_CODEC_ADC1_ADC1_DITHER_EN 29
+#define SUN20I_CODEC_ADC1_MICIN1_SIN_EN 28
+#define SUN20I_CODEC_ADC1_FMINL_EN 27
+#define SUN20I_CODEC_ADC1_FMINL_GAIN 26
+#define SUN20I_CODEC_ADC1_DITHER_LEVEL 24
+#define SUN20I_CODEC_ADC1_LINEINL_EN 23
+#define SUN20I_CODEC_ADC1_LINEINL_GAIN 22
+#define SUN20I_CODEC_ADC1_ADC1_PGA_GAIN 8
+#define SUN20I_CODEC_ADC2 0x0304
+#define SUN20I_CODEC_ADC2_ADC2_EN 31
+#define SUN20I_CODEC_ADC2_MICIN2_PGA_EN 30
+#define SUN20I_CODEC_ADC2_ADC2_DITHER_EN 29
+#define SUN20I_CODEC_ADC2_MICIN2_SIN_EN 28
+#define SUN20I_CODEC_ADC2_FMINR_EN 27
+#define SUN20I_CODEC_ADC2_FMINR_GAIN 26
+#define SUN20I_CODEC_ADC2_DITHER_LEVEL 24
+#define SUN20I_CODEC_ADC2_LINEINR_EN 23
+#define SUN20I_CODEC_ADC2_LINEINR_GAIN 22
+#define SUN20I_CODEC_ADC2_ADC2_PGA_GAIN 8
+#define SUN20I_CODEC_ADC3 0x0308
+#define SUN20I_CODEC_ADC3_ADC3_EN 31
+#define SUN20I_CODEC_ADC3_MICIN3_PGA_EN 30
+#define SUN20I_CODEC_ADC3_ADC3_DITHER_EN 29
+#define SUN20I_CODEC_ADC3_MICIN3_SIN_EN 28
+#define SUN20I_CODEC_ADC3_DITHER_LEVEL 24
+#define SUN20I_CODEC_ADC3_ADC3_PGA_GAIN 8
+
+#define SUN20I_CODEC_DAC 0x0310
+#define SUN20I_CODEC_DAC_DACL_EN 15
+#define SUN20I_CODEC_DAC_DACR_EN 14
+#define SUN20I_CODEC_DAC_LINEOUTL_EN 13
+#define SUN20I_CODEC_DAC_LMUTE 12
+#define SUN20I_CODEC_DAC_LINEOUTR_EN 11
+#define SUN20I_CODEC_DAC_RMUTE 10
+#define SUN20I_CODEC_DAC_LINEOUTL_DIFFEN 6
+#define SUN20I_CODEC_DAC_LINEOUTR_DIFFEN 5
+#define SUN20I_CODEC_DAC_LINEOUT_VOL_CTRL 0
+
+#define SUN20I_CODEC_MICBIAS 0x0318
+#define SUN20I_CODEC_MICBIAS_SELDETADCFS 28
+#define SUN20I_CODEC_MICBIAS_SELDETADCDB 26
+#define SUN20I_CODEC_MICBIAS_SELDETADCBF 24
+#define SUN20I_CODEC_MICBIAS_JACKDETEN 23
+#define SUN20I_CODEC_MICBIAS_SELDETADCDY 21
+#define SUN20I_CODEC_MICBIAS_MICADCEN 20
+#define SUN20I_CODEC_MICBIAS_POPFREE 19
+#define SUN20I_CODEC_MICBIAS_DET_MODE 18
+#define SUN20I_CODEC_MICBIAS_AUTOPLEN 17
+#define SUN20I_CODEC_MICBIAS_MICDETPL 16
+#define SUN20I_CODEC_MICBIAS_HMICBIASEN 15
+#define SUN20I_CODEC_MICBIAS_HMICBIASSEL 13
+#define SUN20I_CODEC_MICBIAS_HMIC_CHOPPER_EN 12
+#define SUN20I_CODEC_MICBIAS_HMIC_CHOPPER_CLK 10
+#define SUN20I_CODEC_MICBIAS_MMICBIASEN 7
+#define SUN20I_CODEC_MICBIAS_MMICBIASSEL 5
+#define SUN20I_CODEC_MICBIAS_MMIC_CHOPPER_EN 4
+#define SUN20I_CODEC_MICBIAS_MMIC_CHOPPER_CLK 2
+
+/* TODO */
+#define SUN20I_CODEC_RAMP 0x031c
+#define SUN20I_CODEC_RAMP_HP_PULL_OUT_EN 15
+
+#define SUN20I_CODEC_HMIC_CTRL 0x0328
+#define SUN20I_CODEC_HMIC_CTRL_SAMPLE_SELECT 21
+#define SUN20I_CODEC_HMIC_CTRL_MDATA_THRESHOLD 16
+#define SUN20I_CODEC_HMIC_CTRL_SF 14
+#define SUN20I_CODEC_HMIC_CTRL_M 10
+#define SUN20I_CODEC_HMIC_CTRL_N 6
+#define SUN20I_CODEC_HMIC_CTRL_THRESH_DEBOUNCE 3
+#define SUN20I_CODEC_HMIC_CTRL_JACK_OUT_IRQ_EN 2
+#define SUN20I_CODEC_HMIC_CTRL_JACK_IN_IRQ_EN 1
+#define SUN20I_CODEC_HMIC_CTRL_MIC_DET_IRQ_EN 0
+#define SUN20I_CODEC_HMIC_STS 0x032c
+#define SUN20I_CODEC_HMIC_STS_MDATA_DISCARD 13
+#define SUN20I_CODEC_HMIC_STS_HMIC_DATA 8
+#define SUN20I_CODEC_HMIC_STS_JACK_OUT_IRQ 4
+#define SUN20I_CODEC_HMIC_STS_JACK_IN_IRQ 3
+#define SUN20I_CODEC_HMIC_STS_MIC_DET_IRQ 0
+
+#define SUN20I_CODEC_HP2 0x0340
+#define SUN20I_CODEC_HP2_HPFB_BUF_EN 31
+#define SUN20I_CODEC_HP2_HEADPHONE_GAIN 28
+#define SUN20I_CODEC_HP2_HPFB_RES 26
+#define SUN20I_CODEC_HP2_HP_DRVEN 21
+#define SUN20I_CODEC_HP2_HP_DRVOUTEN 20
+#define SUN20I_CODEC_HP2_RSWITCH 19
+#define SUN20I_CODEC_HP2_RAMPEN 18
+#define SUN20I_CODEC_HP2_HPFB_IN_EN 17
+#define SUN20I_CODEC_HP2_RAMP_FINAL_CONTROL 16
+#define SUN20I_CODEC_HP2_RAMP_OUT_EN 15
+#define SUN20I_CODEC_HP2_RAMP_FINAL_STATE_RES 13
+
+/* Not affected by codec bus clock/reset */
+#define SUN20I_CODEC_POWER 0x0348
+#define SUN20I_CODEC_POWER_ALDO_EN_MASK BIT(31)
+#define SUN20I_CODEC_POWER_HPLDO_EN_MASK BIT(30)
+#define SUN20I_CODEC_POWER_ALDO_VOLTAGE_MASK GENMASK(14, 12)
+#define SUN20I_CODEC_POWER_HPLDO_VOLTAGE_MASK GENMASK(10, 8)
+
+#define SUN20I_CODEC_ADC_CUR 0x034c
+
+#define SUN20I_CODEC_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE|\
+ SNDRV_PCM_FMTBIT_S20_LE|\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define DRIVER_NAME "sun20i-codec"
+
+/* snd_soc_register_card() takes over drvdata, so the card must be first! */
+struct sun20i_codec {
+ struct snd_soc_card card;
+ struct snd_soc_dai_link dai_link;
+ struct snd_soc_dai_link_component dlcs[3];
+ struct snd_dmaengine_dai_dma_data dma_data[2];
+
+ struct clk *bus_clk;
+ struct clk *adc_clk;
+ struct clk *dac_clk;
+ struct reset_control *reset;
+};
+
+static int sun20i_codec_dai_probe(struct snd_soc_dai *dai)
+{
+ struct sun20i_codec *codec = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai,
+ &codec->dma_data[SNDRV_PCM_STREAM_PLAYBACK],
+ &codec->dma_data[SNDRV_PCM_STREAM_CAPTURE]);
+
+ return 0;
+}
+
+static struct clk *sun20i_codec_get_clk(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct sun20i_codec *codec = snd_soc_dai_get_drvdata(dai);
+
+ return substream->stream == SNDRV_PCM_STREAM_CAPTURE ?
+ codec->adc_clk : codec->dac_clk;
+}
+
+static const unsigned int sun20i_codec_rates[] = {
+ 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000,
+ 29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000,
+};
+
+static const struct snd_pcm_hw_constraint_list sun20i_codec_rate_lists[] = {
+ [SNDRV_PCM_STREAM_PLAYBACK] = {
+ .list = sun20i_codec_rates,
+ .count = ARRAY_SIZE(sun20i_codec_rates),
+ },
+ [SNDRV_PCM_STREAM_CAPTURE] = {
+ .list = sun20i_codec_rates,
+ .count = ARRAY_SIZE(sun20i_codec_rates) - 4, /* max 48 kHz */
+ },
+};
+
+static int sun20i_codec_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ const struct snd_pcm_hw_constraint_list *list;
+ int ret;
+
+ list = &sun20i_codec_rate_lists[substream->stream];
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, list);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(sun20i_codec_get_clk(substream, dai));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void sun20i_codec_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ clk_disable_unprepare(sun20i_codec_get_clk(substream, dai));
+}
+
+static unsigned int sun20i_codec_get_clk_rate(unsigned int sample_rate)
+{
+ return (sample_rate % 4000) ? 22579200 : 24576000;
+}
+
+static const unsigned short sun20i_codec_divisors[] = {
+ 512, 1024, 2048, 128,
+ 768, 1536, 3072, 256,
+};
+
+static int sun20i_codec_get_fs(unsigned int clk_rate, unsigned int sample_rate)
+{
+ unsigned int divisor = clk_rate / sample_rate;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sun20i_codec_divisors); ++i)
+ if (sun20i_codec_divisors[i] == divisor)
+ return i;
+
+ return -EINVAL;
+}
+
+static int sun20i_codec_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct sun20i_codec *codec = snd_soc_dai_get_drvdata(dai);
+ struct snd_soc_component *component = dai->component;
+ unsigned int channels = params_channels(params);
+ unsigned int sample_bits = params_width(params);
+ unsigned int sample_rate = params_rate(params);
+ unsigned int clk_rate = sun20i_codec_get_clk_rate(sample_rate);
+ enum dma_slave_buswidth dma_width;
+ unsigned int reg;
+ int ret, val;
+
+ switch (params_physical_width(params)) {
+ case 16:
+ dma_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ break;
+ case 32:
+ dma_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ break;
+ default:
+ dev_err(dai->dev, "Unsupported physical sample width: %d\n",
+ params_physical_width(params));
+ return -EINVAL;
+ }
+ codec->dma_data[substream->stream].addr_width = dma_width;
+
+ ret = clk_set_rate(sun20i_codec_get_clk(substream, dai),
+ sun20i_codec_get_clk_rate(sample_rate));
+ if (ret)
+ return ret;
+
+ reg = substream->stream == SNDRV_PCM_STREAM_CAPTURE ?
+ SUN20I_CODEC_ADC_FIFOC : SUN20I_CODEC_DAC_FIFOC;
+
+ val = sun20i_codec_get_fs(clk_rate, sample_rate);
+ if (val < 0)
+ return val;
+ snd_soc_component_update_bits(component, reg,
+ 0x7 << SUN20I_CODEC_DAC_FIFOC_FS,
+ val << SUN20I_CODEC_DAC_FIFOC_FS);
+
+ /* Data is at MSB for full 4-byte samples, otherwise at LSB. */
+ val = sample_bits != 32;
+ snd_soc_component_update_bits(component, reg,
+ 0x1 << SUN20I_CODEC_DAC_FIFOC_FIFO_MODE,
+ val << SUN20I_CODEC_DAC_FIFOC_FIFO_MODE);
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ val = sample_bits > 16;
+ snd_soc_component_update_bits(component, reg,
+ 0x1 << SUN20I_CODEC_ADC_FIFOC_SAMPLE_BITS,
+ val << SUN20I_CODEC_ADC_FIFOC_SAMPLE_BITS);
+
+ val = BIT(channels) - 1;
+ snd_soc_component_update_bits(component, SUN20I_CODEC_ADC_DIG_CTRL,
+ 0xf << SUN20I_CODEC_ADC_DIG_CTRL_ADC_EN,
+ val << SUN20I_CODEC_ADC_DIG_CTRL_ADC_EN);
+ } else {
+ val = sample_bits > 16;
+ snd_soc_component_update_bits(component, reg,
+ 0x1 << SUN20I_CODEC_DAC_FIFOC_SAMPLE_BITS,
+ val << SUN20I_CODEC_DAC_FIFOC_SAMPLE_BITS);
+
+ val = channels == 1;
+ snd_soc_component_update_bits(component, reg,
+ 0x1 << SUN20I_CODEC_DAC_FIFOC_MONO_EN,
+ val << SUN20I_CODEC_DAC_FIFOC_MONO_EN);
+ }
+
+ return 0;
+}
+
+static int sun20i_codec_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ unsigned int reg, mask;
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ reg = SUN20I_CODEC_ADC_FIFOC;
+ mask = BIT(SUN20I_CODEC_ADC_FIFOC_DRQ_EN);
+ } else {
+ reg = SUN20I_CODEC_DAC_FIFOC;
+ mask = BIT(SUN20I_CODEC_DAC_FIFOC_DRQ_EN);
+ }
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ mask |= BIT(SUN20I_CODEC_DAC_FIFOC_FIFO_FLUSH);
+ snd_soc_component_update_bits(component, reg, mask, mask);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ snd_soc_component_update_bits(component, reg, mask, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops sun20i_codec_dai_ops = {
+ .startup = sun20i_codec_startup,
+ .shutdown = sun20i_codec_shutdown,
+ .hw_params = sun20i_codec_hw_params,
+ .trigger = sun20i_codec_trigger,
+};
+
+static struct snd_soc_dai_driver sun20i_codec_dai = {
+ .name = DRIVER_NAME,
+ .probe = sun20i_codec_dai_probe,
+ .ops = &sun20i_codec_dai_ops,
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 3, /* ??? */
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = SUN20I_CODEC_PCM_FORMATS,
+ .sig_bits = 20,
+ },
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .formats = SUN20I_CODEC_PCM_FORMATS,
+ .sig_bits = 20,
+ },
+};
+
+static const DECLARE_TLV_DB_SCALE(sun20i_codec_boost_vol_scale, 0, 600, 0);
+static const DECLARE_TLV_DB_SCALE(sun20i_codec_digital_vol_scale, -12000, 75, 1);
+static const DECLARE_TLV_DB_SCALE(sun20i_codec_headphone_vol_scale, -4200, 600, 0);
+/* FIXME */
+static const DECLARE_TLV_DB_SCALE(sun20i_codec_line_out_vol_scale, -4650, 150, 1);
+/* FIXME */
+static const DECLARE_TLV_DB_SCALE(sun20i_codec_pga_vol_scale, 500, 100, 0);
+
+static const char *const sun20i_codec_line_out_mode_enum_text[] = {
+ "Single-Ended", "Differential"
+};
+
+static const SOC_ENUM_DOUBLE_DECL(sun20i_codec_line_out_mode_enum,
+ SUN20I_CODEC_DAC,
+ SUN20I_CODEC_DAC_LINEOUTL_DIFFEN,
+ SUN20I_CODEC_DAC_LINEOUTR_DIFFEN,
+ sun20i_codec_line_out_mode_enum_text);
+
+static const struct snd_kcontrol_new sun20i_codec_controls[] = {
+ /* Digital Controls */
+ SOC_DOUBLE_TLV("DAC Playback Volume",
+ SUN20I_CODEC_DAC_VOL_CTRL,
+ SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_L,
+ SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_R,
+ 0xc0, 0, sun20i_codec_digital_vol_scale),
+ SOC_SINGLE_TLV("ADC3 Capture Volume",
+ SUN20I_CODEC_ADC_VOL_CTRL,
+ SUN20I_CODEC_ADC_VOL_CTRL_ADC3_VOL,
+ 0xc0, 0, sun20i_codec_digital_vol_scale),
+ SOC_SINGLE_TLV("ADC2 Capture Volume",
+ SUN20I_CODEC_ADC_VOL_CTRL,
+ SUN20I_CODEC_ADC_VOL_CTRL_ADC2_VOL,
+ 0xc0, 0, sun20i_codec_digital_vol_scale),
+ SOC_SINGLE_TLV("ADC1 Capture Volume",
+ SUN20I_CODEC_ADC_VOL_CTRL,
+ SUN20I_CODEC_ADC_VOL_CTRL_ADC1_VOL,
+ 0xc0, 0, sun20i_codec_digital_vol_scale),
+
+ /* Analog Controls */
+ SOC_DOUBLE_R_TLV("FM Capture Volume",
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC1_FMINL_GAIN,
+ 0x1, 0, sun20i_codec_boost_vol_scale),
+ SOC_DOUBLE_R_TLV("Line In Capture Volume",
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC1_LINEINL_GAIN,
+ 0x1, 0, sun20i_codec_boost_vol_scale),
+ SOC_ENUM("Line Out Mode Playback Enum",
+ sun20i_codec_line_out_mode_enum),
+ SOC_SINGLE_TLV("Line Out Playback Volume",
+ SUN20I_CODEC_DAC,
+ SUN20I_CODEC_DAC_LINEOUT_VOL_CTRL,
+ 0x1f, 0, sun20i_codec_line_out_vol_scale),
+ SOC_SINGLE_TLV("Headphone Playback Volume",
+ SUN20I_CODEC_HP2,
+ SUN20I_CODEC_HP2_HEADPHONE_GAIN,
+ 0x7, 1, sun20i_codec_headphone_vol_scale),
+};
+
+static const struct snd_kcontrol_new sun20i_codec_line_out_switch =
+ SOC_DAPM_DOUBLE("Line Out Playback Switch",
+ SUN20I_CODEC_DAC,
+ SUN20I_CODEC_DAC_LMUTE,
+ SUN20I_CODEC_DAC_RMUTE, 1, 1);
+
+static const struct snd_kcontrol_new sun20i_codec_hp_switch =
+ SOC_DAPM_SINGLE("Headphone Playback Switch",
+ SUN20I_CODEC_HP2,
+ SUN20I_CODEC_HP2_HP_DRVOUTEN, 1, 0);
+
+static const struct snd_kcontrol_new sun20i_codec_adc12_mixer_controls[] = {
+ /* ADC1 Only */
+ SOC_DAPM_SINGLE("Mic1 Capture Switch",
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC1_MICIN1_SIN_EN, 1, 0),
+ /* Shared */
+ SOC_DAPM_DOUBLE_R("FM Capture Switch",
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC1_FMINL_EN, 1, 0),
+ /* Shared */
+ SOC_DAPM_DOUBLE_R("Line In Capture Switch",
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC1_LINEINL_EN, 1, 0),
+ /* ADC2 Only */
+ SOC_DAPM_SINGLE("Mic2 Capture Switch",
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC2_MICIN2_SIN_EN, 1, 0),
+};
+
+static const struct snd_kcontrol_new sun20i_codec_adc3_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Mic3 Capture Switch",
+ SUN20I_CODEC_ADC3,
+ SUN20I_CODEC_ADC3_MICIN3_SIN_EN, 1, 0),
+};
+
+static const struct snd_kcontrol_new sun20i_codec_mic1_volume =
+ SOC_DAPM_SINGLE_TLV("Capture Volume",
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC1_ADC1_PGA_GAIN,
+ 0x1f, 0, sun20i_codec_pga_vol_scale);
+
+static const struct snd_kcontrol_new sun20i_codec_mic2_volume =
+ SOC_DAPM_SINGLE_TLV("Capture Volume",
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC2_ADC2_PGA_GAIN,
+ 0x1f, 0, sun20i_codec_pga_vol_scale);
+
+static const struct snd_kcontrol_new sun20i_codec_mic3_volume =
+ SOC_DAPM_SINGLE_TLV("Capture Volume",
+ SUN20I_CODEC_ADC3,
+ SUN20I_CODEC_ADC3_ADC3_PGA_GAIN,
+ 0x1f, 0, sun20i_codec_pga_vol_scale);
+
+static const struct snd_soc_dapm_widget sun20i_codec_widgets[] = {
+ /* Playback */
+ SND_SOC_DAPM_OUTPUT("LINEOUTL"),
+ SND_SOC_DAPM_OUTPUT("LINEOUTR"),
+
+ SND_SOC_DAPM_SWITCH("LINEOUTL Switch",
+ SUN20I_CODEC_DAC,
+ SUN20I_CODEC_DAC_LINEOUTL_EN, 0,
+ &sun20i_codec_line_out_switch),
+ SND_SOC_DAPM_SWITCH("LINEOUTR Switch",
+ SUN20I_CODEC_DAC,
+ SUN20I_CODEC_DAC_LINEOUTR_EN, 0,
+ &sun20i_codec_line_out_switch),
+
+ SND_SOC_DAPM_OUTPUT("HPOUTL"),
+ SND_SOC_DAPM_OUTPUT("HPOUTR"),
+
+ SND_SOC_DAPM_SWITCH("HPOUTL Switch",
+ SND_SOC_NOPM, 0, 0, &sun20i_codec_hp_switch),
+ SND_SOC_DAPM_SWITCH("HPOUTR Switch",
+ SND_SOC_NOPM, 0, 0, &sun20i_codec_hp_switch),
+ SND_SOC_DAPM_SUPPLY("Headphone Driver",
+ SUN20I_CODEC_HP2,
+ SUN20I_CODEC_HP2_HP_DRVEN, 0, NULL, 0),
+
+ SND_SOC_DAPM_DAC("DACL", NULL,
+ SUN20I_CODEC_DAC,
+ SUN20I_CODEC_DAC_DACL_EN, 0),
+ SND_SOC_DAPM_DAC("DACR", NULL,
+ SUN20I_CODEC_DAC,
+ SUN20I_CODEC_DAC_DACR_EN, 0),
+ SND_SOC_DAPM_SUPPLY("DAC",
+ SUN20I_CODEC_DAC_DPC,
+ SUN20I_CODEC_DAC_DPC_EN_DA, 0, NULL, 0),
+
+ SND_SOC_DAPM_AIF_IN("DACL FIFO", "Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("DACR FIFO", "Playback", 1,
+ SND_SOC_NOPM, 0, 0),
+
+ /* Capture */
+ SND_SOC_DAPM_AIF_OUT("ADC1 FIFO", "Capture", 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("ADC2 FIFO", "Capture", 1,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("ADC3 FIFO", "Capture", 2,
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_ADC("ADC1", NULL,
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC1_ADC1_EN, 0),
+ SND_SOC_DAPM_ADC("ADC2", NULL,
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC2_ADC2_EN, 0),
+ SND_SOC_DAPM_ADC("ADC3", NULL,
+ SUN20I_CODEC_ADC3,
+ SUN20I_CODEC_ADC3_ADC3_EN, 0),
+ SND_SOC_DAPM_SUPPLY("ADC",
+ SUN20I_CODEC_ADC_FIFOC,
+ SUN20I_CODEC_ADC_FIFOC_EN_AD, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER_NAMED_CTL("ADC1 Mixer", SND_SOC_NOPM, 0, 0,
+ sun20i_codec_adc12_mixer_controls, 3),
+ SND_SOC_DAPM_MIXER_NAMED_CTL("ADC2 Mixer", SND_SOC_NOPM, 0, 0,
+ sun20i_codec_adc12_mixer_controls + 1, 3),
+ SND_SOC_DAPM_MIXER_NAMED_CTL("ADC3 Mixer", SND_SOC_NOPM, 0, 0,
+ sun20i_codec_adc3_mixer_controls,
+ ARRAY_SIZE(sun20i_codec_adc3_mixer_controls)),
+
+ SND_SOC_DAPM_PGA("Mic1",
+ SUN20I_CODEC_ADC1,
+ SUN20I_CODEC_ADC1_MICIN1_PGA_EN, 0,
+ &sun20i_codec_mic1_volume, 1),
+ SND_SOC_DAPM_PGA("Mic2",
+ SUN20I_CODEC_ADC2,
+ SUN20I_CODEC_ADC2_MICIN2_PGA_EN, 0,
+ &sun20i_codec_mic2_volume, 1),
+ SND_SOC_DAPM_PGA("Mic3",
+ SUN20I_CODEC_ADC3,
+ SUN20I_CODEC_ADC3_MICIN3_PGA_EN, 0,
+ &sun20i_codec_mic3_volume, 1),
+
+ SND_SOC_DAPM_INPUT("MICIN1"),
+ SND_SOC_DAPM_INPUT("MICIN2"),
+ SND_SOC_DAPM_INPUT("MICIN3"),
+
+ SND_SOC_DAPM_INPUT("FMINL"),
+ SND_SOC_DAPM_INPUT("FMINR"),
+
+ SND_SOC_DAPM_INPUT("LINEINL"),
+ SND_SOC_DAPM_INPUT("LINEINR"),
+
+ SND_SOC_DAPM_SUPPLY("HBIAS",
+ SUN20I_CODEC_MICBIAS,
+ SUN20I_CODEC_MICBIAS_HMICBIASEN, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MBIAS",
+ SUN20I_CODEC_MICBIAS,
+ SUN20I_CODEC_MICBIAS_MMICBIASEN, 0, NULL, 0),
+
+ SND_SOC_DAPM_REGULATOR_SUPPLY("avcc", 0, 0),
+ SND_SOC_DAPM_REGULATOR_SUPPLY("hpvcc", 0, 0),
+ SND_SOC_DAPM_REGULATOR_SUPPLY("vdd33", 0, 0),
+};
+
+static const struct snd_soc_dapm_route sun20i_codec_routes[] = {
+ /* Playback */
+ { "LINEOUTL", NULL, "LINEOUTL Switch" },
+ { "LINEOUTR", NULL, "LINEOUTR Switch" },
+
+ { "LINEOUTL Switch", "Line Out Playback Switch", "DACL" },
+ { "LINEOUTR Switch", "Line Out Playback Switch", "DACR" },
+
+ { "HPOUTL", NULL, "HPOUTL Switch" },
+ { "HPOUTR", NULL, "HPOUTR Switch" },
+
+ { "HPOUTL Switch", "Headphone Playback Switch", "DACL" },
+ { "HPOUTR Switch", "Headphone Playback Switch", "DACR" },
+ { "HPOUTL Switch", NULL, "Headphone Driver" },
+ { "HPOUTR Switch", NULL, "Headphone Driver" },
+ { "Headphone Driver", NULL, "hpvcc" },
+
+ { "DACL", NULL, "DACL FIFO" },
+ { "DACR", NULL, "DACR FIFO" },
+ { "DACL", NULL, "DAC" },
+ { "DACR", NULL, "DAC" },
+ { "DACL", NULL, "avcc" },
+ { "DACR", NULL, "avcc" },
+
+ /* Capture */
+ { "ADC1 FIFO", NULL, "ADC1" },
+ { "ADC2 FIFO", NULL, "ADC2" },
+ { "ADC3 FIFO", NULL, "ADC3" },
+
+ { "ADC1", NULL, "ADC1 Mixer" },
+ { "ADC2", NULL, "ADC2 Mixer" },
+ { "ADC3", NULL, "ADC3 Mixer" },
+ { "ADC1", NULL, "ADC" },
+ { "ADC2", NULL, "ADC" },
+ { "ADC3", NULL, "ADC" },
+ { "ADC1", NULL, "avcc" },
+ { "ADC2", NULL, "avcc" },
+ { "ADC3", NULL, "avcc" },
+
+ { "ADC1 Mixer", "Mic1 Capture Switch", "Mic1" },
+ { "ADC2 Mixer", "Mic2 Capture Switch", "Mic2" },
+ { "ADC3 Mixer", "Mic3 Capture Switch", "Mic3" },
+ { "ADC1 Mixer", "FM Capture Switch", "FMINL" },
+ { "ADC2 Mixer", "FM Capture Switch", "FMINR" },
+ { "ADC1 Mixer", "Line In Capture Switch", "LINEINL" },
+ { "ADC2 Mixer", "Line In Capture Switch", "LINEINR" },
+
+ { "Mic1", NULL, "MICIN1" },
+ { "Mic2", NULL, "MICIN2" },
+ { "Mic3", NULL, "MICIN3" },
+
+ { "HBIAS", NULL, "vdd33" },
+ { "MBIAS", NULL, "vdd33" },
+};
+
+static int sun20i_codec_component_probe(struct snd_soc_component *component)
+{
+ struct sun20i_codec *codec = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ ret = reset_control_deassert(codec->reset);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(codec->bus_clk);
+ if (ret)
+ goto err_assert_reset;
+
+ /* Enable digital volume control. */
+ snd_soc_component_update_bits(component, SUN20I_CODEC_DAC_VOL_CTRL,
+ 0x1 << SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_SEL,
+ 0x1 << SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_SEL);
+ snd_soc_component_update_bits(component, SUN20I_CODEC_ADC_DIG_CTRL,
+ 0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN,
+ 0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN);
+
+ return 0;
+
+err_assert_reset:
+ reset_control_assert(codec->reset);
+
+ return ret;
+}
+
+static void sun20i_codec_component_remove(struct snd_soc_component *component)
+{
+ struct sun20i_codec *codec = snd_soc_component_get_drvdata(component);
+
+ clk_disable_unprepare(codec->bus_clk);
+ reset_control_assert(codec->reset);
+}
+
+static const struct snd_soc_component_driver sun20i_codec_component = {
+ .controls = sun20i_codec_controls,
+ .num_controls = ARRAY_SIZE(sun20i_codec_controls),
+ .dapm_widgets = sun20i_codec_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun20i_codec_widgets),
+ .dapm_routes = sun20i_codec_routes,
+ .num_dapm_routes = ARRAY_SIZE(sun20i_codec_routes),
+ .probe = sun20i_codec_component_probe,
+ .remove = sun20i_codec_component_remove,
+};
+
+static int sun20i_codec_init_card(struct device *dev,
+ struct sun20i_codec *codec)
+{
+ struct snd_soc_dai_link *dai_link = &codec->dai_link;
+ struct snd_soc_card *card = &codec->card;
+ int ret;
+
+ codec->dlcs[0].of_node = dev->of_node;
+ codec->dlcs[0].dai_name = DRIVER_NAME;
+ codec->dlcs[1].name = "snd-soc-dummy";
+ codec->dlcs[1].dai_name = "snd-soc-dummy-dai";
+ codec->dlcs[2].of_node = dev->of_node;
+
+ dai_link->name = DRIVER_NAME;
+ dai_link->stream_name = DRIVER_NAME;
+ dai_link->cpus = &codec->dlcs[0];
+ dai_link->num_cpus = 1;
+ dai_link->codecs = &codec->dlcs[1];
+ dai_link->num_codecs = 1;
+ dai_link->platforms = &codec->dlcs[2];
+ dai_link->num_platforms = 1;
+
+ card->name = DRIVER_NAME;
+ card->dev = dev;
+ card->owner = THIS_MODULE;
+ card->dai_link = dai_link;
+ card->num_links = 1;
+ card->fully_routed = true;
+
+ ret = snd_soc_of_parse_aux_devs(card, "aux-devs");
+ if (ret)
+ return ret;
+
+ ret = snd_soc_of_parse_pin_switches(card, "pin-switches");
+ if (ret)
+ return ret;
+
+ ret = snd_soc_of_parse_audio_routing(card, "routing");
+ if (ret)
+ return ret;
+
+ ret = snd_soc_of_parse_audio_simple_widgets(card, "widgets");
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct regmap_config sun20i_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN20I_CODEC_ADC_CUR,
+};
+
+static int sun20i_codec_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sun20i_codec *codec;
+ struct regmap *regmap;
+ struct resource *res;
+ void __iomem *base;
+ int ret;
+
+ codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
+ if (!codec)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, codec);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base),
+ "Failed to map registers\n");
+
+ regmap = devm_regmap_init_mmio(dev, base,
+ &sun20i_codec_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to create regmap\n");
+
+ codec->bus_clk = devm_clk_get(dev, "bus");
+ if (IS_ERR(codec->bus_clk))
+ return dev_err_probe(dev, PTR_ERR(codec->bus_clk),
+ "Failed to get bus clock\n");
+
+ codec->adc_clk = devm_clk_get(dev, "adc");
+ if (IS_ERR(codec->adc_clk))
+ return dev_err_probe(dev, PTR_ERR(codec->adc_clk),
+ "Failed to get ADC clock\n");
+
+ codec->dac_clk = devm_clk_get(dev, "dac");
+ if (IS_ERR(codec->dac_clk))
+ return dev_err_probe(dev, PTR_ERR(codec->dac_clk),
+ "Failed to get DAC clock\n");
+
+ codec->reset = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(codec->reset))
+ return dev_err_probe(dev, PTR_ERR(codec->reset),
+ "Failed to get reset\n");
+
+ ret = devm_snd_soc_register_component(dev, &sun20i_codec_component,
+ &sun20i_codec_dai, 1);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register component\n");
+
+ codec->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
+ res->start + SUN20I_CODEC_DAC_TXDATA;
+ codec->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 8;
+ codec->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
+ res->start + SUN20I_CODEC_ADC_RXDATA;
+ codec->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 8;
+
+ ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register PCM\n");
+
+ ret = sun20i_codec_init_card(dev, codec);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to initialize card\n");
+
+ ret = devm_snd_soc_register_card(dev, &codec->card);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register card\n");
+
+ return 0;
+}
+
+static const struct of_device_id sun20i_codec_of_match[] = {
+ { .compatible = "allwinner,sun20i-d1-codec" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun20i_codec_of_match);
+
+static struct platform_driver sun20i_codec_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = sun20i_codec_of_match,
+ },
+ .probe = sun20i_codec_probe,
+};
+module_platform_driver(sun20i_codec_driver);
+
+MODULE_DESCRIPTION("Allwinner D1 (sun20i) codec driver");
+MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sun20i-codec");

View File

@ -0,0 +1,23 @@
From 87a77f803f5038e3fc64f45d5142ea402512029a Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 23 Jun 2021 21:18:47 -0500
Subject: [PATCH 082/117] ASoC: sun20i-codec: What is this ramp thing?
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
sound/soc/sunxi/sun20i-codec.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/sound/soc/sunxi/sun20i-codec.c
+++ b/sound/soc/sunxi/sun20i-codec.c
@@ -709,6 +709,10 @@ static int sun20i_codec_component_probe(
0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN,
0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN);
+ /* Maaagic... */
+ snd_soc_component_update_bits(component, SUN20I_CODEC_RAMP,
+ BIT(1) | BIT(0), BIT(0));
+
return 0;
err_assert_reset:

View File

@ -0,0 +1,132 @@
From 54b1030c72d74ba6390d62086cbfc6a511f58aa7 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 00:39:42 -0500
Subject: [PATCH 083/117] riscv: dts: allwinner: d1: Add sound cards to boards
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../sun20i-d1-common-regulators.dtsi | 5 +++++
.../sun20i-d1-lichee-rv-86-panel.dtsi | 21 +++++++++++++++++++
.../allwinner/sun20i-d1-lichee-rv-dock.dts | 12 +++++++++++
.../boot/dts/allwinner/sun20i-d1-nezha.dts | 12 +++++++++++
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 13 +++++++++++-
5 files changed, 62 insertions(+), 1 deletion(-)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-common-regulators.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-common-regulators.dtsi
@@ -18,6 +18,11 @@
};
};
+&codec {
+ avcc-supply = <&reg_aldo>;
+ hpvcc-supply = <&reg_hpldo>;
+};
+
&lradc {
vref-supply = <&reg_aldo>;
};
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel.dtsi
@@ -9,6 +9,12 @@
ethernet1 = &xr829;
};
+ audio_amplifier: audio-amplifier {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&pio 1 10 GPIO_ACTIVE_HIGH>; /* PB10 */
+ sound-name-prefix = "Amplifier";
+ };
+
dmic_codec: dmic-codec {
compatible = "dmic-codec";
num-channels = <2>;
@@ -51,6 +57,21 @@
};
};
+&codec {
+ aux-devs = <&audio_amplifier>;
+ routing = "Internal Speaker", "Amplifier OUTL",
+ "Internal Speaker", "Amplifier OUTR",
+ "Amplifier INL", "HPOUTL",
+ "Amplifier INR", "HPOUTR",
+ "LINEINL", "HPOUTL",
+ "LINEINR", "HPOUTR",
+ "MICIN3", "Internal Microphone",
+ "Internal Microphone", "HBIAS";
+ widgets = "Microphone", "Internal Microphone",
+ "Speaker", "Internal Speaker";
+ status = "okay";
+};
+
&dmic {
pinctrl-0 = <&dmic_pb11_d0_pin>, <&dmic_pe17_clk_pin>;
pinctrl-names = "default";
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts
@@ -48,6 +48,18 @@
};
};
+&codec {
+ routing = "Internal Speaker", "HPOUTL",
+ "Internal Speaker", "HPOUTR",
+ "LINEINL", "HPOUTL",
+ "LINEINR", "HPOUTR",
+ "MICIN3", "Internal Microphone",
+ "Internal Microphone", "HBIAS";
+ widgets = "Microphone", "Internal Microphone",
+ "Speaker", "Internal Speaker";
+ status = "okay";
+};
+
&dmic {
pinctrl-0 = <&dmic_pb11_d0_pin>, <&dmic_pe17_clk_pin>;
pinctrl-names = "default";
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts
@@ -51,6 +51,18 @@
};
};
+&codec {
+ routing = "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "LINEINL", "HPOUTL",
+ "LINEINR", "HPOUTR",
+ "MICIN3", "Headset Microphone",
+ "Headset Microphone", "HBIAS";
+ widgets = "Microphone", "Headset Microphone",
+ "Headphone", "Headphone Jack";
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&reg_vdd_cpu>;
};
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -312,10 +312,21 @@
};
codec: audio-codec@2030000 {
- compatible = "simple-mfd", "syscon";
+ compatible = "allwinner,sun20i-d1-codec", "simple-mfd", "syscon";
reg = <0x2030000 0x1000>;
+ interrupts = <41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_AUDIO>,
+ <&ccu CLK_AUDIO_ADC>,
+ <&ccu CLK_AUDIO_DAC>,
+ <&osc24M>,
+ <&rtc CLK_OSC32K>;
+ clock-names = "bus", "adc", "dac", "hosc", "losc";
+ resets = <&ccu RST_BUS_AUDIO>;
+ dmas = <&dma 7>, <&dma 7>;
+ dma-names = "rx", "tx";
#address-cells = <1>;
#size-cells = <1>;
+ #sound-dai-cells = <0>;
regulators@2030348 {
compatible = "allwinner,sun20i-d1-analog-ldos";

View File

@ -0,0 +1,39 @@
From bae2790f627eb30ec3845167341b108e13328f6f Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 7 Aug 2022 10:46:43 -0500
Subject: [PATCH 084/117] drm/sun4i: dsi: Allow panel attach before card
registration
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -967,13 +967,12 @@ static int sun6i_dsi_attach(struct mipi_
if (IS_ERR(panel))
return PTR_ERR(panel);
- if (!dsi->drm || !dsi->drm->registered)
- return -EPROBE_DEFER;
dsi->panel = panel;
dsi->device = device;
- drm_kms_helper_hotplug_event(dsi->drm);
+ if (dsi->drm && dsi->drm->registered)
+ drm_kms_helper_hotplug_event(dsi->drm);
dev_info(host->dev, "Attached device %s\n", device->name);
@@ -988,7 +987,8 @@ static int sun6i_dsi_detach(struct mipi_
dsi->panel = NULL;
dsi->device = NULL;
- drm_kms_helper_hotplug_event(dsi->drm);
+ if (dsi->drm && dsi->drm->registered)
+ drm_kms_helper_hotplug_event(dsi->drm);
return 0;
}

View File

@ -0,0 +1,21 @@
From 5755bea969adcb00b102271b0cbaa3002acd7a35 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 27 Apr 2022 18:50:01 -0500
Subject: [PATCH 085/117] drm/sun4i: mixer: Remove unused CMA headers
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/sun8i_mixer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "sun4i_drv.h"

View File

@ -0,0 +1,110 @@
From 9a7acb8f03346705d7420a490d95b32309d90e22 Mon Sep 17 00:00:00 2001
From: Roman Beranek <roman.beranek@prusa3d.com>
Date: Wed, 25 Nov 2020 13:07:35 +0100
Subject: [PATCH 086/117] drm/sun4i: decouple TCON_DCLK_DIV value from
pll_mipi/dotclock ratio
Observations showed that an actual refresh rate differs from the intended.
Specifically, in case of 4-lane panels it was reduced by 1/3, and in case of
2-lane panels by 2/3.
BSP code apparently distinguishes between a `dsi_div` and a 'tcon inner div'.
While this 'inner' divider is under DSI always 4, the `dsi_div` is defined
as a number of bits per pixel over a number of DSI lanes. This value is then
involved in setting the rate of PLL_MIPI.
I couldn't really figure out how to fit this into the dotclock driver,
so I opted for this hack where the requested rate is adjusted in such a way
that the sun4i_dotclock driver can remain untouched.
Signed-off-by: Roman Beranek <roman.beranek@prusa3d.com>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 44 +++++++++++++++++-------------
1 file changed, 25 insertions(+), 19 deletions(-)
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -291,18 +291,6 @@ static int sun4i_tcon_get_clk_delay(cons
return delay;
}
-static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
- const struct drm_display_mode *mode)
-{
- /* Configure the dot clock */
- clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
-
- /* Set the resolution */
- regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
- SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
- SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-}
-
static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
const struct drm_connector *connector)
{
@@ -365,12 +353,18 @@ static void sun4i_tcon0_mode_set_cpu(str
u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
u8 lanes = device->lanes;
u32 block_space, start_delay;
- u32 tcon_div;
tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
- sun4i_tcon0_mode_set_common(tcon, mode);
+ /* Configure the dot clock */
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000
+ * bpp / (lanes * SUN6I_DSI_TCON_DIV));
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -394,9 +388,7 @@ static void sun4i_tcon0_mode_set_cpu(str
* The datasheet says that this should be set higher than 20 *
* pixel cycle, but it's not clear what a pixel cycle is.
*/
- regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
- tcon_div &= GENMASK(6, 0);
- block_space = mode->htotal * bpp / (tcon_div * lanes);
+ block_space = mode->htotal * bpp / (SUN6I_DSI_TCON_DIV * lanes);
block_space -= mode->hdisplay + 40;
regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
@@ -438,7 +430,14 @@ static void sun4i_tcon0_mode_set_lvds(st
tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7;
- sun4i_tcon0_mode_set_common(tcon, mode);
+
+ /* Configure the dot clock */
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -515,7 +514,14 @@ static void sun4i_tcon0_mode_set_rgb(str
tcon->dclk_min_div = tcon->quirks->dclk_min_div;
tcon->dclk_max_div = 127;
- sun4i_tcon0_mode_set_common(tcon, mode);
+
+ /* Configure the dot clock */
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, connector);

View File

@ -0,0 +1,57 @@
From 9ea0c216d4f85a8ea888a38853e9573bbd9e995a Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 7 Aug 2022 21:09:39 -0500
Subject: [PATCH 087/117] drm/sun4i: tcon: Always protect the LCD dotclock rate
This handles the case where multiple CRTCs get their .mode_set function
called during the same atomic commit, before rate protection is applied
by enabling the CRTC.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/sun4i_dotclock.c | 4 ++++
drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 ++++--
2 files changed, 8 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -6,6 +6,7 @@
* Maxime Ripard <maxime.ripard@free-electrons.com>
*/
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
@@ -194,12 +195,15 @@ int sun4i_dclk_create(struct device *dev
if (IS_ERR(tcon->dclk))
return PTR_ERR(tcon->dclk);
+ clk_rate_exclusive_get(tcon->dclk);
+
return 0;
}
EXPORT_SYMBOL(sun4i_dclk_create);
int sun4i_dclk_free(struct sun4i_tcon *tcon)
{
+ clk_rate_exclusive_put(tcon->dclk);
clk_unregister(tcon->dclk);
return 0;
}
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -108,9 +108,11 @@ static void sun4i_tcon_channel_set_statu
if (enabled) {
clk_prepare_enable(clk);
- clk_rate_exclusive_get(clk);
+ if (clk != tcon->dclk)
+ clk_rate_exclusive_get(clk);
} else {
- clk_rate_exclusive_put(clk);
+ if (clk != tcon->dclk)
+ clk_rate_exclusive_put(clk);
clk_disable_unprepare(clk);
}
}

View File

@ -0,0 +1,113 @@
From f792492db1f42c43eb4b8bb72ce573418afc933d Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@amarulasolutions.com>
Date: Tue, 31 Dec 2019 18:35:24 +0530
Subject: [PATCH 088/117] drm/sun4i: tcon_top: Register reset, clock gates in
probe
TCON TOP is processing clock gates and reset control for
TV0, TV1 and DSI channels during bind and release the same
during unbind component ops.
The usual DSI initialization would setup all controller
clocks along with DPHY clocking during probe.
Since the actual clock gates (along with DSI clock gate)
are initialized during ton top bind, the DPHY is failed to
get the DSI clock during that time.
To solve, this circular dependency move the reset control,
clock gate registration from bind to probe and release the
same from unbind to remove.
This eventually give a chance DPHY to initialize the DSI
clock gate.
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 42 ++++++++++++++------------
1 file changed, 22 insertions(+), 20 deletions(-)
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -124,14 +124,29 @@ static struct clk_hw *sun8i_tcon_top_reg
static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
void *data)
{
- struct platform_device *pdev = to_platform_device(dev);
+ return 0;
+}
+
+static void sun8i_tcon_top_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+}
+
+static const struct component_ops sun8i_tcon_top_ops = {
+ .bind = sun8i_tcon_top_bind,
+ .unbind = sun8i_tcon_top_unbind,
+};
+
+static int sun8i_tcon_top_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
struct clk_hw_onecell_data *clk_data;
struct sun8i_tcon_top *tcon_top;
const struct sun8i_tcon_top_quirks *quirks;
void __iomem *regs;
int ret, i;
- quirks = of_device_get_match_data(&pdev->dev);
+ quirks = of_device_get_match_data(dev);
tcon_top = devm_kzalloc(dev, sizeof(*tcon_top), GFP_KERNEL);
if (!tcon_top)
@@ -222,7 +237,7 @@ static int sun8i_tcon_top_bind(struct de
dev_set_drvdata(dev, tcon_top);
- return 0;
+ return component_add(dev, &sun8i_tcon_top_ops);
err_unregister_gates:
for (i = 0; i < CLK_NUM; i++)
@@ -235,13 +250,15 @@ err_assert_reset:
return ret;
}
-static void sun8i_tcon_top_unbind(struct device *dev, struct device *master,
- void *data)
+static int sun8i_tcon_top_remove(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct sun8i_tcon_top *tcon_top = dev_get_drvdata(dev);
struct clk_hw_onecell_data *clk_data = tcon_top->clk_data;
int i;
+ component_del(dev, &sun8i_tcon_top_ops);
+
of_clk_del_provider(dev->of_node);
for (i = 0; i < CLK_NUM; i++)
if (clk_data->hws[i])
@@ -249,21 +266,6 @@ static void sun8i_tcon_top_unbind(struct
clk_disable_unprepare(tcon_top->bus);
reset_control_assert(tcon_top->rst);
-}
-
-static const struct component_ops sun8i_tcon_top_ops = {
- .bind = sun8i_tcon_top_bind,
- .unbind = sun8i_tcon_top_unbind,
-};
-
-static int sun8i_tcon_top_probe(struct platform_device *pdev)
-{
- return component_add(&pdev->dev, &sun8i_tcon_top_ops);
-}
-
-static int sun8i_tcon_top_remove(struct platform_device *pdev)
-{
- component_del(&pdev->dev, &sun8i_tcon_top_ops);
return 0;
}

View File

@ -0,0 +1,75 @@
From 03dbb926f6d65f75af902e421c44aeaaf84be66a Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 22:46:28 -0500
Subject: [PATCH 089/117] riscv: dts: allwinner: lichee-rv-86-panel-480p: Add
panel
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../sun20i-d1-lichee-rv-86-panel-480p.dts | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-86-panel-480p.dts
@@ -7,6 +7,40 @@
model = "Sipeed Lichee RV 86 Panel (480p)";
compatible = "sipeed,lichee-rv-86-panel-480p", "sipeed,lichee-rv",
"allwinner,sun20i-d1";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ power-supply = <&reg_vcc>;
+ pwms = <&pwm 7 50000 0>;
+ };
+
+ spi {
+ compatible = "spi-gpio";
+ cs-gpios = <&pio 4 14 GPIO_ACTIVE_LOW>; /* PE14 */
+ mosi-gpios = <&pio 4 12 GPIO_ACTIVE_HIGH>; /* PE12 */
+ sck-gpios = <&pio 4 15 GPIO_ACTIVE_HIGH>; /* PE15 */
+ num-chipselects = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "sitronix,st7701s";
+ reg = <0>;
+ backlight = <&backlight>;
+ reset-gpios = <&pio 6 13 GPIO_ACTIVE_LOW>; /* PG13 */
+ spi-3wire;
+
+ port {
+ panel_in_tcon_lcd0: endpoint {
+ remote-endpoint = <&tcon_lcd0_out_panel>;
+ };
+ };
+ };
+ };
+};
+
+&de {
+ status = "okay";
};
&i2c2 {
@@ -27,3 +61,20 @@
wakeup-source;
};
};
+
+&pwm {
+ pinctrl-0 = <&pwm7_pd22_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&tcon_lcd0 {
+ pinctrl-0 = <&lcd_rgb666_pins>;
+ pinctrl-names = "default";
+};
+
+&tcon_lcd0_out {
+ tcon_lcd0_out_panel: endpoint {
+ remote-endpoint = <&panel_in_tcon_lcd0>;
+ };
+};

View File

@ -0,0 +1,82 @@
From 4c72279c90469971ca5ec627a76e50bf51bf076f Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 7 Aug 2022 10:59:29 -0500
Subject: [PATCH 090/117] riscv: dts: allwinner: d1: Add DSI pipeline
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 49 ++++++++++++++++++++
1 file changed, 49 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -124,6 +124,14 @@
#interrupt-cells = <3>;
/omit-if-no-ref/
+ dsi_4lane_pins: dsi-4lane-pins {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+ "PD6", "PD7", "PD8", "PD9";
+ drive-strength = <30>;
+ function = "dsi";
+ };
+
+ /omit-if-no-ref/
i2c0_pb10_pins: i2c0-pb10-pins {
pins = "PB10", "PB11";
function = "i2c0";
@@ -903,6 +911,40 @@
};
};
+ dsi: dsi@5450000 {
+ compatible = "allwinner,sun20i-d1-mipi-dsi",
+ "allwinner,sun50i-a100-mipi-dsi";
+ reg = <0x5450000 0x1000>;
+ interrupts = <108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&tcon_top CLK_TCON_TOP_DSI>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ phys = <&dphy>;
+ phy-names = "dphy";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port {
+ dsi_in_tcon_lcd0: endpoint {
+ remote-endpoint = <&tcon_lcd0_out_dsi>;
+ };
+ };
+ };
+
+ dphy: phy@5451000 {
+ compatible = "allwinner,sun20i-d1-mipi-dphy",
+ "allwinner,sun50i-a100-mipi-dphy";
+ reg = <0x5451000 0x1000>;
+ interrupts = <108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_MIPI_DSI>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ #phy-cells = <0>;
+ };
+
tcon_top: tcon-top@5460000 {
compatible = "allwinner,sun20i-d1-tcon-top";
reg = <0x5460000 0x1000>;
@@ -1022,6 +1064,13 @@
tcon_lcd0_out: port@1 {
reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_tcon_lcd0>;
+ };
};
};
};

View File

@ -0,0 +1,62 @@
From 7ac17ab7ea644ec27935865d6d0208ecc7fd4ed9 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 11 Aug 2022 22:29:03 -0500
Subject: [PATCH 091/117] riscv: dts: allwinner: devterm: Add DSI panel and
backlight
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../allwinner/sun20i-d1-clockworkpi-v3.14.dts | 8 +++++++-
.../dts/allwinner/sun20i-d1-devterm-v3.14.dts | 20 +++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
@@ -48,6 +48,12 @@
};
};
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ power-supply = <&reg_vcc>;
+ pwms = <&pwm 4 50000 0>; /* PD20/GPIO9 */
+ };
+
reg_vdd_cpu: vdd-cpu {
compatible = "pwm-regulator";
pwms = <&pwm 0 50000 0>;
@@ -252,7 +258,7 @@
};
&pwm {
- pinctrl-0 = <&pwm0_pd16_pin>;
+ pinctrl-0 = <&pwm0_pd16_pin>, <&pwm4_pd20_pin>;
pinctrl-names = "default";
status = "okay";
};
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
@@ -35,3 +35,23 @@
};
};
};
+
+&de {
+ status = "okay";
+};
+
+&dsi {
+ pinctrl-0 = <&dsi_4lane_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ panel@0 {
+ compatible = "clockwork,cwd686";
+ reg = <0>;
+ backlight = <&backlight>;
+ reset-gpios = <&pio 3 19 GPIO_ACTIVE_LOW>; /* PD19/GPIO8 */
+ rotation = <90>;
+ iovcc-supply = <&reg_dcdc3>;
+ vci-supply = <&reg_aldo2>;
+ };
+};

View File

@ -0,0 +1,29 @@
From 822fdc3556b688103cdaf7b4b34e98fbe1676425 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 7 Aug 2022 10:58:02 -0500
Subject: [PATCH 092/117] dt-bindings: display: sun4i-tcon: Add external LVDS
PHY
A100 and D1 use the same "combo" PHY for LVDS0 and DSI.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../bindings/display/allwinner,sun4i-a10-tcon.yaml | 7 +++++++
1 file changed, 7 insertions(+)
--- a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml
@@ -80,6 +80,13 @@ properties:
dmas:
maxItems: 1
+ phys:
+ maxItems: 1
+
+ phy-names:
+ items:
+ - const: "lvds0"
+
resets:
anyOf:
- items:

View File

@ -0,0 +1,21 @@
From 7d95f6b52ea5f01c9e2414d4984e5a274328c021 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 7 Aug 2022 10:58:57 -0500
Subject: [PATCH 093/117] riscv: dts: allwinner: d1: Add LVDS0 PHY
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi
@@ -1040,6 +1040,8 @@
resets = <&ccu RST_BUS_TCON_LCD0>,
<&ccu RST_BUS_LVDS0>;
reset-names = "lcd", "lvds";
+ phys = <&dphy>;
+ phy-names = "lvds0";
#clock-cells = <0>;
ports {

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