Update On Wed Feb 11 20:15:52 CET 2026

This commit is contained in:
github-action[bot]
2026-02-11 20:15:52 +01:00
parent 2f88b68cb8
commit 687f856b4b
153 changed files with 13832 additions and 5259 deletions
+22 -10
View File
@@ -11,25 +11,37 @@ I18N: [English](README_EN.md) | [简体中文](README.md) | [日本語](README_J
1. QQ 讨论群:Op 固件技术研究群,号码 891659613,加群链接:[点击加入](https://qm.qq.com/q/IMa6Yf2SgC "Op固件技术研究群")
2. TG 讨论群:OP 编译官方大群,加群链接:[点击加入](https://t.me/JhKgAA6Hx1 "OP 编译官方大群")
## 软路由 ArmSoM Sige 系列介绍
## 瑞莎网络计算 - 轻松打造你的网络边缘计算系统
ArmSoM-Sige 系列:软路由、单板计算机、小型服务器与智能家居的全能之选。
![radxa-netcompute-features](./doc/radxa-netcompute-features.png)
[商品介绍页面 - ArmSom 品牌店](https://shop518100695.taobao.com/)
瑞莎网络计算系列覆盖从入门到高性能的边缘网关场景,从千兆到 2.5G,从四核到六核,全系列基于瑞芯微高可靠处理器,低功耗、稳定运行,适合 7×24 小时网络服务。
购买链接:
| 产品型号 | E20C | E24C | E25C | E52C | E54C |
| -------- | ----------------------- | ----------------------- | ------------------------------- | --------------------------------- | ------------------------- |
| 处理器 | 瑞芯微RK3528A (四核) | 瑞芯微 RK3528A(四核) | 瑞芯微 RK3568 (四核) | 瑞芯微 RK3582 (六核) | 瑞芯微 RK3582 (六核) |
| 以太网 | 2x 千兆以太网 | 4x 千兆以太网 | 2x 2.5G 以太网 | 2x 2.5G 以太网 | 4x 千兆以太网 |
| 适用场景 | 入门级软路由 / 家用网关 | 多口家庭路由 / IoT 网关 | 高速 2.5G 家庭 / 小型企业软路由 | 高性能 2.5G 路由 / VPN / 边缘计算 | 多口网络控制器 / 企业网关 |
[![sige1-zh](doc/sige-zh.jpg)](https://item.taobao.com/item.htm?id=721197662185)
- 多网口设计,为网络计算而生
- 提供 2 / 4 网口、千兆 / 2.5G 多种组合,灵活适配家用、宿舍、小型企业与 IoT 网络。
- 一板多用,系统自由切换
- 支持 OpenWrt、Debian、iStoreOS、Armbian 等多种系统,可应用于网关、轻量服务器或开发板等领域。
- 稳定可靠,适合全天候运行
- 优秀的金属外壳散热设计 + 瑞芯微平台的低功耗特性,确保长时间满载仍能保持稳定。
- 开发生态完善,轻松扩展功能
- 提供配套文档、源码与社区支持,方便开发者进行二次开发、插件扩展与自定义功能。
## 新一代 OpenWrt WIFI7 硬路由 CW Q3600 系列介绍
## 了解更多
畅网Wi-Fi7 ,如7而至(2.5G网口),双系统自由切换
[商品介绍页面 - 畅网 品牌店](https://www.changwang.cn/products.html?typeid=149)
- [官网介绍](https://radxa.com/products#NetworkComputer)
购买链接:
- [官方文档](https://docs.radxa.com/e/e20c)
[![cw-zh](doc/cw-zh.jpg)](https://www.changwang.cn/product.html?id=29)
- [瑞莎京东店铺](https://mall.jd.com/view_search-3967032-31323445-99-1-20-1.html)
- [瑞莎淘宝店铺](https://radxa.taobao.com/category-1797203497.htm?spm=a1z10.1-c-s.0.0.eaee3a483AhQEE)
## 注意
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

+30
View File
@@ -0,0 +1,30 @@
include $(TOPDIR)/rules.mk
ARCH:=arm
BOARD:=hisilicon
BOARDNAME:=HiSilicon
FEATURES:=ext4 usb rtc neon vfpv4
CPU_TYPE:=cortex-a7
SUBTARGETS:=hi3798mv100
KERNEL_PATCHVER:=6.12
define Target/Description
Build firmware images for HiSilicon Hi3798MV100 (EC6108V9C) TV Box.
endef
include $(INCLUDE_DIR)/target.mk
KERNELNAME:=zImage dtbs
DEFAULT_PACKAGES += \
fdt-utils uboot-envtools \
kmod-gpio-button-hotplug \
kmod-usb-storage kmod-fs-ext4 \
kmod-usb2 kmod-usb3 \
kmod-hisi-femac \
kmod-nft-core kmod-nft-ipv4 kmod-nft-nat nftables \
kmod-fs-f2fs f2fs-tools
$(eval $(call BuildTarget))
@@ -0,0 +1,13 @@
#!/bin/sh
. /lib/functions/ucidefault.sh
board_config_update
case "$(board_name)" in
*ec6108v9c*)
# 强制指定网口为 eth0,防止系统识别成 eth1 导致进不了后台
ucidefault_set_interface_lan "eth0"
;;
esac
board_config_commit
@@ -0,0 +1,32 @@
#!/bin/sh
. /lib/functions.sh
inittab_add_console() {
local console
case $(board_name) in
# 匹配你的设备树 compatible 定义的名字
*ec6108v9c*)
# 海思主线内核的标准串口设备名
console="ttyAMA0"
;;
*)
return
;;
esac
# 如果检测到的 TTY 不是我们定义的,就退出
[ "$DEVNAME" != "$console" ] && return
# 检查 /etc/inittab 是否已经有了该串口的配置,防止重复写入
grep -q "^#\{0,1\}${console}::askfirst" "/etc/inittab" && return
# 追加登录条目:askfirst 表示按 Enter 键才进入 shell,防止启动杂讯乱弹
echo -e "\n${console}::askfirst:/usr/libexec/login.sh" >> /etc/inittab
# 立即重载 init 进程,使配置生效
kill -HUP 1
}
[ "${ACTION}" = "add" ] && inittab_add_console
@@ -0,0 +1,9 @@
#!/bin/sh /etc/rc.common
# 启动优先级设为 99,即在所有服务之后运行
START=99
boot() {
# 海思盒子暂时不需要重置计数器
return 0
}
@@ -0,0 +1,7 @@
#!/bin/sh
if [ -b /dev/mmcblk0p13 ]; then
mkfs.f2fs -f /dev/mmcblk0p13
fi
exit 0
@@ -0,0 +1,46 @@
REQUIRE_IMAGE_METADATA=1
platform_do_upgrade() {
local board=$(board_name)
case "$board" in
huawei,ec6108v9c)
echo "Upgrading kernel partition..."
get_image "$1" | dd bs=1M count=16 of=/dev/mmcblk0p3 || {
echo "Kernel upgrade failed!"
return 1
}
echo "Upgrading rootfs partition..."
get_image "$1" | dd bs=1M skip=16 of=/dev/mmcblk0p4 || {
echo "Rootfs upgrade failed!"
return 1
}
sync
echo "Upgrade completed successfully!"
;;
*)
default_do_upgrade "$1"
;;
esac
}
```
### 工作原理
```
sysupgrade.bin 结构:
┌────────────────┬──────────────┬──────────┐
│ kernel (16MB) │ rootfs │ metadata │
└────────────────┴──────────────┴──────────┘
写入到 /dev/mmcblk0p3 时:
┌───────── 从这里开始写入
┌──────────┬──────────┬────────────┬──────────────┐
│ fastboot │ bootargs │ kernel │ rootfs │
│ 1MB │ 1MB │ 16MB │ 512MB │
│ 0-1MB │ 1-2MB │ 2MB-18MB │ 18MB-530MB │
└──────────┴──────────┴────────────┴──────────────┘
│←── 16MB ──→│←─ rootfs ──→│
写入覆盖这两个分区
+146
View File
@@ -0,0 +1,146 @@
CONFIG_ALIGNMENT_TRAP=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_ARCH_MULTI_CPU_AUTO=y
# CONFIG_ARCH_MULTI_V4 is not set
# CONFIG_ARCH_MULTI_V4T is not set
CONFIG_ARCH_MULTI_V4_V5=y
CONFIG_ARCH_MULTI_V5=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARM=y
CONFIG_ARM_HAS_GROUP_RELOCS=y
CONFIG_ARM_L1_CACHE_SHIFT=5
CONFIG_ARM_THUMB=y
CONFIG_ARM_UNWIND=y
CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
CONFIG_BUFFER_HEAD=y
CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMMON_CLK=y
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5TJ=y
CONFIG_CPU_ARM926T=y
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
CONFIG_CPU_ENDIAN_BE32=y
CONFIG_CPU_MITIGATIONS=y
CONFIG_CPU_PABRT_LEGACY=y
CONFIG_CPU_THUMB_CAPABLE=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_USE_DOMAINS=y
CONFIG_CRYPTO_CRC32=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_GF128MUL=y
CONFIG_CRYPTO_LIB_SHA1=y
CONFIG_CRYPTO_LIB_UTILS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
CONFIG_DMA_NEED_SYNC=y
CONFIG_DMA_OPS_HELPERS=y
CONFIG_DTC=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FORCE_NR_CPUS=y
CONFIG_FS_IOMAP=y
CONFIG_FS_POSIX_ACL=y
CONFIG_FUNCTION_ALIGNMENT=0
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_FW_LOADER_SYSFS=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_DEVICES=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_IDLE_POLL_SETUP=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_PCI_IOMAP=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GPIO_CDEV=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HZ_FIXED=0
CONFIG_HZ_PERIODIC=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQSTACKS=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_MIGRATION=y
CONFIG_MMU_LAZY_TLB_REFCOUNT=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_KUSER_HELPERS=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NET_EGRESS=y
CONFIG_NET_INGRESS=y
CONFIG_NET_XGRESS=y
CONFIG_NLS=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PAGE_POOL=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYS_OFFSET=0
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_RANDSTRUCT_NONE=y
CONFIG_RATIONAL=y
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SOFTIRQ_ON_OWN_STACK=y
CONFIG_SPARSE_IRQ=y
CONFIG_SQUASHFS_ZLIB=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TINY_SRCU=y
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
CONFIG_UNWINDER_ARM=y
CONFIG_USE_OF=y
# CONFIG_VFP is not set
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZLIB_INFLATE=y
@@ -0,0 +1,546 @@
CONFIG_ARCH_FORCE_MAX_ORDER=10
CONFIG_ARCH_HI3xxx=y
CONFIG_ARCH_HIP01=y
CONFIG_ARCH_HIP04=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_HIX5HD2=y
CONFIG_ARCH_MULTIPLATFORM=y
CONFIG_ARCH_MULTI_V6_V7=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
CONFIG_ARM_AMBA=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
CONFIG_ARM_CPU_SUSPEND=y
CONFIG_ARM_ERRATA_643719=y
CONFIG_ARM_ERRATA_798181=y
CONFIG_ARM_GIC=y
CONFIG_ARM_GLOBAL_TIMER=y
CONFIG_ARM_GT_INITIAL_PRESCALER_VAL=0
CONFIG_ARM_HEAVY_MB=y
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_PAN=y
CONFIG_ARM_PATCH_IDIV=y
CONFIG_ARM_PATCH_PHYS_VIRT=y
# CONFIG_ARM_SMMU is not set
CONFIG_ARM_TIMER_SP804=y
CONFIG_ARM_VIRT_EXT=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_ATA=y
CONFIG_ATAGS=y
CONFIG_ATA_FORCE=y
CONFIG_ATA_VERBOSE_ERROR=y
CONFIG_AUTO_ZRELADDR=y
# CONFIG_BLK_CGROUP is not set
CONFIG_BLK_DEBUG_FS=y
CONFIG_BLK_DEV_BSG=y
CONFIG_BLK_DEV_BSG_COMMON=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_ICQ=y
CONFIG_BLK_PM=y
CONFIG_BLOCK_LEGACY_AUTOLOAD=y
CONFIG_BOUNCE=y
# CONFIG_BPF_JIT is not set
# CONFIG_BPF_SYSCALL is not set
# CONFIG_BRIDGE is not set
CONFIG_BUFFER_HEAD=y
CONFIG_CACHESTAT_SYSCALL=y
CONFIG_CACHE_L2X0=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_CPUACCT is not set
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_FREEZER=y
# CONFIG_CGROUP_NET_CLASSID is not set
# CONFIG_CGROUP_NET_PRIO is not set
CONFIG_CGROUP_PIDS=y
# CONFIG_CGROUP_RDMA is not set
# CONFIG_CGROUP_SCHED is not set
CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CMDLINE_PARTITION=y
CONFIG_COMMON_CLK_HI3516CV300=y
CONFIG_COMMON_CLK_HI3519=y
CONFIG_COMMON_CLK_HI3559A=y
CONFIG_COMMON_CLK_HI3660=y
CONFIG_COMMON_CLK_HI3670=y
CONFIG_COMMON_CLK_HI3798=y
CONFIG_COMMON_CLK_HI6220=y
CONFIG_COMMON_RESET_HI3660=y
CONFIG_COMMON_RESET_HI6220=y
CONFIG_COMPAT_BRK=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_CONTEXT_TRACKING=y
CONFIG_CONTEXT_TRACKING_IDLE=y
CONFIG_COREDUMP=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_CPUSETS=y
# CONFIG_CPUSETS_V1 is not set
CONFIG_CPU_32v6K=y
CONFIG_CPU_32v7=y
CONFIG_CPU_ABRT_EV7=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_CACHE_V7=y
CONFIG_CPU_CACHE_VIPT=y
CONFIG_CPU_COPY_V6=y
CONFIG_CPU_HAS_ASID=y
CONFIG_CPU_ISOLATION=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_PABRT_V7=y
CONFIG_CPU_PM=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_SPECTRE=y
CONFIG_CPU_TLB_V7=y
CONFIG_CPU_V7=y
CONFIG_CRC16=y
CONFIG_CROSS_MEMORY_ATTACH=y
# CONFIG_CRYPTO_AES is not set
# CONFIG_CRYPTO_CCM is not set
CONFIG_CRYPTO_CRC32C=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_DEV_HISI_ADVCA is not set
# CONFIG_CRYPTO_GCM is not set
# CONFIG_CRYPTO_GHASH is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_PCRYPT is not set
CONFIG_CURRENT_POINTER_IN_TPIDRURO=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_ALIGN_RODATA=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
CONFIG_DEBUG_INFO_NONE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_MISC=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_LZ4=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DECOMPRESS_ZSTD=y
CONFIG_DEVMEM=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DMADEVICES=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DNOTIFY=y
CONFIG_DNS_RESOLVER=y
CONFIG_DRM=y
CONFIG_DRM_BRIDGE=y
CONFIG_DRM_PANEL=y
CONFIG_DRM_PANEL_BRIDGE=y
CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
CONFIG_DST_CACHE=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_ROWS=30
CONFIG_DWMAC_GENERIC=y
CONFIG_DW_DMAC=y
CONFIG_DW_DMAC_CORE=y
CONFIG_ELF_CORE=y
# CONFIG_ENABLE_DEFAULT_TRACERS is not set
# CONFIG_EXPERT is not set
CONFIG_EXT4_FS=y
CONFIG_EXTCON=y
CONFIG_FHANDLE=y
CONFIG_FIXED_PHY=y
# CONFIG_FORTIFY_SOURCE is not set
CONFIG_FREEZER=y
CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_FTRACE=y
# CONFIG_FTRACE_SYSCALLS is not set
CONFIG_FWNODE_MDIO=y
CONFIG_FW_CACHE=y
# CONFIG_FW_LOADER_USER_HELPER is not set
CONFIG_GENERIC_ARCH_TOPOLOGY=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_VDSO_32=y
CONFIG_GLOB=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_CDEV_V1=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_GRACE_PERIOD=y
CONFIG_GRO_CELLS=y
# CONFIG_HARDENED_USERCOPY is not set
CONFIG_HARDEN_BRANCH_PREDICTOR=y
CONFIG_HAVE_SMP=y
CONFIG_HDMI=y
# CONFIG_HI13X1_GMAC is not set
CONFIG_HID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GENERIC=y
CONFIG_HID_ITE=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_REDRAGON=y
CONFIG_HID_SUPPORT=y
CONFIG_HIGHMEM=y
CONFIG_HIGHPTE=y
CONFIG_HIP04_ETH=y
CONFIG_HISI_FEMAC=y
CONFIG_HISI_FESTA_PHY=y
# CONFIG_HISTB_DMA is not set
# CONFIG_HIST_TRIGGERS is not set
CONFIG_HIX5HD2_GMAC=y
CONFIG_HNS_MDIO=y
CONFIG_HOTPLUG_CORE_SYNC=y
CONFIG_HOTPLUG_CORE_SYNC_DEAD=y
CONFIG_HOTPLUG_CPU=y
CONFIG_HWMON=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_HISI=y
CONFIG_HW_RANDOM_HISTB=y
# CONFIG_HZ_PERIODIC is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_DESIGNWARE_CORE=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_HID=y
# CONFIG_I2C_HIX5HD2 is not set
CONFIG_INET_DIAG=y
# CONFIG_INET_DIAG_DESTROY is not set
# CONFIG_INET_RAW_DIAG is not set
CONFIG_INET_TCP_DIAG=y
CONFIG_INET_TUNNEL=y
CONFIG_INITRAMFS_PRESERVE_MTIME=y
CONFIG_INPUT=y
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_KEYBOARD=y
# CONFIG_INPUT_MISC is not set
CONFIG_INPUT_MOUSE=y
CONFIG_INPUT_VIVALDIFMAP=y
# CONFIG_IOMMUFD is not set
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IOSCHED_BFQ=y
CONFIG_IO_URING=y
CONFIG_IPV6=y
CONFIG_IPV6_SIT=y
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_MULTICAST is not set
CONFIG_IP_PNP=y
# CONFIG_IP_PNP_BOOTP is not set
CONFIG_IP_PNP_DHCP=y
# CONFIG_IP_PNP_RARP is not set
CONFIG_IRQ_DOMAIN_HIERARCHY=y
# CONFIG_ISDN is not set
CONFIG_JBD2=y
# CONFIG_K3_DMA is not set
CONFIG_KALLSYMS=y
CONFIG_KCMP=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_MODE_NEON is not set
# CONFIG_KERNEL_XZ is not set
CONFIG_KEYBOARD_ATKBD=y
CONFIG_KEYS=y
CONFIG_KMAP_LOCAL=y
CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_LEGACY_TIOCSTI=y
# CONFIG_LIST_HARDENED is not set
CONFIG_LOCALVERSION_AUTO=y
CONFIG_LOCKD=y
CONFIG_LOCK_SPIN_ON_OWNER=y
# CONFIG_LRU_GEN is not set
CONFIG_LZ4_DECOMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MARVELL_PHY=y
CONFIG_MCPM=y
CONFIG_MCPM_QUAD_CLUSTER=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MDIO_HISI_FEMAC=y
CONFIG_MEMCG=y
# CONFIG_MEMCG_V1 is not set
# CONFIG_MFD_HI655X_PMIC is not set
CONFIG_MFD_SYSCON=y
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_DW=y
# CONFIG_MMC_DW_BLUEFIELD is not set
# CONFIG_MMC_DW_EXYNOS is not set
CONFIG_MMC_DW_HI3798CV200=y
# CONFIG_MMC_DW_HI3798MV200 is not set
CONFIG_MMC_DW_K3=y
CONFIG_MMC_DW_PLTFM=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_BYD=y
CONFIG_MOUSE_PS2_CYPRESS=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
CONFIG_MOUSE_PS2_FOCALTECH=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SMBUS=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_PS2_TRACKPOINT=y
CONFIG_MQ_IOSCHED_DEADLINE=y
CONFIG_MQ_IOSCHED_KYBER=y
# CONFIG_MTD is not set
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NAMESPACES=y
CONFIG_NEED_SRCU_NMI_SAFE=y
CONFIG_NEON=y
CONFIG_NET_DEVMEM=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_HANDSHAKE=y
CONFIG_NET_IP_TUNNEL=y
CONFIG_NET_NS=y
CONFIG_NET_PTP_CLASSIFY=y
# CONFIG_NET_SCHED is not set
CONFIG_NET_SELFTESTS=y
# CONFIG_NET_SWITCHDEV is not set
CONFIG_NET_VENDOR_ASIX=y
CONFIG_NET_VENDOR_ENGLEDER=y
CONFIG_NET_VENDOR_FUNGIBLE=y
CONFIG_NET_VENDOR_LITEX=y
CONFIG_NET_VENDOR_MICROSOFT=y
CONFIG_NET_VENDOR_VERTEXCOM=y
CONFIG_NET_VENDOR_WANGXUN=y
# CONFIG_NEW_LEDS is not set
CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_DISABLE_UDP_SUPPORT=y
CONFIG_NFS_FS=y
CONFIG_NFS_USE_KERNEL_DNS=y
# CONFIG_NFS_USE_LEGACY_DNS is not set
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=16
CONFIG_NVMEM=y
CONFIG_NVMEM_LAYOUTS=y
CONFIG_NVMEM_SYSFS=y
CONFIG_OF_MDIO=y
# CONFIG_OF_PARTITION is not set
CONFIG_OID_REGISTRY=y
CONFIG_OUTER_CACHE=y
CONFIG_OUTER_CACHE_SYNC=y
CONFIG_PAGE_COUNTER=y
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_PCS_XPCS=y
CONFIG_PER_VMA_LOCK=y
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
# CONFIG_PHY_HISI_INNO_USB2 is not set
CONFIG_PHY_HIX5HD2_SATA=y
CONFIG_PID_NS=y
CONFIG_PINCTRL=y
CONFIG_PL330_DMA=y
CONFIG_PM=y
CONFIG_PM_CLK=y
CONFIG_PM_SLEEP=y
CONFIG_PM_SLEEP_SMP=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_HISI=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_POWER_SUPPLY_HWMON=y
CONFIG_PPS=y
CONFIG_PREEMPT=y
CONFIG_PREEMPTION=y
CONFIG_PREEMPT_BUILD=y
CONFIG_PREEMPT_COUNT=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_RCU=y
CONFIG_PRINTK_TIME=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PWM=y
# CONFIG_PWM_HIBVT is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=21
CONFIG_RCU_TRACE=y
CONFIG_RD_BZIP2=y
CONFIG_RD_GZIP=y
CONFIG_RD_LZ4=y
CONFIG_RD_LZMA=y
CONFIG_RD_LZO=y
CONFIG_RD_XZ=y
CONFIG_RD_ZSTD=y
CONFIG_REALTEK_PHY=y
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_HISI=y
CONFIG_RFS_ACCEL=y
CONFIG_ROOT_NFS=y
CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_RPS=y
CONFIG_RSEQ=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_CMOS is not set
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_NVMEM=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SATA_HOST=y
CONFIG_SATA_PMP=y
# CONFIG_SCHED_CORE is not set
CONFIG_SCHED_MC=y
CONFIG_SCHED_MM_CID=y
CONFIG_SCHED_SMT=y
# CONFIG_SCHED_STACK_END_CHECK is not set
CONFIG_SCSI=y
CONFIG_SCSI_COMMON=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
# CONFIG_SECURITY_DMESG_RESTRICT is not set
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_DWLIB=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIO=y
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_SERPORT=y
CONFIG_SG_POOL=y
# CONFIG_SLAB_BUCKETS is not set
# CONFIG_SLAB_FREELIST_HARDENED is not set
# CONFIG_SLAB_FREELIST_RANDOM is not set
CONFIG_SLAB_OBJ_EXT=y
CONFIG_SLUB_DEBUG=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
CONFIG_SOCK_DIAG=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_PL022=y
CONFIG_SPLIT_PTE_PTLOCKS=y
CONFIG_STACKDEPOT=y
CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y
CONFIG_STACKTRACE=y
# CONFIG_STAGING is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_SWPHY=y
CONFIG_SWP_EMULATE=y
CONFIG_SYNC_FILE=y
# CONFIG_SYN_COOKIES is not set
CONFIG_SYSFS_SYSCALL=y
# CONFIG_SYSVIPC is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TRACE_CLOCK=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
# CONFIG_UEVENT_HELPER is not set
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_HID=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_PHY=y
CONFIG_USB_STORAGE=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_XHCI_HCD=y
# CONFIG_USB_XHCI_PLATFORM is not set
CONFIG_USER_NS=y
CONFIG_UTS_NS=y
CONFIG_VFP=y
CONFIG_VFPv3=y
CONFIG_VIDEO=y
# CONFIG_VLAN_8021Q is not set
CONFIG_VMAP_STACK=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_VT_CONSOLE_SLEEP=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_WATCHDOG is not set
CONFIG_WLAN_VENDOR_ADMTEK=y
CONFIG_WLAN_VENDOR_ATH=y
CONFIG_WLAN_VENDOR_ATMEL=y
CONFIG_WLAN_VENDOR_BROADCOM=y
CONFIG_WLAN_VENDOR_INTEL=y
CONFIG_WLAN_VENDOR_INTERSIL=y
CONFIG_WLAN_VENDOR_MARVELL=y
CONFIG_WLAN_VENDOR_MEDIATEK=y
CONFIG_WLAN_VENDOR_MICROCHIP=y
CONFIG_WLAN_VENDOR_PURELIFI=y
CONFIG_WLAN_VENDOR_QUANTENNA=y
CONFIG_WLAN_VENDOR_RALINK=y
CONFIG_WLAN_VENDOR_REALTEK=y
CONFIG_WLAN_VENDOR_RSI=y
CONFIG_WLAN_VENDOR_SILABS=y
CONFIG_WLAN_VENDOR_ST=y
CONFIG_WLAN_VENDOR_TI=y
CONFIG_WLAN_VENDOR_ZYDAS=y
# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
CONFIG_XPS=y
CONFIG_XXHASH=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_ARM64=y
CONFIG_XZ_DEC_ARMTHUMB=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_XZ_DEC_POWERPC=y
CONFIG_XZ_DEC_RISCV=y
CONFIG_XZ_DEC_SPARC=y
CONFIG_XZ_DEC_X86=y
CONFIG_ZSTD_COMMON=y
CONFIG_ZSTD_DECOMPRESS=y
CONFIG_FS_STACK=y
CONFIG_EXPORTFS=y
CONFIG_OVERLAY_FS=y
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU=y
CONFIG_SQUASHFS_ZLIB=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_EMBEDDED=y
CONFIG_ZLIB_INFLATE=y
CONFIG_XZ_DEC=y
@@ -0,0 +1,7 @@
BOARDNAME:=HiSilicon Hi3798MV100
# Hi3798MV100 Cortex-A7
CPU_TYPE:=cortex-a7
CPU_SUBTYPE:=neon-vfpv4
FEATURES:=ext4 squashfs usb fpu neon rtc
DEFAULT_PACKAGES += kmod-usb-storage kmod-fs-ext4 kmod-fs-f2fs f2fs-tools
@@ -0,0 +1,46 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
KERNEL_LOADADDR := 0x02000000
KERNEL_ENTRYADDR := 0x02000000
define Device/Default
PROFILES := Default
KERNEL := kernel-bin | append-dtb | uImage none
IMAGES := sysupgrade.bin
DEVICE_DTS_DIR = $$(DTS_DIR)/hisilicon
IMAGE/sysupgrade.bin := append-kernel | pad-to 16M | append-rootfs | append-metadata
endef
define Device/huawei_ec6108v9c
DEVICE_VENDOR := Huawei
DEVICE_MODEL := EC6108V9C
DEVICE_DTS := hi3798mv100-ec6108v9c
KERNEL_NAME := zImage
IMAGES := sysupgrade.bin kernel.bin rootfs.squashfs
ARTIFACTS := partition.xml bootargs.bin
IMAGE/kernel.bin := append-kernel
IMAGE/rootfs.squashfs := append-rootfs
# sysupgrade.bin (from Default)
ARTIFACT/bootargs.bin := mkbootargs-bin
ARTIFACT/partition.xml := gen-partition-xml-from-template
endef
TARGET_DEVICES += huawei_ec6108v9c
define Build/gen-partition-xml-from-template
sed -e 's|@@BOOTARGS_FILE@@|$(DEVICE_IMG_PREFIX)-bootargs.bin|g' \
-e 's|@@KERNEL_FILE@@|$(DEVICE_IMG_PREFIX)-squashfs-kernel.bin|g' \
-e 's|@@ROOTFS_FILE@@|$(DEVICE_IMG_PREFIX)-squashfs-rootfs.squashfs|g' \
$(CURDIR)/partition.xml.template > $@
endef
define Build/mkbootargs-bin
mkbootargs \
-s 64 \
-r $(CURDIR)/bootargs.txt \
-o $@
endef
$(eval $(call BuildImage))
@@ -0,0 +1,16 @@
baudrate=115200
ethaddr=00:00:00:00:00:00
ipaddr=192.168.1.10
netmask=255.255.255.0
gatewayip=192.168.1.1
serverip=192.168.1.1
bootcmd=mmc read 0 0x01000000 0x1000 0x8000;bootm 0x01000000
bootargs_512M=mem=512M mmz=ddr,0,0,320M
bootargs_768M=mem=768M mmz=ddr,0,0,400M
bootargs_1G=mem=1G mmz=ddr,0,0,400M
bootargs_2G=mem=2G mmz=ddr,0,0,600M
bootargs=console=ttyAMA0,115200 root=/dev/mmcblk0p4 rootfstype=squashfs rootwait random.trust_cpu=on ip=dhcp blkdevparts=mmcblk0:1M(boot),1M(bootargs),16M(kernel),512M(rootfs),512M(rootfs_data),-(others)
bootdelay=0
stdin=serial
stdout=serial
stderr=serial
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="GB2312" ?>
<Partition_Info ProgrammerFile="">
<Part Sel="0" PartitionName="fastboot" FlashType="emmc" FileSystem="none" Start="0" Length="1M" SelectFile="fastboot.bin"/>
<Part Sel="1" PartitionName="bootargs" FlashType="emmc" FileSystem="none" Start="1M" Length="1M" SelectFile="@@BOOTARGS_FILE@@"/>
<Part Sel="1" PartitionName="kernel" FlashType="emmc" FileSystem="none" Start="2M" Length="16M" SelectFile="@@KERNEL_FILE@@"/>
<Part Sel="1" PartitionName="rootfs" FlashType="emmc" FileSystem="squashfs" Start="18M" Length="512M" SelectFile="@@ROOTFS_FILE@@"/>
<Part Sel="1" PartitionName="rootfs_data" FlashType="emmc" FileSystem="f2fs" Start="530M" Length="512M" SelectFile=""/>
</Partition_Info>
@@ -0,0 +1,785 @@
--- /dev/null
+++ b/arch/arm/boot/dts/hisilicon/hi3798.dtsi
@@ -0,0 +1,782 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Based on arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
+ *
+ * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
+ * Copyright (c) 2023 David Yang
+ */
+
+#include <dt-bindings/clock/histb-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy.h>
+
+/ {
+ compatible = "hisilicon,hi3798";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ xtal24mhz: xtal24mhz@24M {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ };
+
+ i2c_hdmi: i2c-hdmi {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio4 4 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio4 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ i2c-gpio,sda-open-drain;
+ i2c-gpio,scl-open-drain;
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ status = "disabled";
+ };
+
+ soc: soc@f0000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&gic>;
+ ranges = <0 0xf0000000 0x10000000>;
+
+ crg: clock-reset-controller@8a22000 {
+ compatible = "hisilicon,cpuctrl", "syscon", "simple-mfd";
+ reg = <0x8a22000 0x2000>;
+ #clock-cells = <1>;
+ #reset-cells = <2>;
+ };
+
+ sysctrl: system-controller@8000000 {
+ compatible = "syscon";
+ reg = <0x8000000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <2>;
+ };
+
+ rng: rng@8005000 {
+ compatible = "hisilicon,histb-rng";
+ reg = <0x8005000 0xc>;
+ };
+
+ reboot {
+ compatible = "syscon-reboot";
+ regmap = <&sysctrl>;
+ offset = <0x4>;
+ mask = <0xdeadbeef>;
+ };
+
+ perictrl: peripheral-controller@8a20000 {
+ compatible = "syscon", "simple-mfd";
+ reg = <0x8a20000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x8a20000 0x1000>;
+
+ usb2_phy1: usb2-phy@124 {
+ compatible = "hisilicon,hi3798mv100-usb2-phy";
+ reg = <0x124 0x4>;
+ clocks = <&crg HISTB_USB2_PHY1_REF_CLK>;
+ resets = <&crg 0xbc 8>;
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb2_phy1_port0: phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ resets = <&crg 0xbc 9>;
+ };
+
+ usb2_phy1_port1: phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ resets = <&crg 0xbc 11>;
+ };
+ };
+
+ usb2_phy2: usb2-phy@158 {
+ compatible = "hisilicon,hi3798mv100-usb2-phy";
+ reg = <0x158 0x4>;
+ clocks = <&crg HISTB_USB2_2_PHY1_REF_CLK>;
+ resets = <&crg 0x190 8>;
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb2_phy2_port0: phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ resets = <&crg 0x190 9>;
+ };
+ };
+
+ combphy0: phy@850 {
+ compatible = "hisilicon,hi3798cv200-combphy";
+ reg = <0x850 0x8>;
+ #phy-cells = <1>;
+ clocks = <&crg HISTB_COMBPHY0_CLK>;
+ resets = <&crg 0x188 4>;
+ assigned-clocks = <&crg HISTB_COMBPHY0_CLK>;
+ assigned-clock-rates = <100000000>;
+ hisilicon,fixed-mode = <PHY_TYPE_USB3>;
+ status = "disabled";
+ };
+
+ combphy1: phy@858 {
+ compatible = "hisilicon,hi3798cv200-combphy";
+ reg = <0x858 0x8>;
+ #phy-cells = <1>;
+ clocks = <&crg HISTB_COMBPHY1_CLK>;
+ resets = <&crg 0x188 12>;
+ assigned-clocks = <&crg HISTB_COMBPHY1_CLK>;
+ assigned-clock-rates = <100000000>;
+ hisilicon,mode-select-bits = <0x0008 11 (0x3 << 11)>;
+ status = "disabled";
+ };
+ };
+
+ pmx0: pinconf@8a21000 {
+ compatible = "pinconf-single";
+ reg = <0x8a21000 0x180>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <7>;
+
+ range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+ };
+
+ apb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ ir: ir@8001000 {
+ compatible = "hisilicon,hix5hd2-ir";
+ reg = <0x8001000 0x1000>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sysctrl HISTB_IR_CLK>;
+ clock-names = "apb_pclk";
+ resets = <&sysctrl 0x48 5>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ timer0: timer@8002000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x8002000 0x1000>;
+ /* timer00 & timer01 */
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&xtal24mhz>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ timer1: timer@8a29000 {
+ /*
+ * Only used in NORMAL state, not available in
+ * SLOW or DOZE state.
+ * The rate is fixed in 24MHz.
+ */
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x8a29000 0x1000>;
+ /* timer10 & timer11 */
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&xtal24mhz>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ timer2: timer@8a2a000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x8a2a000 0x1000>;
+ /* timer20 & timer21 */
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&xtal24mhz>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ timer3: timer@8a2b000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x8a2b000 0x1000>;
+ /* timer30 & timer31 */
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&xtal24mhz>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ timer4: timer@8a81000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x8a81000 0x1000>;
+ /* timer40 & timer41 */
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&xtal24mhz>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart0: uart@8b00000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x8b00000 0x1000>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sysctrl HISTB_UART0_CLK>, <&sysctrl HISTB_UART0_CLK>;
+ clock-names = "uartclk", "apb_pclk";
+ resets = <&sysctrl 0x48 13>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ uart1: uart@8006000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x8006000 0x1000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_UART1_CLK>, <&crg HISTB_UART1_CLK>;
+ clock-names = "uartclk", "apb_pclk";
+ resets = <&crg 0x68 1>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ uart2: uart@8b02000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x8b02000 0x1000>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_UART2_CLK>, <&crg HISTB_UART2_CLK>;
+ clock-names = "uartclk", "apb_pclk";
+ resets = <&crg 0x68 5>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ gpio0: gpio@8b20000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b20000 0x1000>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio1: gpio@8b21000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b21000 0x1000>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio2: gpio@8b22000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b22000 0x1000>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio3: gpio@8b23000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b23000 0x1000>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio4: gpio@8b24000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b24000 0x1000>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio5: gpio@8004000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8004000 0x1000>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio6: gpio@8b26000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b26000 0x1000>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio7: gpio@8b27000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b27000 0x1000>;
+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio8: gpio@8b28000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b28000 0x1000>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio9: gpio@8b29000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b29000 0x1000>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio10: gpio@8b2a000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b2a000 0x1000>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio11: gpio@8b2b000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b2b000 0x1000>;
+ interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio12: gpio@8b2c000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x8b2c000 0x1000>;
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ wdt0: watchdog@8a2c000 {
+ compatible = "arm,sp805-wdt", "arm,primecell";
+ arm,primecell-periphid = <0x00141805>;
+ reg = <0x8a2c000 0x1000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_APB_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ mkl: mkl@8a90000 {
+ compatible = "hisilicon,advca-mkl";
+ reg = <0x8a90000 0x1000>;
+ /* clocks = <&crg HISTB_CA_BUS_CLK>; */
+ resets = <&crg 0xc0 8>;
+ };
+
+ otp: otp@8ab0000 {
+ compatible = "hisilicon,advca-otp";
+ reg = <0x8ab0000 0x1000>;
+ /* clocks = <&crg HISTB_OTP_CLK>; */
+ resets = <&crg 0xc0 10>;
+ };
+
+ hdmi: hdmi@8ce0000 {
+ compatible = "hisilicon,histb-hdmi-1-4";
+ reg = <0x8ce0000 0x10000>;
+ /* clocks = <&crg HISTB_OTP_CLK>;
+ clock-names = "base"; */
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&crg 0x10c 9>, <&crg 0x10c 8>, <&crg 0x110 4>;
+ reset-names = "base", "bus", "phy";
+ };
+
+ cipher@9a00000 {
+ compatible = "hisilicon,hi3798mv100-advca-muc";
+ reg = <0x9a00000 0x10000>, <0x99f0000 0x1000>;
+ reg-names = "base", "mmu";
+ /* clocks = <&crg HISTB_CIPHER_CLK>, <&crg HISTB_CIPHER_BUS_CLK>;
+ clock-names = "base", "bus"; */
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "base", "secure";
+ /* resets = <&crg 0xc0 9>, <&crg 0x378 4>;
+ reset-names = "base", "mmu"; */
+ };
+
+ hash0: hash@9a10000 {
+ compatible = "hisilicon,hi3798mv100-advca-sha";
+ reg = <0x9a10000 0x1000>;
+ /* clocks = <&crg HISTB_SHA0_CLK>; */
+ resets = <&crg 0xc4 4>;
+ status = "disabled";
+ };
+
+ hash1: hash@9a20000 {
+ compatible = "hisilicon,hi3798mv100-advca-sha";
+ reg = <0x9a20000 0x1000>;
+ /* clocks = <&crg HISTB_SHA1_CLK>; */
+ resets = <&crg 0xc4 6>;
+ status = "disabled";
+ };
+
+ sign@9a30000 {
+ compatible = "hisilicon,advca-sign";
+ reg = <0x9a30000 0x1000>;
+ resets = <&crg 0x384 4>;
+ };
+
+ i2c0: i2c@8b10000 {
+ compatible = "hisilicon,hix5hd2-i2c";
+ reg = <0x8b10000 0x1000>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <400000>;
+ clocks = <&crg HISTB_I2C0_CLK>;
+ resets = <&crg 0x6c 5>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ i2c1: i2c@8b11000 {
+ compatible = "hisilicon,hix5hd2-i2c";
+ reg = <0x8b11000 0x1000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <400000>;
+ clocks = <&crg HISTB_I2C1_CLK>;
+ resets = <&crg 0x6c 9>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ i2c2: i2c@8b12000 {
+ compatible = "hisilicon,hix5hd2-i2c";
+ reg = <0x8b12000 0x1000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <400000>;
+ clocks = <&crg HISTB_I2C2_CLK>;
+ resets = <&crg 0x6c 13>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ spi0: spi@8b1a000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0x8b1a000 0x1000>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <1>;
+ clocks = <&crg HISTB_SPI0_CLK>, <&crg HISTB_SPI0_CLK>;
+ clock-names = "sspclk", "apb_pclk";
+ resets = <&crg 0x70 1>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ vddcpu: regulator@8a23018 {
+ compatible = "hisilicon,histb-volt";
+ reg = <0x8a23018 4>;
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-always-on;
+ };
+
+ vddcore: regulator@8a2301c {
+ compatible = "hisilicon,histb-volt";
+ reg = <0x8a2301c 4>;
+ regulator-name = "vdd-core";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-always-on;
+ };
+
+ vddgpu: regulator@8a23020 {
+ compatible = "hisilicon,histb-volt";
+ reg = <0x8a23020 4>;
+ regulator-name = "vdd-gpu";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-always-on;
+ };
+ };
+
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ gpu: gpu@9200000 {
+ compatible = "arm,mali-450", "arm,mali-utgard";
+ reg = <0x9200000 0x30000>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gp", "gpmmu", "pp0", "ppmmu0", "pp1",
+ "ppmmu1", "pmu", "pp";
+ pmu_domain_config = <0x1 0x2 0x2 0x0 0x0 0x0 0x0 0x0 0x0 0x1 0x2 0x0>;
+ pmu_switch_delay = <0x1ff>;
+
+ clocks = <&crg HISTB_GPU_BUS_CLK>, <&crg HISTB_GPU_CORE_CLK>;
+ clock-names = "bus", "core";
+ resets = <&crg 0xd4 4>;
+ status = "disabled";
+
+ mali-supply = <&vddgpu>;
+ operating-points = <150000 000000
+ 200000 000000
+ 250000 000000
+ 300000 000000
+ 345600 000000
+ 400000 000000
+ 432000 000000
+ 500000 000000>;
+ cooling-min-state = <0>;
+ cooling-max-state = <7>;
+ #cooling-cells = <2>; /* min followed by max */
+ };
+
+ nand: nand@9810000 {
+ compatible = "hisilicon,hinfc610";
+ reg = <0x9810000 0x100>, <0xf000000 0x2176>;
+ /* clocks = <&crg HISTB_NAND_CLK>; */
+ clock-names = "apb_pclk";
+ resets = <&crg 0x60 4>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ /* unremovable emmc as mmcblk0 */
+ emmc: mmc@9830000 {
+ compatible = "hisilicon,hi3798cv200-dw-mshc";
+ reg = <0x9830000 0x10000>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_MMC_CIU_CLK>,
+ <&crg HISTB_MMC_BIU_CLK>,
+ <&crg HISTB_MMC_SAMPLE_CLK>,
+ <&crg HISTB_MMC_DRV_CLK>;
+ clock-names = "ciu", "biu", "ciu-sample", "ciu-drive";
+ resets = <&crg 0xa0 4>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ sd: mmc@9820000 {
+ compatible = "snps,dw-mshc";
+ reg = <0x9820000 0x10000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_SDIO0_CIU_CLK>,
+ <&crg HISTB_SDIO0_BIU_CLK>;
+ clock-names = "ciu", "biu";
+ resets = <&crg 0x9c 4>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ pcie: pcie@9860000 {
+ compatible = "hisilicon,hi3798cv200-pcie";
+ reg = <0x9860000 0x1000>,
+ <0x0 0x2000>,
+ <0x2000000 0x01000000>;
+ reg-names = "control", "rc-dbi", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ ranges = <0x81000000 0x0 0x00000000 0x4f00000 0x0 0x100000>,
+ <0x82000000 0x0 0x3000000 0x3000000 0x0 0x01f00000>;
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic 0 131 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_PCIE_AUX_CLK>,
+ <&crg HISTB_PCIE_PIPE_CLK>,
+ <&crg HISTB_PCIE_SYS_CLK>,
+ <&crg HISTB_PCIE_BUS_CLK>;
+ clock-names = "aux", "pipe", "sys", "bus";
+ resets = <&crg 0x18c 6>, <&crg 0x18c 5>, <&crg 0x18c 4>;
+ reset-names = "soft", "sys", "bus";
+ phys = <&combphy1 PHY_TYPE_PCIE>;
+ phy-names = "phy";
+ status = "disabled";
+ };
+
+ dmac: dmac@9870000 {
+ compatible = "hisilicon,hi3798mv100-dmac";
+ reg = <0x9870000 0x10000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_DMAC_CLK>;
+ resets = <&crg 0xa4 4>;
+ status = "disabled";
+ };
+
+ ohci0: usb@9880000 {
+ compatible = "generic-ohci";
+ reg = <0x9880000 0x10000>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_USB2_BUS_CLK>,
+ <&crg HISTB_USB2_12M_CLK>,
+ <&crg HISTB_USB2_48M_CLK>;
+ clock-names = "bus", "clk12", "clk48";
+ resets = <&crg 0xb8 12>;
+ reset-names = "bus";
+ phys = <&usb2_phy1_port0>, <&usb2_phy1_port1>;
+ phy-names = "usb0", "usb1";
+ status = "disabled";
+ };
+
+ ehci0: usb@9890000 {
+ compatible = "generic-ehci";
+ reg = <0x9890000 0x10000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_USB2_BUS_CLK>,
+ <&crg HISTB_USB2_PHY_CLK>,
+ <&crg HISTB_USB2_UTMI_CLK>,
+ <&crg HISTB_USB2_UTMI_CLK1>;
+ clock-names = "bus", "phy", "utmi0", "utmi1";
+ resets = <&crg 0xb8 12>,
+ <&crg 0xb8 16>,
+ <&crg 0xb8 13>,
+ <&crg 0xb8 14>;
+ reset-names = "bus", "phy", "utmi0", "utmi1";
+ phys = <&usb2_phy1_port0>, <&usb2_phy1_port1>;
+ phy-names = "usb0", "usb1";
+ status = "disabled";
+ };
+
+ xhci0: usb@98a0000 {
+ compatible = "generic-xhci";
+ reg = <0x98a0000 0x10000>;
+ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_USB3_BUS_CLK>,
+ <&crg HISTB_USB3_UTMI_CLK>,
+ <&crg HISTB_USB3_PIPE_CLK>,
+ <&crg HISTB_USB3_SUSPEND_CLK>;
+ clock-names = "bus", "utmi0", "pipe", "suspend";
+ resets = <&crg 0xb0 12>;
+ reset-names = "vcc";
+ status = "disabled";
+ };
+
+ ohci1: usb@9920000 {
+ compatible = "generic-ohci";
+ reg = <0x9920000 0x10000>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_USB2_2_BUS_CLK>,
+ <&crg HISTB_USB2_2_12M_CLK>,
+ <&crg HISTB_USB2_2_48M_CLK>;
+ clock-names = "bus", "clk12", "clk48";
+ resets = <&crg 0x198 12>;
+ reset-names = "bus";
+ phys = <&usb2_phy2_port0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci1: usb@9930000 {
+ compatible = "generic-ehci";
+ reg = <0x9930000 0x10000>;
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_USB2_2_BUS_CLK>,
+ <&crg HISTB_USB2_2_PHY_CLK>,
+ <&crg HISTB_USB2_2_UTMI_CLK>;
+ clock-names = "bus", "phy", "utmi";
+ resets = <&crg 0x198 12>,
+ <&crg 0x198 16>,
+ <&crg 0x198 14>;
+ reset-names = "bus", "phy", "utmi";
+ phys = <&usb2_phy2_port0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+ };
+ };
+};
@@ -0,0 +1,232 @@
--- /dev/null
+++ b/arch/arm/boot/dts/hisilicon/hi3798mv100.dtsi
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) 2023 David Yang
+ */
+
+#include <dt-bindings/pinctrl/hisi.h>
+#include "hi3798-s5.dtsi"
+
+#define PINCTRL_REG(i) ((i) * 4)
+
+/* value, enable bits, disable bits, mask */
+#define PINCTRL_PULLDOWN(value, enable, disable, mask) \
+ (value << 12) (enable << 12) (disable << 12) (mask << 12)
+#define PINCTRL_PULLUP(value, enable, disable, mask) \
+ (value << 12) (enable << 12) (disable << 12) (mask << 12)
+#define PINCTRL_SLEW_RATE(value, mask) (value << 8) (mask << 8)
+#define PINCTRL_DRV_STRENGTH(value, mask) (value << 9) (mask << 9)
+
+/ {
+ compatible = "hisilicon,hi3798mv100";
+};
+
+&soc {
+ eth0: ethernet@9840000 {
+ compatible = "hisilicon,hisi-femac-v2";
+ reg = <0x9840000 0x1000>, <0x9841300 0x200>;
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_ETH0_MAC_CLK>;
+ resets = <&crg 0xcc 4>, <&crg 0x120 4>;
+ reset-names = "mac", "phy";
+ status = "disabled";
+
+ phy-handle = <&phy1>;
+ phy-mode = "mii";
+ hisilicon,phy-reset-delays-us = <10000 10000 20000>;
+ };
+
+ mdio0: mdio@9841100 {
+ compatible = "hisilicon,hisi-femac-mdio";
+ reg = <0x9841100 0x10>;
+ clocks = <&crg HISTB_FEPHY_CLK>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy1: phy@1 {
+ reg = <1>;
+ /* Placeholder, overwritten by bootloader */
+ mac-address = [00 00 00 00 00 00];
+ };
+ };
+};
+
+&crg {
+ compatible = "hisilicon,hi3798mv100-crg", "hisilicon,cpuctrl", "syscon", "simple-mfd";
+};
+
+&sysctrl {
+ compatible = "hisilicon,hi3798mv100-sysctrl", "syscon";
+};
+
+&pmx0 {
+ pinctrl-single,gpio-range = <
+ &range 8 3 2 /* GPIO0_0..2 */
+ &range 79 1 0 /* GPIO0_3 */
+ &range 21 4 5 /* GPIO0_4..7 */
+ &range 25 1 5 /* GPIO2_0 */
+ &range 54 1 2 /* GPIO2_1 */
+ &range 55 2 0 /* GPIO2_2..3 */
+ &range 78 1 1 /* GPIO2_5 */
+ &range 31 1 6 /* GPIO2_6 */
+ &range 32 1 1 /* GPIO2_7 */
+ &range 57 8 0 /* GPIO3_0..7 */
+ &range 80 2 0 /* GPIO4_0..1 */
+ &range 43 1 2 /* GPIO4_2 */
+ &range 44 1 0 /* GPIO4_3 */
+ &range 45 4 2 /* GPIO4_4..7 */
+ &range 82 8 0 /* GPIO6_0..7 */
+ >;
+
+ emmc {
+ emmc_data: emmc-data {
+ pinctrl-single,pins = <
+ PINCTRL_REG(0) MUX_M1 /* SDIO1_CDATA7 */
+ PINCTRL_REG(1) MUX_M1 /* SDIO1_CDATA6 */
+ PINCTRL_REG(2) MUX_M1 /* SDIO1_CDATA5 */
+ PINCTRL_REG(3) MUX_M1 /* SDIO1_CDATA4 */
+ PINCTRL_REG(4) MUX_M1 /* SDIO1_CDATA3 */
+ PINCTRL_REG(5) MUX_M1 /* SDIO1_CDATA2 */
+ PINCTRL_REG(6) MUX_M1 /* SDIO1_CDATA1 */
+ PINCTRL_REG(7) MUX_M1 /* SDIO1_CDATA0 */
+ >;
+ };
+
+ emmc_detect: emmc-detect {
+ pinctrl-single,pins = <
+ PINCTRL_REG(8) MUX_M1 /* SDIO1_CARD_DETECT */
+ PINCTRL_REG(9) MUX_M1 /* SDIO1_CARD_POWER_EN */
+ >;
+ };
+
+ emmc_cwpr: emmc-cwpr {
+ pinctrl-single,pins = <
+ PINCTRL_REG(10) MUX_M1 /* SDIO1_CWPR */
+ >;
+ };
+
+ emmc_ccmd: emmc-ccmd {
+ pinctrl-single,pins = <
+ PINCTRL_REG(11) MUX_M1 /* SDIO1_CCMD */
+ >;
+ };
+
+ emmc_cclk_out: emmc-cclk-out {
+ pinctrl-single,pins = <
+ PINCTRL_REG(12) MUX_M1 /* SDIO1_CCLK_OUT */
+ >;
+ };
+
+ emmc_rst: emmc-rst {
+ pinctrl-single,pins = <
+ PINCTRL_REG(13) MUX_M1 /* SDIO1_RST */
+ >;
+ };
+ };
+
+ hdmi {
+ hdmi_hotplug: hdmi-hotplug {
+ pinctrl-single,pins = <
+ PINCTRL_REG(47) MUX_M1 /* HDMITX_HOTPLUG */
+ >;
+ };
+ };
+};
+
+/*
+ * Don't just copy gpio-ranges
+ * Some GPIO pins cannot coexist with other peripherals; check datasheet
+ * or pray for a proper bootloader
+ */
+&gpio0 {
+/*
+ gpio-ranges = <
+ &pmx0 0 8 3
+ &pmx0 3 79 1
+ &pmx0 4 21 4
+ >;
+*/
+ gpio-line-names =
+ "GPIO0_0", "GPIO0_1", "GPIO0_2", "GPIO0_3",
+ "GPIO0_4", "GPIO0_5", "GPIO0_6", "GPIO0_7";
+};
+
+&gpio2 {
+/*
+ gpio-ranges = <
+ &pmx0 0 25 1
+ &pmx0 1 54 1
+ &pmx0 2 55 2
+ &pmx0 5 78 1
+ &pmx0 6 31 2
+ >;
+*/
+ gpio-line-names =
+ "GPIO2_0", "GPIO2_1", "GPIO2_2", "GPIO2_3",
+ "", "GPIO2_5", "GPIO2_6", "GPIO2_7";
+};
+
+&gpio3 {
+/*
+ gpio-ranges = <
+ &pmx0 0 57 8
+ >;
+*/
+ gpio-line-names =
+ "GPIO3_0", "GPIO3_1", "GPIO3_2", "GPIO3_3",
+ "GPIO3_4", "GPIO3_5", "GPIO3_6", "GPIO3_7";
+};
+
+&gpio4 {
+/*
+ gpio-ranges = <
+ &pmx0 0 80 2
+ &pmx0 2 43 6
+ >;
+*/
+ gpio-line-names =
+ "GPIO4_0", "GPIO4_1", "GPIO4_2", "GPIO4_3",
+ "GPIO4_4", "GPIO4_5", "GPIO4_6", "GPIO4_7";
+ status = "okay";
+};
+
+&gpio5 {
+ gpio-line-names =
+ "GPIO5_0", "GPIO5_1", "GPIO5_2", "",
+ "", "GPIO5_5", "GPIO5_6", "";
+};
+
+&gpio6 {
+/*
+ gpio-ranges = <
+ &pmx0 0 82 8
+ >;
+*/
+ gpio-line-names =
+ "GPIO6_0", "GPIO6_1", "GPIO6_2", "GPIO6_3",
+ "GPIO6_4", "GPIO6_5", "GPIO6_6", "GPIO6_7";
+};
+
+&hdmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_hotplug>;
+};
+
+&dmac {
+ status = "okay";
+};
+
+&usb2_phy1 {
+ status = "okay";
+};
+
+&usb2_phy2 {
+ status = "okay";
+};
+
+&wdt0 {
+ status = "okay";
+};
@@ -0,0 +1,195 @@
--- /dev/null
+++ b/arch/arm/boot/dts/hisilicon/hi3798mv100-ec6108v9c.dts
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) 2023 David Yang
+ */
+
+/dts-v1/;
+#include "hi3798mv100.dtsi"
+
+/ {
+ model = "Huawei EC6108V9C";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ network {
+ label = "green:network";
+ gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ network-activity {
+ label = "red:network";
+ gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ ir {
+ label = "green:ir";
+ gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ panic-indicator;
+ default-state = "off";
+ };
+ };
+};
+
+&emmc_data {
+ pinctrl-single,bias-pulldown = <
+ PINCTRL_PULLDOWN(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(6, 7)
+ >;
+};
+
+&emmc_detect {
+ pinctrl-single,bias-pulldown = <
+ PINCTRL_PULLDOWN(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(3, 3)
+ >;
+};
+
+&emmc_ccmd {
+ pinctrl-single,bias-pullup = <
+ PINCTRL_PULLUP(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(6, 7)
+ >;
+};
+
+&emmc_cclk_out {
+ pinctrl-single,bias-pulldown = <
+ PINCTRL_PULLDOWN(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(5, 7)
+ >;
+};
+
+&emmc_rst {
+ pinctrl-single,bias-pullup = <
+ PINCTRL_PULLUP(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(3, 3)
+ >;
+};
+
+&timer1 {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&gpio0 {
+ gpio-ranges = <
+ &pmx0 2 10 1
+ &pmx0 3 79 1
+ &pmx0 4 21 4
+ >;
+ status = "okay";
+};
+
+&gpio2 {
+ gpio-ranges = <
+ &pmx0 0 25 1
+ &pmx0 1 54 1
+ &pmx0 2 55 2
+ >;
+ status = "okay";
+};
+
+&gpio4 {
+ gpio-ranges = <
+ &pmx0 0 80 2
+/* &pmx0 4 45 2 */
+ >;
+ status = "okay";
+};
+
+&gpio5 {
+ status = "okay";
+};
+
+&gpio6 {
+ gpio-ranges = <
+ &pmx0 0 82 2
+ >;
+ status = "okay";
+};
+
+&gpu {
+ status = "okay";
+};
+
+&emmc {
+ fifo-depth = <256>;
+ clock-frequency = <100000000>;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ non-removable;
+ status = "okay";
+};
+
+/*
+&sd {
+ status = "okay";
+};
+*/
+
+&eth0 {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ir {
+ status = "okay";
+};
+/*
+&i2c_hdmi {
+ status = "okay";
+};
+*/
@@ -0,0 +1,67 @@
--- /dev/null
+++ b/arch/arm/boot/dts/hisilicon/hi3798-s5.dtsi
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) 2023 David Yang
+ */
+
+#include "hi3798.dtsi"
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "hisilicon,hi3798-smp";
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0>;
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <1>;
+ };
+
+ cpu2: cpu@2 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <2>;
+ };
+
+ cpu3: cpu@3 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <3>;
+ };
+ };
+
+ gic: interrupt-controller@f8a01000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ /* gic dist base, gic cpu base */
+ reg = <0xf8a01000 0x1000>, <0xf8a02000 0x100>;
+ };
+
+ pmu: pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ interrupt-parent = <&gic>;
+ };
+};
+
+&hash0 {
+ status = "okay";
+};
@@ -0,0 +1,12 @@
--- a/arch/arm/boot/dts/hisilicon/Makefile
+++ b/arch/arm/boot/dts/hisilicon/Makefile
@@ -6,7 +6,8 @@ dtb-$(CONFIG_ARCH_HIP01) += \
dtb-$(CONFIG_ARCH_HIP04) += \
hip04-d01.dtb
dtb-$(CONFIG_ARCH_HISI) += \
- hi3519-demb.dtb
+ hi3519-demb.dtb \
+ hi3798mv100-ec6108v9c.dtb
dtb-$(CONFIG_ARCH_HIX5HD2) += \
hisi-x5hd2-dkb.dtb
dtb-$(CONFIG_ARCH_SD5203) += \
@@ -0,0 +1,21 @@
--- a/arch/arm/mach-hisi/core.h
+++ b/arch/arm/mach-hisi/core.h
@@ -4,6 +4,9 @@
#include <linux/reboot.h>
+extern volatile int hisi_pen_release;
+extern void hisi_secondary_startup(void);
+
extern void hi3xxx_set_cpu_jump(int cpu, void *jump_addr);
extern int hi3xxx_get_cpu_jump(int cpu);
extern void secondary_startup(void);
@@ -16,4 +19,8 @@ extern void hix5hd2_set_cpu(int cpu, boo
extern void hix5hd2_cpu_die(unsigned int cpu);
extern void hip01_set_cpu(int cpu, bool enable);
+
+extern void hi3798_set_cpu(int cpu, bool enable);
+extern void hi3798_cpu_die(unsigned int cpu);
+extern int hi3798_cpu_kill(unsigned int cpu);
#endif
@@ -0,0 +1,39 @@
--- /dev/null
+++ b/arch/arm/mach-hisi/headsmp.S
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2003 ARM Limited
+ * All Rights Reserved
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+
+/*
+ * Hisilicon specific entry point for secondary CPUs. This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(hisi_secondary_startup)
+ ARM_BE8(setend be)
+ mrc p15, 0, r0, c0, c0, 5
+ and r0, r0, #15
+ adr r4, 1f
+ ldmia r4, {r5, r6}
+ sub r4, r4, r5
+ add r6, r6, r4
+pen: ldr r7, [r6]
+ cmp r7, r0
+ bne pen
+
+ /*
+ * we've been released from the holding pen: secondary_stack
+ * should now contain the SVC stack for this core
+ */
+ b secondary_startup
+
+ .align
+1: .long .
+ .long hisi_pen_release
+ENDPROC(hisi_secondary_startup)
@@ -0,0 +1,81 @@
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -46,7 +46,77 @@ static const char *const hi3xxx_compat[]
NULL,
};
-DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
+DT_MACHINE_START(HI3620, "HiSilicon Hi3620 (Flattened Device Tree)")
.map_io = hi3620_map_io,
.dt_compat = hi3xxx_compat,
MACHINE_END
+
+#define S40_IOCH1_PHYS_BASE 0xf8000000
+#define S40_IOCH1_VIRT_BASE 0xf9000000
+#define S40_IOCH1_SIZE 0x02000000
+
+static struct map_desc s40_io_desc[] __initdata = {
+ {
+ .pfn = __phys_to_pfn(S40_IOCH1_PHYS_BASE),
+ .virtual = S40_IOCH1_VIRT_BASE,
+ .length = S40_IOCH1_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init s40_map_io(void)
+{
+ debug_ll_io_init();
+ iotable_init(s40_io_desc, ARRAY_SIZE(s40_io_desc));
+}
+
+static const char *const s40_compat[] __initconst = {
+ "hisilicon,hi3796cv200",
+ "hisilicon,hi3796mv200",
+ "hisilicon,hi3798cv200",
+ "hisilicon,hi3798mv200",
+ "hisilicon,hi3798mv300",
+ NULL,
+};
+
+DT_MACHINE_START(S40, "HiSilicon S40 (Flattened Device Tree)")
+ .map_io = s40_map_io,
+ .dt_compat = s40_compat,
+MACHINE_END
+
+#define S5_IOCH2_PHYS_BASE 0xff000000
+#define S5_IOCH2_VIRT_BASE 0xfb000000
+#define S5_IOCH2_SIZE 0x00430000
+
+static struct map_desc s5_io_desc[] __initdata = {
+ {
+ .pfn = __phys_to_pfn(S40_IOCH1_PHYS_BASE),
+ .virtual = S40_IOCH1_VIRT_BASE,
+ .length = S40_IOCH1_SIZE,
+ .type = MT_DEVICE,
+ },
+ {
+ .pfn = __phys_to_pfn(S5_IOCH2_PHYS_BASE),
+ .virtual = S5_IOCH2_VIRT_BASE,
+ .length = S5_IOCH2_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init s5_map_io(void)
+{
+ debug_ll_io_init();
+ iotable_init(s5_io_desc, ARRAY_SIZE(s5_io_desc));
+}
+
+static const char *const s5_compat[] __initconst = {
+ "hisilicon,hi3716cv200",
+ "hisilicon,hi3716mv410",
+ "hisilicon,hi3798mv100",
+ NULL,
+};
+
+DT_MACHINE_START(S5, "HiSilicon S5 (Flattened Device Tree)")
+ .map_io = s5_map_io,
+ .dt_compat = s5_compat,
+MACHINE_END
@@ -0,0 +1,179 @@
--- a/arch/arm/mach-hisi/hotplug.c
+++ b/arch/arm/mach-hisi/hotplug.c
@@ -54,7 +54,7 @@
#define CPU0_SRST_REQ_EN (1 << 0)
#define HIX5HD2_PERI_CRG20 0x50
-#define CRG20_CPU1_RESET (1 << 17)
+#define CRG20_ARM_SRST(i) (1 << ((i) + 16))
#define HIX5HD2_PERI_PMC0 0x1000
#define PMC0_CPU1_WAIT_MTCOMS_ACK (1 << 8)
@@ -64,6 +64,12 @@
#define HIP01_PERI9 0x50
#define PERI9_CPU1_RESET (1 << 1)
+#define HI3798_PERI_CRG18 0x48
+#define CRG18_CPU_SW_BEGIN (1 << 10)
+#define HI3798_PERI_CRG20 0x50
+#define CRG20_ARM_POR_SRST(i) (1 << ((i) + 12))
+#define CRG20_CLUSTER_DBG_SRST(i) (1 << ((i) + 20))
+
enum {
HI3620_CTRL,
ERROR_CTRL,
@@ -203,7 +209,7 @@ void hix5hd2_set_cpu(int cpu, bool enabl
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
/* unreset */
val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
- val &= ~CRG20_CPU1_RESET;
+ val &= ~CRG20_ARM_SRST(cpu);
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
} else {
/* power down cpu1 */
@@ -211,10 +217,9 @@ void hix5hd2_set_cpu(int cpu, bool enabl
val |= PMC0_CPU1_PMC_ENABLE | PMC0_CPU1_POWERDOWN;
val &= ~PMC0_CPU1_WAIT_MTCOMS_ACK;
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
-
/* reset */
val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
- val |= CRG20_CPU1_RESET;
+ val |= CRG20_ARM_SRST(cpu);
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
}
}
@@ -247,6 +252,55 @@ void hip01_set_cpu(int cpu, bool enable)
}
}
+void hi3798_set_cpu(int cpu, bool enable)
+{
+ u32 val;
+ u32 val_crg18;
+
+ if (!ctrl_base)
+ if (!hix5hd2_hotplug_init())
+ BUG();
+
+ if (enable) {
+ val_crg18 = readl_relaxed(ctrl_base + HI3798_PERI_CRG18);
+ /* select 400MHz */
+ val = 0x306;
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG18);
+ val |= CRG18_CPU_SW_BEGIN;
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG18);
+ /* unreset arm_por_srst_req */
+ val = readl_relaxed(ctrl_base + HI3798_PERI_CRG20);
+ val &= ~CRG20_ARM_POR_SRST(cpu);
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG20);
+ /* unreset cluster_dbg_srst_req */
+ val = readl_relaxed(ctrl_base + HI3798_PERI_CRG20);
+ val &= ~CRG20_CLUSTER_DBG_SRST(cpu);
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG20);
+ /* unreset */
+ val = readl_relaxed(ctrl_base + HI3798_PERI_CRG20);
+ val &= ~CRG20_ARM_SRST(cpu);
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG20);
+ /* restore freq */
+ val = val_crg18 & ~CRG18_CPU_SW_BEGIN;
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG18);
+ writel_relaxed(val_crg18, ctrl_base + HI3798_PERI_CRG18);
+ } else {
+ /* reset */
+ val = readl_relaxed(ctrl_base + HI3798_PERI_CRG20);
+ val |= CRG20_ARM_SRST(cpu);
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG20);
+ /* reset cluster_dbg_srst_req */
+ val = readl_relaxed(ctrl_base + HI3798_PERI_CRG20);
+ val |= CRG20_CLUSTER_DBG_SRST(cpu);
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG20);
+ /* reset arm_por_srst_req */
+ val = readl_relaxed(ctrl_base + HI3798_PERI_CRG20);
+ val |= CRG20_ARM_POR_SRST(cpu);
+ writel_relaxed(val, ctrl_base + HI3798_PERI_CRG20);
+ }
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
static inline void cpu_enter_lowpower(void)
{
unsigned int v;
@@ -268,7 +322,45 @@ static inline void cpu_enter_lowpower(vo
: "cc");
}
-#ifdef CONFIG_HOTPLUG_CPU
+static inline void cpu_leave_lowpower(void)
+{
+ unsigned int v;
+
+ asm volatile(
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " orr %0, %0, #0x04\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " orr %0, %0, #0x20\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ :
+ : "cc");
+}
+
+static inline void hisi_do_lowpower(unsigned int cpu, int *spurious)
+{
+ for (;;) {
+ wfi();
+
+ if (hisi_pen_release == cpu) {
+ /*
+ * OK, proper wakeup, we're done
+ */
+ break;
+ }
+
+ /*
+ * Getting here, means that we have come out of WFI without
+ * having been woken up - this shouldn't happen
+ *
+ * Just note it happening - when we're woken, we can report
+ * its occurrence.
+ */
+ (*spurious)++;
+ }
+}
+
void hi3xxx_cpu_die(unsigned int cpu)
{
cpu_enter_lowpower();
@@ -295,4 +387,30 @@ void hix5hd2_cpu_die(unsigned int cpu)
flush_cache_all();
hix5hd2_set_cpu(cpu, false);
}
+
+void hi3798_cpu_die(unsigned int cpu)
+{
+ int spurious = 0;
+
+ /*
+ * we're ready for shutdown now, so do it
+ */
+ cpu_enter_lowpower();
+ hisi_do_lowpower(cpu, &spurious);
+
+ /*
+ * bring this CPU back into the world of cache
+ * coherency, and then restore interrupts
+ */
+ cpu_leave_lowpower();
+
+ if (spurious)
+ pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
+
+int hi3798_cpu_kill(unsigned int cpu)
+{
+ hi3798_set_cpu(cpu, false);
+ return 1;
+}
#endif
@@ -0,0 +1,8 @@
--- a/arch/arm/mach-hisi/Makefile
+++ b/arch/arm/mach-hisi/Makefile
@@ -7,4 +7,4 @@ CFLAGS_platmcpm.o := -march=armv7-a
obj-y += hisilicon.o
obj-$(CONFIG_MCPM) += platmcpm.o
-obj-$(CONFIG_SMP) += platsmp.o hotplug.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o hotplug.o
@@ -0,0 +1,139 @@
--- a/arch/arm/mach-hisi/platsmp.c
+++ b/arch/arm/mach-hisi/platsmp.c
@@ -20,6 +20,48 @@
static void __iomem *ctrl_base;
+/*
+ * hisi_pen_release controls the release of CPUs from the holding
+ * pen in headsmp.S, which exists because we are not always able to
+ * control the release of individual CPUs from the board firmware.
+ */
+volatile int hisi_pen_release = -1;
+
+/*
+ * Write hisi_write_pen_release in a way that is guaranteed to be visible to
+ * all observers, irrespective of whether they're taking part in coherency
+ * or not. This is necessary for the hotplug code to work reliably.
+ */
+static void hisi_write_pen_release(int val)
+{
+ hisi_pen_release = val;
+ smp_wmb();
+ sync_cache_w(&hisi_pen_release);
+}
+
+/*
+ * hisi_lock exists to avoid running the loops_per_jiffy delay loop
+ * calibrations on the secondary CPU while the requesting CPU is using
+ * the limited-bandwidth bus - which affects the calibration value.
+ */
+static DEFINE_RAW_SPINLOCK(hisi_lock);
+
+static void hisi_pen_secondary_init(unsigned int cpu)
+{
+ /*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ hisi_write_pen_release(-1);
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ raw_spin_lock(&hisi_lock);
+ raw_spin_unlock(&hisi_lock);
+}
+
+
void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
{
cpu = cpu_logical_map(cpu);
@@ -182,6 +224,87 @@ static const struct smp_operations hip01
.smp_boot_secondary = hip01_boot_secondary,
};
+
+static void hi3798_smp_prepare_cpus(unsigned int max_cpus)
+{
+ unsigned int i;
+ unsigned int l2ctlr;
+ unsigned int ncores;
+
+ asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
+ ncores = ((l2ctlr >> 24) & 0x3) + 1;
+
+ pr_info("smp: %u cores detected\n", ncores);
+ if (ncores > max_cpus) {
+ pr_warn("smp: %u cores greater than maximum (%u), clipping\n",
+ ncores, max_cpus);
+ ncores = max_cpus;
+ }
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ /* Put the boot address in this magic register */
+ hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS,
+ __pa_symbol(hisi_secondary_startup));
+}
+
+static int hi3798_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long timeout;
+
+ /*
+ * Set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ raw_spin_lock(&hisi_lock);
+
+ hi3798_set_cpu(cpu, true);
+
+ /*
+ * This is really belt and braces; we hold unintended secondary
+ * CPUs in the holding pen until we're ready for them. However,
+ * since we haven't sent them a soft interrupt, they shouldn't
+ * be there.
+ */
+ hisi_write_pen_release(cpu);
+
+ /*
+ * Send the secondary CPU a soft interrupt, thereby causing
+ * the boot monitor to read the system wide flags register,
+ * and branch to the address found there.
+ */
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ timeout = jiffies + (1 * HZ);
+ while (time_before(jiffies, timeout)) {
+ smp_rmb();
+ if (hisi_pen_release == -1)
+ break;
+
+ udelay(10);
+ }
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ raw_spin_unlock(&hisi_lock);
+
+ return hisi_pen_release != -1 ? -ENOSYS : 0;
+}
+
+static const struct smp_operations hi3798_smp_ops __initconst = {
+ .smp_prepare_cpus = hi3798_smp_prepare_cpus,
+ .smp_secondary_init = hisi_pen_secondary_init,
+ .smp_boot_secondary = hi3798_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = hi3798_cpu_die,
+ .cpu_kill = hi3798_cpu_kill,
+#endif
+};
+
+
CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops);
+CPU_METHOD_OF_DECLARE(hi3798_smp, "hisilicon,hi3798-smp", &hi3798_smp_ops);
@@ -0,0 +1,13 @@
--- a/Documentation/devicetree/bindings/clock/hisi-crg.txt
+++ b/Documentation/devicetree/bindings/clock/hisi-crg.txt
@@ -15,6 +15,10 @@ Required Properties:
- "hisilicon,hi3519-crg"
- "hisilicon,hi3798cv200-crg"
- "hisilicon,hi3798cv200-sysctrl"
+ - "hisilicon,hi3798mv100-crg"
+ - "hisilicon,hi3798mv100-sysctrl"
+ - "hisilicon,hi3798mv200-crg"
+ - "hisilicon,hi3798mv200-sysctrl"
- reg: physical base address of the controller and length of memory mapped
region.
@@ -0,0 +1,572 @@
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -4,6 +4,7 @@
*
* Copyright (c) 2012-2013 Hisilicon Limited.
* Copyright (c) 2012-2013 Linaro Limited.
+ * Copyright (c) 2023 David Yang
*
* Author: Haojian Zhuang <haojian.zhuang@linaro.org>
* Xin Li <li.xin@linaro.org>
@@ -13,6 +14,8 @@
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -23,321 +26,331 @@
static DEFINE_SPINLOCK(hisi_clk_lock);
-struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
- int nr_clks)
+struct hisi_clock_data *hisi_clk_init(struct device_node *np, size_t nr)
{
- struct hisi_clock_data *clk_data;
- struct resource *res;
- struct clk **clk_table;
-
- clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
- if (!clk_data)
- return NULL;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return NULL;
- clk_data->base = devm_ioremap(&pdev->dev,
- res->start, resource_size(res));
- if (!clk_data->base)
- return NULL;
-
- clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
- sizeof(*clk_table),
- GFP_KERNEL);
- if (!clk_table)
- return NULL;
-
- clk_data->clk_data.clks = clk_table;
- clk_data->clk_data.clk_num = nr_clks;
-
- return clk_data;
-}
-EXPORT_SYMBOL_GPL(hisi_clk_alloc);
-
-struct hisi_clock_data *hisi_clk_init(struct device_node *np,
- int nr_clks)
-{
- struct hisi_clock_data *clk_data;
- struct clk **clk_table;
void __iomem *base;
+ struct hisi_clock_data *data;
+ int ret;
+ int i;
base = of_iomap(np, 0);
if (!base) {
pr_err("%s: failed to map clock registers\n", __func__);
- goto err;
+ return NULL;
}
- clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
- if (!clk_data)
- goto err;
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
- clk_data->base = base;
- clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
- if (!clk_table)
+ data->clk_data = kzalloc(sizeof(*data->clk_data) + nr * sizeof(data->clk_data->hws[0]),
+ GFP_KERNEL);
+ if (!data->clk_data)
goto err_data;
- clk_data->clk_data.clks = clk_table;
- clk_data->clk_data.clk_num = nr_clks;
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
- return clk_data;
+ ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, data->clk_data);
+ if (ret)
+ goto err_clk;
+
+ data->base = base;
+ data->clks = NULL;
+ data->clk_data->num = nr;
+ for (i = 0; i < nr; i++)
+ data->clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+ return data;
+
+err_clk:
+ kfree(data->clk_data);
err_data:
- kfree(clk_data);
-err:
+ kfree(data);
return NULL;
}
EXPORT_SYMBOL_GPL(hisi_clk_init);
-int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
- int nums, struct hisi_clock_data *data)
-{
- struct clk *clk;
- int i;
-
- for (i = 0; i < nums; i++) {
- clk = clk_register_fixed_rate(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- clks[i].fixed_rate);
- if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- goto err;
- }
- data->clk_data.clks[clks[i].id] = clk;
- }
+#define hisi_clk_unregister_fn(type) \
+static void hisi_clk_unregister_##type(struct hisi_clock_data *data) \
+{ \
+ for (int i = 0; i < data->clks->type##_clks_num; i++) { \
+ struct clk_hw *clk = data->clk_data->hws[data->clks->type##_clks[i].id]; \
+\
+ if (clk && !IS_ERR(clk)) \
+ clk_hw_unregister_##type(clk); \
+ } \
+}
- return 0;
+hisi_clk_unregister_fn(fixed_rate)
+hisi_clk_unregister_fn(fixed_factor)
-err:
- while (i--)
- clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
+void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data)
+{
+ if (data->clks) {
+ if (data->clks->fixed_rate_clks_num)
+ hisi_clk_unregister_fixed_rate(data);
+ if (data->clks->fixed_factor_clks_num)
+ hisi_clk_unregister_fixed_factor(data);
+ }
- return PTR_ERR(clk);
+ of_clk_del_provider(np);
+ kfree(data->clk_data);
+ kfree(data);
}
-EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);
+EXPORT_SYMBOL_GPL(hisi_clk_free);
-int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
- int nums,
- struct hisi_clock_data *data)
+int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
+ size_t num, struct hisi_clock_data *data)
{
- struct clk *clk;
+ struct clk_hw *clk;
int i;
- for (i = 0; i < nums; i++) {
- clk = clk_register_fixed_factor(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags, clks[i].mult,
- clks[i].div);
+ for (i = 0; i < num; i++) {
+ const struct hisi_fixed_rate_clock *p_clk = &clks[i];
+
+ clk = clk_hw_register_fixed_rate(NULL, p_clk->name, p_clk->parent_name,
+ p_clk->flags, p_clk->fixed_rate);
+
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
+ __func__, p_clk->name);
goto err;
}
- data->clk_data.clks[clks[i].id] = clk;
+
+ data->clk_data->hws[p_clk->id] = clk;
}
return 0;
err:
while (i--)
- clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
-
+ clk_hw_unregister_fixed_rate(data->clk_data->hws[clks[i].id]);
return PTR_ERR(clk);
}
-EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);
+EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);
-int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
- int nums, struct hisi_clock_data *data)
+int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
+ size_t num, struct hisi_clock_data *data)
{
- struct clk *clk;
- void __iomem *base = data->base;
+ struct clk_hw *clk;
int i;
- for (i = 0; i < nums; i++) {
- u32 mask = BIT(clks[i].width) - 1;
+ for (i = 0; i < num; i++) {
+ const struct hisi_fixed_factor_clock *p_clk = &clks[i];
+
+ clk = clk_hw_register_fixed_factor(NULL, p_clk->name, p_clk->parent_name,
+ p_clk->flags, p_clk->mult, p_clk->div);
- clk = clk_register_mux_table(NULL, clks[i].name,
- clks[i].parent_names,
- clks[i].num_parents, clks[i].flags,
- base + clks[i].offset, clks[i].shift,
- mask, clks[i].mux_flags,
- clks[i].table, &hisi_clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
+ __func__, p_clk->name);
goto err;
}
- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
-
- data->clk_data.clks[clks[i].id] = clk;
+ data->clk_data->hws[p_clk->id] = clk;
}
return 0;
err:
while (i--)
- clk_unregister_mux(data->clk_data.clks[clks[i].id]);
-
+ clk_hw_unregister_fixed_rate(data->clk_data->hws[clks[i].id]);
return PTR_ERR(clk);
}
-EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
+EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);
+
+/*
+ * We ARE function creater. Commit message from checkpatch:
+ * Avoid warning on macros that use argument concatenation as
+ * those macros commonly create another function
+ */
+#define hisi_clk_register_fn(fn, type, stmt) \
+int fn(struct device *dev, const struct type *clks, \
+ size_t num, struct hisi_clock_data *data) \
+{ \
+ void __iomem *base = data->base; \
+\
+ for (int i = 0; i < num; i++) { \
+ const struct type *p_clk = &clks[i]; \
+ struct clk_hw *clk = stmt; \
+\
+ if (IS_ERR(clk)) { \
+ pr_err("%s: failed to register clock %s\n", \
+ __func__, p_clk->name); \
+ return PTR_ERR(clk); \
+ } \
+\
+ if (p_clk->alias) \
+ clk_hw_register_clkdev(clk, p_clk->alias, NULL); \
+\
+ data->clk_data->hws[p_clk->id] = clk; \
+ } \
+\
+ return 0; \
+} \
+EXPORT_SYMBOL_GPL(fn);
+
+hisi_clk_register_fn(hisi_clk_register_mux, hisi_mux_clock,
+ __devm_clk_hw_register_mux(dev, NULL, p_clk->name,
+ p_clk->num_parents, p_clk->parent_names, NULL, NULL,
+ p_clk->flags, base + p_clk->offset, p_clk->shift, BIT(p_clk->width) - 1,
+ p_clk->mux_flags, p_clk->table, &hisi_clk_lock))
int hisi_clk_register_phase(struct device *dev,
const struct hisi_phase_clock *clks,
- int nums, struct hisi_clock_data *data)
+ size_t num, struct hisi_clock_data *data)
{
void __iomem *base = data->base;
- struct clk *clk;
- int i;
- for (i = 0; i < nums; i++) {
- clk = clk_register_hisi_phase(dev, &clks[i], base,
- &hisi_clk_lock);
+ for (int i = 0; i < num; i++) {
+ const struct hisi_phase_clock *p_clk = &clks[i];
+ struct clk_hw *clk = devm_clk_hw_register_hisi_phase(dev,
+ p_clk, base, &hisi_clk_lock);
+
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
- clks[i].name);
+ p_clk->name);
return PTR_ERR(clk);
}
- data->clk_data.clks[clks[i].id] = clk;
+ data->clk_data->hws[p_clk->id] = clk;
}
return 0;
}
EXPORT_SYMBOL_GPL(hisi_clk_register_phase);
-int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
- int nums, struct hisi_clock_data *data)
+hisi_clk_register_fn(hisi_clk_register_divider, hisi_divider_clock,
+ devm_clk_hw_register_divider_table(dev, p_clk->name, p_clk->parent_name,
+ p_clk->flags, base + p_clk->offset, p_clk->shift, p_clk->width,
+ p_clk->div_flags, p_clk->table, &hisi_clk_lock))
+hisi_clk_register_fn(hisi_clk_register_gate, hisi_gate_clock,
+ devm_clk_hw_register_gate(dev, p_clk->name, p_clk->parent_name,
+ p_clk->flags, base + p_clk->offset, p_clk->bit_idx,
+ p_clk->gate_flags, &hisi_clk_lock))
+hisi_clk_register_fn(hisi_clk_register_gate_sep, hisi_gate_clock,
+ devm_clk_hw_register_hisi_gate_sep(dev, p_clk->name, p_clk->parent_name,
+ p_clk->flags, base + p_clk->offset, p_clk->bit_idx,
+ p_clk->gate_flags, &hisi_clk_lock))
+hisi_clk_register_fn(hi6220_clk_register_divider, hi6220_divider_clock,
+ devm_clk_hw_register_hi6220_divider(dev, p_clk->name, p_clk->parent_name,
+ p_clk->flags, base + p_clk->offset, p_clk->shift, p_clk->width,
+ p_clk->mask_bit, &hisi_clk_lock))
+
+static size_t hisi_clocks_get_nr(const struct hisi_clocks *clks)
{
- struct clk *clk;
- void __iomem *base = data->base;
- int i;
+ if (clks->nr)
+ return clks->nr;
- for (i = 0; i < nums; i++) {
- clk = clk_register_divider_table(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].shift, clks[i].width,
- clks[i].div_flags,
- clks[i].table,
- &hisi_clk_lock);
- if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- goto err;
- }
+ return clks->fixed_rate_clks_num + clks->fixed_factor_clks_num +
+ clks->mux_clks_num + clks->phase_clks_num +
+ clks->divider_clks_num + clks->gate_clks_num +
+ clks->gate_sep_clks_num + clks->customized_clks_num;
+}
- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
+int hisi_clk_early_init(struct device_node *np, const struct hisi_clocks *clks)
+{
+ struct hisi_clock_data *data;
+ int ret;
- data->clk_data.clks[clks[i].id] = clk;
- }
+ data = hisi_clk_init(np, hisi_clocks_get_nr(clks));
+ if (!data)
+ return -ENOMEM;
+ data->clks = clks;
+
+ ret = hisi_clk_register_fixed_rate(clks->fixed_rate_clks,
+ clks->fixed_rate_clks_num, data);
+ if (ret)
+ goto err;
+ ret = hisi_clk_register_fixed_factor(clks->fixed_factor_clks,
+ clks->fixed_factor_clks_num, data);
+ if (ret)
+ goto err;
+
+ np->data = data;
return 0;
err:
- while (i--)
- clk_unregister_divider(data->clk_data.clks[clks[i].id]);
-
- return PTR_ERR(clk);
+ hisi_clk_free(np, data);
+ return ret;
}
-EXPORT_SYMBOL_GPL(hisi_clk_register_divider);
+EXPORT_SYMBOL_GPL(hisi_clk_early_init);
-int hisi_clk_register_gate(const struct hisi_gate_clock *clks,
- int nums, struct hisi_clock_data *data)
+static int hisi_clk_register(struct device *dev, const struct hisi_clocks *clks,
+ struct hisi_clock_data *data)
{
- struct clk *clk;
- void __iomem *base = data->base;
- int i;
+ int ret;
- for (i = 0; i < nums; i++) {
- clk = clk_register_gate(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].bit_idx,
- clks[i].gate_flags,
- &hisi_clk_lock);
- if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- goto err;
- }
-
- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
-
- data->clk_data.clks[clks[i].id] = clk;
+#define do_hisi_clk_register(type) do { \
+ if (clks->type##_clks_num) { \
+ ret = hisi_clk_register_##type(dev, clks->type##_clks, \
+ clks->type##_clks_num, data); \
+ if (ret) \
+ return ret; \
+ } \
+} while (0)
+
+ do_hisi_clk_register(mux);
+ do_hisi_clk_register(phase);
+ do_hisi_clk_register(divider);
+ do_hisi_clk_register(gate);
+ do_hisi_clk_register(gate_sep);
+
+ if (clks->clk_register_customized && clks->customized_clks_num) {
+ ret = clks->clk_register_customized(dev, clks->customized_clks,
+ clks->customized_clks_num, data);
+ if (ret)
+ return ret;
}
return 0;
-
-err:
- while (i--)
- clk_unregister_gate(data->clk_data.clks[clks[i].id]);
-
- return PTR_ERR(clk);
}
-EXPORT_SYMBOL_GPL(hisi_clk_register_gate);
-void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks,
- int nums, struct hisi_clock_data *data)
+int hisi_clk_probe(struct platform_device *pdev)
{
- struct clk *clk;
- void __iomem *base = data->base;
- int i;
-
- for (i = 0; i < nums; i++) {
- clk = hisi_register_clkgate_sep(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].bit_idx,
- clks[i].gate_flags,
- &hisi_clk_lock);
- if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- continue;
- }
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct hisi_clocks *clks;
+ struct hisi_clock_data *data;
+ int ret;
+
+ clks = of_device_get_match_data(dev);
+ if (!clks)
+ return -ENOENT;
+
+ if (!np->data) {
+ ret = hisi_clk_early_init(np, clks);
+ if (ret)
+ return ret;
+ }
- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
+ data = np->data;
+ np->data = NULL;
- data->clk_data.clks[clks[i].id] = clk;
+ if (clks->prologue) {
+ ret = clks->prologue(dev, data);
+ if (ret)
+ goto err;
}
-}
-EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep);
-void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
- int nums, struct hisi_clock_data *data)
-{
- struct clk *clk;
- void __iomem *base = data->base;
- int i;
+ ret = hisi_clk_register(dev, clks, data);
+ if (ret)
+ goto err;
- for (i = 0; i < nums; i++) {
- clk = hi6220_register_clkdiv(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].shift,
- clks[i].width,
- clks[i].mask_bit,
- &hisi_clk_lock);
- if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- continue;
- }
+ platform_set_drvdata(pdev, data);
+ return 0;
+
+err:
+ hisi_clk_free(np, data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_clk_probe);
- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
+void hisi_clk_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct hisi_clock_data *data = platform_get_drvdata(pdev);
- data->clk_data.clks[clks[i].id] = clk;
- }
+ hisi_clk_free(np, data);
}
+EXPORT_SYMBOL_GPL(hisi_clk_remove);
@@ -0,0 +1,89 @@
--- a/drivers/clk/hisilicon/clkdivider-hi6220.c
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/clk-provider.h>
-#include <linux/slab.h>
+#include <linux/device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/spinlock.h>
@@ -55,13 +55,15 @@ static unsigned long hi6220_clkdiv_recal
CLK_DIVIDER_ROUND_CLOSEST, dclk->width);
}
-static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int hi6220_clkdiv_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
- return divider_round_rate(hw, rate, prate, dclk->table,
- dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+ req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, dclk->table,
+ dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+
+ return 0;
}
static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -93,23 +95,23 @@ static int hi6220_clkdiv_set_rate(struct
static const struct clk_ops hi6220_clkdiv_ops = {
.recalc_rate = hi6220_clkdiv_recalc_rate,
- .round_rate = hi6220_clkdiv_round_rate,
+ .determine_rate = hi6220_clkdiv_determine_rate,
.set_rate = hi6220_clkdiv_set_rate,
};
-struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+struct clk_hw *devm_clk_hw_register_hi6220_divider(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, void __iomem *reg,
u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
{
struct hi6220_clk_divider *div;
- struct clk *clk;
struct clk_init_data init;
struct clk_div_table *table;
u32 max_div, min_div;
int i;
+ int ret;
/* allocate the divider */
- div = kzalloc(sizeof(*div), GFP_KERNEL);
+ div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);
@@ -117,11 +119,9 @@ struct clk *hi6220_register_clkdiv(struc
max_div = div_mask(width) + 1;
min_div = 1;
- table = kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL);
- if (!table) {
- kfree(div);
+ table = devm_kcalloc(dev, max_div + 1, sizeof(*table), GFP_KERNEL);
+ if (!table)
return ERR_PTR(-ENOMEM);
- }
for (i = 0; i < max_div; i++) {
table[i].div = min_div + i;
@@ -144,11 +144,9 @@ struct clk *hi6220_register_clkdiv(struc
div->table = table;
/* register the clock */
- clk = clk_register(dev, &div->hw);
- if (IS_ERR(clk)) {
- kfree(table);
- kfree(div);
- }
+ ret = devm_clk_hw_register(dev, &div->hw);
+ if (ret)
+ return ERR_PTR(ret);
- return clk;
+ return &div->hw;
}
@@ -0,0 +1,98 @@
--- a/drivers/clk/hisilicon/clkgate-separated.c
+++ b/drivers/clk/hisilicon/clkgate-separated.c
@@ -11,15 +11,15 @@
#include <linux/kernel.h>
#include <linux/clk-provider.h>
+#include <linux/device.h>
#include <linux/io.h>
-#include <linux/slab.h>
#include "clk.h"
/* clock separated gate register offset */
-#define CLKGATE_SEPERATED_ENABLE 0x0
-#define CLKGATE_SEPERATED_DISABLE 0x4
-#define CLKGATE_SEPERATED_STATUS 0x8
+#define CLKGATE_SEPARATED_ENABLE 0x0
+#define CLKGATE_SEPARATED_DISABLE 0x4
+#define CLKGATE_SEPARATED_STATUS 0x8
struct clkgate_separated {
struct clk_hw hw;
@@ -40,7 +40,7 @@ static int clkgate_separated_enable(stru
spin_lock_irqsave(sclk->lock, flags);
reg = BIT(sclk->bit_idx);
writel_relaxed(reg, sclk->enable);
- readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS);
+ readl_relaxed(sclk->enable + CLKGATE_SEPARATED_STATUS);
if (sclk->lock)
spin_unlock_irqrestore(sclk->lock, flags);
return 0;
@@ -56,8 +56,8 @@ static void clkgate_separated_disable(st
if (sclk->lock)
spin_lock_irqsave(sclk->lock, flags);
reg = BIT(sclk->bit_idx);
- writel_relaxed(reg, sclk->enable + CLKGATE_SEPERATED_DISABLE);
- readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS);
+ writel_relaxed(reg, sclk->enable + CLKGATE_SEPARATED_DISABLE);
+ readl_relaxed(sclk->enable + CLKGATE_SEPARATED_STATUS);
if (sclk->lock)
spin_unlock_irqrestore(sclk->lock, flags);
}
@@ -68,7 +68,7 @@ static int clkgate_separated_is_enabled(
u32 reg;
sclk = container_of(hw, struct clkgate_separated, hw);
- reg = readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS);
+ reg = readl_relaxed(sclk->enable + CLKGATE_SEPARATED_STATUS);
reg &= BIT(sclk->bit_idx);
return reg ? 1 : 0;
@@ -80,17 +80,18 @@ static const struct clk_ops clkgate_sepa
.is_enabled = clkgate_separated_is_enabled,
};
-struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name,
- const char *parent_name,
- unsigned long flags,
- void __iomem *reg, u8 bit_idx,
- u8 clk_gate_flags, spinlock_t *lock)
+struct clk_hw *
+devm_clk_hw_register_hisi_gate_sep(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 clk_gate_flags, spinlock_t *lock)
{
struct clkgate_separated *sclk;
- struct clk *clk;
struct clk_init_data init;
+ int ret;
- sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
+ sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
if (!sclk)
return ERR_PTR(-ENOMEM);
@@ -100,14 +101,15 @@ struct clk *hisi_register_clkgate_sep(st
init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0);
- sclk->enable = reg + CLKGATE_SEPERATED_ENABLE;
+ sclk->enable = reg + CLKGATE_SEPARATED_ENABLE;
sclk->bit_idx = bit_idx;
sclk->flags = clk_gate_flags;
sclk->hw.init = &init;
sclk->lock = lock;
- clk = clk_register(dev, &sclk->hw);
- if (IS_ERR(clk))
- kfree(sclk);
- return clk;
+ ret = devm_clk_hw_register(dev, &sclk->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &sclk->hw;
}
@@ -0,0 +1,156 @@
--- a/drivers/clk/hisilicon/clk-hi3519.c
+++ b/drivers/clk/hisilicon/clk-hi3519.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include "clk.h"
-#include "reset.h"
+#include "crg.h"
#define HI3519_INNER_CLK_OFFSET 64
#define HI3519_FIXED_24M 65
@@ -73,130 +73,33 @@ static const struct hisi_gate_clock hi35
CLK_SET_RATE_PARENT, 0xe4, 18, 0, },
};
-static struct hisi_clock_data *hi3519_clk_register(struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3519_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks,
- ARRAY_SIZE(hi3519_fixed_rate_clks),
- clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = hisi_clk_register_mux(hi3519_mux_clks,
- ARRAY_SIZE(hi3519_mux_clks),
- clk_data);
- if (ret)
- goto unregister_fixed_rate;
-
- ret = hisi_clk_register_gate(hi3519_gate_clks,
- ARRAY_SIZE(hi3519_gate_clks),
- clk_data);
- if (ret)
- goto unregister_mux;
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_fixed_rate:
- hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks,
- ARRAY_SIZE(hi3519_fixed_rate_clks),
- clk_data);
-
-unregister_mux:
- hisi_clk_unregister_mux(hi3519_mux_clks,
- ARRAY_SIZE(hi3519_mux_clks),
- clk_data);
-unregister_gate:
- hisi_clk_unregister_gate(hi3519_gate_clks,
- ARRAY_SIZE(hi3519_gate_clks),
- clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3519_clk_unregister(struct platform_device *pdev)
-{
- struct hi3519_crg_data *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3519_gate_clks,
- ARRAY_SIZE(hi3519_gate_clks),
- crg->clk_data);
- hisi_clk_unregister_mux(hi3519_mux_clks,
- ARRAY_SIZE(hi3519_mux_clks),
- crg->clk_data);
- hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks,
- ARRAY_SIZE(hi3519_fixed_rate_clks),
- crg->clk_data);
-}
-
-static int hi3519_clk_probe(struct platform_device *pdev)
-{
- struct hi3519_crg_data *crg;
-
- crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
- if (!crg)
- return -ENOMEM;
-
- crg->rstc = hisi_reset_init(pdev);
- if (!crg->rstc)
- return -ENOMEM;
-
- crg->clk_data = hi3519_clk_register(pdev);
- if (IS_ERR(crg->clk_data)) {
- hisi_reset_exit(crg->rstc);
- return PTR_ERR(crg->clk_data);
- }
-
- platform_set_drvdata(pdev, crg);
- return 0;
-}
-
-static void hi3519_clk_remove(struct platform_device *pdev)
-{
- struct hi3519_crg_data *crg = platform_get_drvdata(pdev);
-
- hisi_reset_exit(crg->rstc);
- hi3519_clk_unregister(pdev);
-}
-
+static const struct hisi_clocks hi3519_crg_clks = {
+ .nr = HI3519_NR_CLKS,
+ .fixed_rate_clks = hi3519_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3519_fixed_rate_clks),
+ .mux_clks = hi3519_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3519_mux_clks),
+ .gate_clks = hi3519_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3519_gate_clks),
+};
static const struct of_device_id hi3519_clk_match_table[] = {
- { .compatible = "hisilicon,hi3519-crg" },
+ { .compatible = "hisilicon,hi3519-crg",
+ .data = &hi3519_crg_clks },
{ }
};
MODULE_DEVICE_TABLE(of, hi3519_clk_match_table);
static struct platform_driver hi3519_clk_driver = {
- .probe = hi3519_clk_probe,
- .remove = hi3519_clk_remove,
+ .probe = hisi_clk_probe,
+ .remove = hisi_clk_remove,
.driver = {
.name = "hi3519-clk",
.of_match_table = hi3519_clk_match_table,
},
};
-static int __init hi3519_clk_init(void)
-{
- return platform_driver_register(&hi3519_clk_driver);
-}
-core_initcall(hi3519_clk_init);
-
-static void __exit hi3519_clk_exit(void)
-{
- platform_driver_unregister(&hi3519_clk_driver);
-}
-module_exit(hi3519_clk_exit);
+module_platform_driver(hi3519_clk_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver");
@@ -0,0 +1,329 @@
--- a/drivers/clk/hisilicon/clk-hi3559a.c
+++ b/drivers/clk/hisilicon/clk-hi3559a.c
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>
#include <dt-bindings/clock/hi3559av100-clock.h>
@@ -451,20 +450,23 @@ static const struct clk_ops hisi_clk_pll
.recalc_rate = clk_pll_recalc_rate,
};
-static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks,
- int nums, struct hisi_clock_data *data, struct device *dev)
+static int
+hisi_clk_register_pll(struct device *dev, const void *clocks,
+ size_t num, struct hisi_clock_data *data)
{
+ const struct hi3559av100_pll_clock *clks = clocks;
void __iomem *base = data->base;
- struct hi3559av100_clk_pll *p_clk = NULL;
- struct clk *clk = NULL;
+ struct hi3559av100_clk_pll *p_clk;
struct clk_init_data init;
int i;
- p_clk = devm_kcalloc(dev, nums, sizeof(*p_clk), GFP_KERNEL);
- if (!p_clk)
- return;
+ int ret;
+
+ for (i = 0; i < num; i++) {
+ p_clk = devm_kzalloc(dev, sizeof(*p_clk), GFP_KERNEL);
+ if (!p_clk)
+ return -ENOMEM;
- for (i = 0; i < nums; i++) {
init.name = clks[i].name;
init.flags = 0;
init.parent_names =
@@ -487,82 +489,30 @@ static void hisi_clk_register_pll(struct
p_clk->refdiv_width = clks[i].refdiv_width;
p_clk->hw.init = &init;
- clk = clk_register(NULL, &p_clk->hw);
- if (IS_ERR(clk)) {
+ ret = devm_clk_hw_register(dev, &p_clk->hw);
+ if (ret) {
dev_err(dev, "%s: failed to register clock %s\n",
- __func__, clks[i].name);
- continue;
+ __func__, clks[i].name);
+ return ret;
}
- data->clk_data.clks[clks[i].id] = clk;
- p_clk++;
+ data->clk_data->hws[clks[i].id] = &p_clk->hw;
}
-}
-
-static struct hisi_clock_data *hi3559av100_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg,
- ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- hisi_clk_register_pll(hi3559av100_pll_clks,
- ARRAY_SIZE(hi3559av100_pll_clks), clk_data, &pdev->dev);
-
- ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg,
- ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
- if (ret)
- goto unregister_fixed_rate;
-
- ret = hisi_clk_register_gate(hi3559av100_gate_clks,
- ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
- if (ret)
- goto unregister_mux;
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_gate:
- hisi_clk_unregister_gate(hi3559av100_gate_clks,
- ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
-unregister_mux:
- hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
- ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
-unregister_fixed_rate:
- hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
- ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3559av100_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3559av100_gate_clks,
- ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data);
- hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
- ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data);
- hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
- ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data);
+ return 0;
}
-static const struct hisi_crg_funcs hi3559av100_crg_funcs = {
- .register_clks = hi3559av100_clk_register,
- .unregister_clks = hi3559av100_clk_unregister,
+static const struct hisi_clocks hi3559av100_clks = {
+ .nr = HI3559AV100_CRG_NR_CLKS,
+ .fixed_rate_clks = hi3559av100_fixed_rate_clks_crg,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg),
+ .mux_clks = hi3559av100_mux_clks_crg,
+ .mux_clks_num = ARRAY_SIZE(hi3559av100_mux_clks_crg),
+ .gate_clks = hi3559av100_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3559av100_gate_clks),
+ .customized_clks = hi3559av100_pll_clks,
+ .customized_clks_num = ARRAY_SIZE(hi3559av100_pll_clks),
+ .clk_register_customized = hisi_clk_register_pll,
};
static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] = {
@@ -670,12 +620,12 @@ static struct hisi_gate_clock hi3559av10
},
};
-static int hi3559av100_shub_default_clk_set(void)
+static int hi3559av100_shub_default_clk_set(struct device *dev, struct hisi_clock_data *data)
{
void __iomem *crg_base;
unsigned int val;
- crg_base = ioremap(CRG_BASE_ADDR, SZ_4K);
+ crg_base = devm_ioremap(dev, CRG_BASE_ADDR, SZ_4K);
/* SSP: 192M/2 */
val = readl_relaxed(crg_base + 0x20);
@@ -687,154 +637,47 @@ static int hi3559av100_shub_default_clk_
val |= (0x1 << 28);
writel_relaxed(val, crg_base + 0x1C);
- iounmap(crg_base);
+ devm_iounmap(dev, crg_base);
crg_base = NULL;
return 0;
}
-static struct hisi_clock_data *hi3559av100_shub_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data = NULL;
- int ret;
-
- hi3559av100_shub_default_clk_set();
-
- clk_data = hisi_clk_alloc(pdev, HI3559AV100_SHUB_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks,
- ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = hisi_clk_register_mux(hi3559av100_shub_mux_clks,
- ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
- if (ret)
- goto unregister_fixed_rate;
-
- ret = hisi_clk_register_divider(hi3559av100_shub_div_clks,
- ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
- if (ret)
- goto unregister_mux;
-
- ret = hisi_clk_register_gate(hi3559av100_shub_gate_clks,
- ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
- if (ret)
- goto unregister_factor;
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_gate:
- hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
- ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
-unregister_factor:
- hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
- ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
-unregister_mux:
- hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
- ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
-unregister_fixed_rate:
- hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
- ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3559av100_shub_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
- ARRAY_SIZE(hi3559av100_shub_gate_clks), crg->clk_data);
- hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
- ARRAY_SIZE(hi3559av100_shub_div_clks), crg->clk_data);
- hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
- ARRAY_SIZE(hi3559av100_shub_mux_clks), crg->clk_data);
- hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
- ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), crg->clk_data);
-}
-
-static const struct hisi_crg_funcs hi3559av100_shub_crg_funcs = {
- .register_clks = hi3559av100_shub_clk_register,
- .unregister_clks = hi3559av100_shub_clk_unregister,
+static const struct hisi_clocks hi3559av100_shub_clks = {
+ .nr = HI3559AV100_SHUB_NR_CLKS,
+ .prologue = hi3559av100_shub_default_clk_set,
+ .fixed_rate_clks = hi3559av100_shub_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks),
+ .mux_clks = hi3559av100_shub_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3559av100_shub_mux_clks),
+ .divider_clks = hi3559av100_shub_div_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3559av100_shub_div_clks),
+ .gate_clks = hi3559av100_shub_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3559av100_shub_gate_clks),
};
static const struct of_device_id hi3559av100_crg_match_table[] = {
{
.compatible = "hisilicon,hi3559av100-clock",
- .data = &hi3559av100_crg_funcs
+ .data = &hi3559av100_clks
},
{
.compatible = "hisilicon,hi3559av100-shub-clock",
- .data = &hi3559av100_shub_crg_funcs
+ .data = &hi3559av100_shub_clks
},
{ }
};
MODULE_DEVICE_TABLE(of, hi3559av100_crg_match_table);
-static int hi3559av100_crg_probe(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg;
-
- crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
- if (!crg)
- return -ENOMEM;
-
- crg->funcs = of_device_get_match_data(&pdev->dev);
- if (!crg->funcs)
- return -ENOENT;
-
- crg->rstc = hisi_reset_init(pdev);
- if (!crg->rstc)
- return -ENOMEM;
-
- crg->clk_data = crg->funcs->register_clks(pdev);
- if (IS_ERR(crg->clk_data)) {
- hisi_reset_exit(crg->rstc);
- return PTR_ERR(crg->clk_data);
- }
-
- platform_set_drvdata(pdev, crg);
- return 0;
-}
-
-static void hi3559av100_crg_remove(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- hisi_reset_exit(crg->rstc);
- crg->funcs->unregister_clks(pdev);
-}
-
static struct platform_driver hi3559av100_crg_driver = {
- .probe = hi3559av100_crg_probe,
- .remove = hi3559av100_crg_remove,
+ .probe = hisi_crg_probe,
+ .remove = hisi_crg_remove,
.driver = {
.name = "hi3559av100-clock",
.of_match_table = hi3559av100_crg_match_table,
},
};
-static int __init hi3559av100_crg_init(void)
-{
- return platform_driver_register(&hi3559av100_crg_driver);
-}
-core_initcall(hi3559av100_crg_init);
-
-static void __exit hi3559av100_crg_exit(void)
-{
- platform_driver_unregister(&hi3559av100_crg_driver);
-}
-module_exit(hi3559av100_crg_exit);
-
+module_platform_driver(hi3559av100_crg_driver);
MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver");
@@ -0,0 +1,303 @@
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -11,58 +11,58 @@
#include <linux/kernel.h>
#include <linux/clk-provider.h>
+#include <linux/device.h>
#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <dt-bindings/clock/hi3620-clock.h>
#include "clk.h"
/* clock parent list */
-static const char *const timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
-static const char *const timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
-static const char *const timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
-static const char *const timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
-static const char *const timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
-static const char *const timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
-static const char *const timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
-static const char *const timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
-static const char *const timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
-static const char *const timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
-static const char *const uart0_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *const uart1_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *const uart2_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *const uart3_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *const uart4_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *const spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
-static const char *const spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
-static const char *const spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *const timer0_mux_p[] = { "osc32k", "timerclk01", };
+static const char *const timer1_mux_p[] = { "osc32k", "timerclk01", };
+static const char *const timer2_mux_p[] = { "osc32k", "timerclk23", };
+static const char *const timer3_mux_p[] = { "osc32k", "timerclk23", };
+static const char *const timer4_mux_p[] = { "osc32k", "timerclk45", };
+static const char *const timer5_mux_p[] = { "osc32k", "timerclk45", };
+static const char *const timer6_mux_p[] = { "osc32k", "timerclk67", };
+static const char *const timer7_mux_p[] = { "osc32k", "timerclk67", };
+static const char *const timer8_mux_p[] = { "osc32k", "timerclk89", };
+static const char *const timer9_mux_p[] = { "osc32k", "timerclk89", };
+static const char *const uart0_mux_p[] = { "osc26m", "pclk", };
+static const char *const uart1_mux_p[] = { "osc26m", "pclk", };
+static const char *const uart2_mux_p[] = { "osc26m", "pclk", };
+static const char *const uart3_mux_p[] = { "osc26m", "pclk", };
+static const char *const uart4_mux_p[] = { "osc26m", "pclk", };
+static const char *const spi0_mux_p[] = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi1_mux_p[] = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi2_mux_p[] = { "osc26m", "rclk_cfgaxi", };
/* share axi parent */
-static const char *const saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
-static const char *const pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
-static const char *const pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
-static const char *const sd_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
-static const char *const g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const venc_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
+static const char *const saxi_mux_p[] = { "armpll3", "armpll2", };
+static const char *const pwm0_mux_p[] = { "osc32k", "osc26m", };
+static const char *const pwm1_mux_p[] = { "osc32k", "osc26m", };
+static const char *const sd_mux_p[] = { "armpll2", "armpll3", };
+static const char *const mmc1_mux_p[] = { "armpll2", "armpll3", };
+static const char *const mmc1_mux2_p[] = { "osc26m", "mmc1_div", };
+static const char *const g2d_mux_p[] = { "armpll2", "armpll3", };
+static const char *const venc_mux_p[] = { "armpll2", "armpll3", };
+static const char *const vdec_mux_p[] = { "armpll2", "armpll3", };
+static const char *const vpp_mux_p[] = { "armpll2", "armpll3", };
+static const char *const edc0_mux_p[] = { "armpll2", "armpll3", };
+static const char *const ldi0_mux_p[] = { "armpll2", "armpll4",
"armpll3", "armpll5", };
-static const char *const edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
+static const char *const edc1_mux_p[] = { "armpll2", "armpll3", };
+static const char *const ldi1_mux_p[] = { "armpll2", "armpll4",
"armpll3", "armpll5", };
-static const char *const rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
-static const char *const mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *const mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const rclk_hsic_p[] = { "armpll3", "armpll2", };
+static const char *const mmc2_mux_p[] = { "armpll2", "armpll3", };
+static const char *const mmc3_mux_p[] = { "armpll2", "armpll3", };
/* fixed rate clocks */
-static struct hisi_fixed_rate_clock hi3620_fixed_rate_clks[] __initdata = {
+static struct hisi_fixed_rate_clock hi3620_fixed_rate_clks[] = {
{ HI3620_OSC32K, "osc32k", NULL, 0, 32768, },
{ HI3620_OSC26M, "osc26m", NULL, 0, 26000000, },
{ HI3620_PCLK, "pclk", NULL, 0, 26000000, },
@@ -75,13 +75,13 @@ static struct hisi_fixed_rate_clock hi36
};
/* fixed factor clocks */
-static struct hisi_fixed_factor_clock hi3620_fixed_factor_clks[] __initdata = {
+static struct hisi_fixed_factor_clock hi3620_fixed_factor_clks[] = {
{ HI3620_RCLK_TCXO, "rclk_tcxo", "osc26m", 1, 4, 0, },
{ HI3620_RCLK_CFGAXI, "rclk_cfgaxi", "armpll2", 1, 30, 0, },
{ HI3620_RCLK_PICO, "rclk_pico", "hsic_div", 1, 40, 0, },
};
-static struct hisi_mux_clock hi3620_mux_clks[] __initdata = {
+static struct hisi_mux_clock hi3620_mux_clks[] = {
{ HI3620_TIMER0_MUX, "timer0_mux", timer0_mux_p, ARRAY_SIZE(timer0_mux_p), CLK_SET_RATE_PARENT, 0, 15, 2, 0, },
{ HI3620_TIMER1_MUX, "timer1_mux", timer1_mux_p, ARRAY_SIZE(timer1_mux_p), CLK_SET_RATE_PARENT, 0, 17, 2, 0, },
{ HI3620_TIMER2_MUX, "timer2_mux", timer2_mux_p, ARRAY_SIZE(timer2_mux_p), CLK_SET_RATE_PARENT, 0, 19, 2, 0, },
@@ -119,7 +119,7 @@ static struct hisi_mux_clock hi3620_mux_
{ HI3620_MMC3_MUX, "mmc3_mux", mmc3_mux_p, ARRAY_SIZE(mmc3_mux_p), CLK_SET_RATE_PARENT, 0x140, 9, 1, CLK_MUX_HIWORD_MASK, },
};
-static struct hisi_divider_clock hi3620_div_clks[] __initdata = {
+static struct hisi_divider_clock hi3620_div_clks[] = {
{ HI3620_SHAREAXI_DIV, "saxi_div", "saxi_mux", 0, 0x100, 0, 5, CLK_DIVIDER_HIWORD_MASK, NULL, },
{ HI3620_CFGAXI_DIV, "cfgaxi_div", "saxi_div", 0, 0x100, 5, 2, CLK_DIVIDER_HIWORD_MASK, NULL, },
{ HI3620_SD_DIV, "sd_div", "sd_mux", 0, 0x108, 0, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
@@ -129,7 +129,7 @@ static struct hisi_divider_clock hi3620_
{ HI3620_MMC3_DIV, "mmc3_div", "mmc3_mux", 0, 0x140, 5, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
};
-static struct hisi_gate_clock hi3620_separated_gate_clks[] __initdata = {
+static struct hisi_gate_clock hi3620_separated_gate_clks[] = {
{ HI3620_TIMERCLK01, "timerclk01", "timer_rclk01", CLK_SET_RATE_PARENT, 0x20, 0, 0, },
{ HI3620_TIMER_RCLK01, "timer_rclk01", "rclk_tcxo", CLK_SET_RATE_PARENT, 0x20, 1, 0, },
{ HI3620_TIMERCLK23, "timerclk23", "timer_rclk23", CLK_SET_RATE_PARENT, 0x20, 2, 0, },
@@ -191,29 +191,19 @@ static struct hisi_gate_clock hi3620_sep
{ HI3620_MCU_CLK, "mcu_clk", "acp_clk", CLK_SET_RATE_PARENT, 0x50, 24, 0, },
};
-static void __init hi3620_clk_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- clk_data = hisi_clk_init(np, HI3620_NR_CLKS);
- if (!clk_data)
- return;
-
- hisi_clk_register_fixed_rate(hi3620_fixed_rate_clks,
- ARRAY_SIZE(hi3620_fixed_rate_clks),
- clk_data);
- hisi_clk_register_fixed_factor(hi3620_fixed_factor_clks,
- ARRAY_SIZE(hi3620_fixed_factor_clks),
- clk_data);
- hisi_clk_register_mux(hi3620_mux_clks, ARRAY_SIZE(hi3620_mux_clks),
- clk_data);
- hisi_clk_register_divider(hi3620_div_clks, ARRAY_SIZE(hi3620_div_clks),
- clk_data);
- hisi_clk_register_gate_sep(hi3620_separated_gate_clks,
- ARRAY_SIZE(hi3620_separated_gate_clks),
- clk_data);
-}
-CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+static const struct hisi_clocks hi3620_clks = {
+ .nr = HI3620_NR_CLKS,
+ .fixed_rate_clks = hi3620_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3620_fixed_rate_clks),
+ .fixed_factor_clks = hi3620_fixed_factor_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hi3620_fixed_factor_clks),
+ .mux_clks = hi3620_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3620_mux_clks),
+ .divider_clks = hi3620_div_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3620_div_clks),
+ .gate_sep_clks = hi3620_separated_gate_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3620_separated_gate_clks),
+};
struct hisi_mmc_clock {
unsigned int id;
@@ -251,7 +241,7 @@ struct clk_mmc {
#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
-static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+static struct hisi_mmc_clock hi3620_mmc_clks[] = {
{ HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
{ HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
{ HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
@@ -407,14 +397,15 @@ static const struct clk_ops clk_mmc_ops
.recalc_rate = mmc_clk_recalc_rate,
};
-static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
- void __iomem *base, struct device_node *np)
+static struct clk_hw *
+clk_register_hisi_mmc(struct device *dev, const struct hisi_mmc_clock *mmc_clk,
+ void __iomem *base)
{
struct clk_mmc *mclk;
- struct clk *clk;
struct clk_init_data init;
+ int ret;
- mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+ mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL);
if (!mclk)
return ERR_PTR(-ENOMEM);
@@ -438,47 +429,61 @@ static struct clk *hisi_register_clk_mmc
mclk->sam_off = mmc_clk->sam_off;
mclk->sam_bits = mmc_clk->sam_bits;
- clk = clk_register(NULL, &mclk->hw);
- if (WARN_ON(IS_ERR(clk)))
- kfree(mclk);
- return clk;
-}
-
-static void __init hi3620_mmc_clk_init(struct device_node *node)
-{
- void __iomem *base;
- int i, num = ARRAY_SIZE(hi3620_mmc_clks);
- struct clk_onecell_data *clk_data;
-
- if (!node) {
- pr_err("failed to find pctrl node in DTS\n");
- return;
+ ret = devm_clk_hw_register(dev, &mclk->hw);
+ if (ret) {
+ dev_err(dev, "%s: failed to register clock %s\n",
+ __func__, init.name);
+ return ERR_PTR(ret);
}
- base = of_iomap(node, 0);
- if (!base) {
- pr_err("failed to map pctrl\n");
- return;
- }
+ return &mclk->hw;
+}
- clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
- if (WARN_ON(!clk_data))
- return;
-
- clk_data->clks = kcalloc(num, sizeof(*clk_data->clks), GFP_KERNEL);
- if (!clk_data->clks) {
- kfree(clk_data);
- return;
- }
+static int hisi_register_clk_mmc(struct device *dev, const void *clocks,
+ size_t num, struct hisi_clock_data *data)
+{
+ const struct hisi_mmc_clock *clks = clocks;
+ int i;
for (i = 0; i < num; i++) {
- struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
- clk_data->clks[mmc_clk->id] =
- hisi_register_clk_mmc(mmc_clk, base, node);
+ struct clk_hw *clk = clk_register_hisi_mmc(dev, &clks[i], data->base);
+
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ return PTR_ERR(clk);
+ }
+ data->clk_data->hws[clks[i].id] = clk;
}
- clk_data->clk_num = num;
- of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ return 0;
}
-CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
+static const struct hisi_clocks hi3620_clks_mmc = {
+ .customized_clks = hi3620_mmc_clks,
+ .customized_clks_num = ARRAY_SIZE(hi3620_mmc_clks),
+ .clk_register_customized = hisi_register_clk_mmc,
+};
+
+static const struct of_device_id hi3620_clk_match_table[] = {
+ { .compatible = "hisilicon,hi3620-clock",
+ .data = &hi3620_clks },
+ { .compatible = "hisilicon,hi3620-mmc-clock",
+ .data = &hi3620_clks_mmc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hi3620_clk_match_table);
+
+static struct platform_driver hi3620_clk_driver = {
+ .probe = hisi_clk_probe,
+ .remove = hisi_clk_remove,
+ .driver = {
+ .name = "hi3620-clock",
+ .of_match_table = hi3620_clk_match_table,
+ },
+};
+
+module_platform_driver(hi3620_clk_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HiSilicon Hi3620 Clock Driver");
@@ -0,0 +1,240 @@
--- a/drivers/clk/hisilicon/clk-hi3660.c
+++ b/drivers/clk/hisilicon/clk-hi3660.c
@@ -5,9 +5,13 @@
*/
#include <dt-bindings/clock/hi3660-clock.h>
+
#include <linux/clk-provider.h>
-#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
+
#include "clk.h"
static const struct hisi_fixed_rate_clock hi3660_fixed_rate_clks[] = {
@@ -469,169 +473,79 @@ static const struct hisi_gate_clock hi36
CLK_SET_RATE_PARENT, 0x90, 0, 0, },
};
-static struct hisi_clock_data *clk_crgctrl_data;
-
-static void hi3660_clk_iomcu_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_iomcu_gate_sep_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi3660_iomcu_gate_sep_clks,
- ARRAY_SIZE(hi3660_iomcu_gate_sep_clks),
- clk_data);
-}
-
-static void hi3660_clk_pmuctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_pmu_gate_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate(hi3660_pmu_gate_clks,
- ARRAY_SIZE(hi3660_pmu_gate_clks), clk_data);
-}
-
-static void hi3660_clk_pctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_pctrl_gate_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
- hisi_clk_register_gate(hi3660_pctrl_gate_clks,
- ARRAY_SIZE(hi3660_pctrl_gate_clks), clk_data);
-}
-
-static void hi3660_clk_sctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_sctrl_gate_clks) +
- ARRAY_SIZE(hi3660_sctrl_gate_sep_clks) +
- ARRAY_SIZE(hi3660_sctrl_mux_clks) +
- ARRAY_SIZE(hi3660_sctrl_divider_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
- hisi_clk_register_gate(hi3660_sctrl_gate_clks,
- ARRAY_SIZE(hi3660_sctrl_gate_clks), clk_data);
- hisi_clk_register_gate_sep(hi3660_sctrl_gate_sep_clks,
- ARRAY_SIZE(hi3660_sctrl_gate_sep_clks),
- clk_data);
- hisi_clk_register_mux(hi3660_sctrl_mux_clks,
- ARRAY_SIZE(hi3660_sctrl_mux_clks), clk_data);
- hisi_clk_register_divider(hi3660_sctrl_divider_clks,
- ARRAY_SIZE(hi3660_sctrl_divider_clks),
- clk_data);
-}
+static const struct hisi_clocks hi3660_clk_iomcu_clks = {
+ .gate_sep_clks = hi3660_iomcu_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3660_iomcu_gate_sep_clks),
+};
+
+static const struct hisi_clocks hi3660_clk_pmuctrl_clks = {
+ .gate_clks = hi3660_pmu_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_pmu_gate_clks),
+};
+
+static const struct hisi_clocks hi3660_clk_pctrl_clks = {
+ .gate_clks = hi3660_pctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_pctrl_gate_clks),
+};
+
+static const struct hisi_clocks hi3660_clk_sctrl_clks = {
+ .mux_clks = hi3660_sctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3660_sctrl_mux_clks),
+ .divider_clks = hi3660_sctrl_divider_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3660_sctrl_divider_clks),
+ .gate_clks = hi3660_sctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_sctrl_gate_clks),
+ .gate_sep_clks = hi3660_sctrl_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3660_sctrl_gate_sep_clks),
+};
+
+static const struct hisi_clocks hi3660_clk_crgctrl_clks = {
+ .fixed_rate_clks = hi3660_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3660_fixed_rate_clks),
+ .fixed_factor_clks = hi3660_crg_fixed_factor_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hi3660_crg_fixed_factor_clks),
+ .mux_clks = hi3660_crgctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3660_crgctrl_mux_clks),
+ .divider_clks = hi3660_crgctrl_divider_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3660_crgctrl_divider_clks),
+ .gate_clks = hi3660_crgctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_crgctrl_gate_clks),
+ .gate_sep_clks = hi3660_crgctrl_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks),
+};
static void hi3660_clk_crgctrl_early_init(struct device_node *np)
{
- int nr = ARRAY_SIZE(hi3660_fixed_rate_clks) +
- ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks) +
- ARRAY_SIZE(hi3660_crgctrl_gate_clks) +
- ARRAY_SIZE(hi3660_crgctrl_mux_clks) +
- ARRAY_SIZE(hi3660_crg_fixed_factor_clks) +
- ARRAY_SIZE(hi3660_crgctrl_divider_clks);
- int i;
-
- clk_crgctrl_data = hisi_clk_init(np, nr);
- if (!clk_crgctrl_data)
- return;
-
- for (i = 0; i < nr; i++)
- clk_crgctrl_data->clk_data.clks[i] = ERR_PTR(-EPROBE_DEFER);
-
- hisi_clk_register_fixed_rate(hi3660_fixed_rate_clks,
- ARRAY_SIZE(hi3660_fixed_rate_clks),
- clk_crgctrl_data);
+ hisi_clk_early_init(np, &hi3660_clk_crgctrl_clks);
}
CLK_OF_DECLARE_DRIVER(hi3660_clk_crgctrl, "hisilicon,hi3660-crgctrl",
hi3660_clk_crgctrl_early_init);
-static void hi3660_clk_crgctrl_init(struct device_node *np)
-{
- struct clk **clks;
- int i;
-
- if (!clk_crgctrl_data)
- hi3660_clk_crgctrl_early_init(np);
-
- /* clk_crgctrl_data initialization failed */
- if (!clk_crgctrl_data)
- return;
-
- hisi_clk_register_gate_sep(hi3660_crgctrl_gate_sep_clks,
- ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks),
- clk_crgctrl_data);
- hisi_clk_register_gate(hi3660_crgctrl_gate_clks,
- ARRAY_SIZE(hi3660_crgctrl_gate_clks),
- clk_crgctrl_data);
- hisi_clk_register_mux(hi3660_crgctrl_mux_clks,
- ARRAY_SIZE(hi3660_crgctrl_mux_clks),
- clk_crgctrl_data);
- hisi_clk_register_fixed_factor(hi3660_crg_fixed_factor_clks,
- ARRAY_SIZE(hi3660_crg_fixed_factor_clks),
- clk_crgctrl_data);
- hisi_clk_register_divider(hi3660_crgctrl_divider_clks,
- ARRAY_SIZE(hi3660_crgctrl_divider_clks),
- clk_crgctrl_data);
-
- clks = clk_crgctrl_data->clk_data.clks;
- for (i = 0; i < clk_crgctrl_data->clk_data.clk_num; i++) {
- if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER)
- pr_err("Failed to register crgctrl clock[%d] err=%ld\n",
- i, PTR_ERR(clks[i]));
- }
-}
-
static const struct of_device_id hi3660_clk_match_table[] = {
{ .compatible = "hisilicon,hi3660-crgctrl",
- .data = hi3660_clk_crgctrl_init },
+ .data = &hi3660_clk_crgctrl_clks },
{ .compatible = "hisilicon,hi3660-pctrl",
- .data = hi3660_clk_pctrl_init },
+ .data = &hi3660_clk_pctrl_clks },
{ .compatible = "hisilicon,hi3660-pmuctrl",
- .data = hi3660_clk_pmuctrl_init },
+ .data = &hi3660_clk_pmuctrl_clks },
{ .compatible = "hisilicon,hi3660-sctrl",
- .data = hi3660_clk_sctrl_init },
+ .data = &hi3660_clk_sctrl_clks },
{ .compatible = "hisilicon,hi3660-iomcu",
- .data = hi3660_clk_iomcu_init },
+ .data = &hi3660_clk_iomcu_clks },
{ }
};
-
-static int hi3660_clk_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *np = pdev->dev.of_node;
- void (*init_func)(struct device_node *np);
-
- init_func = of_device_get_match_data(dev);
- if (!init_func)
- return -ENODEV;
-
- init_func(np);
-
- return 0;
-}
+MODULE_DEVICE_TABLE(of, hi3660_clk_match_table);
static struct platform_driver hi3660_clk_driver = {
- .probe = hi3660_clk_probe,
+ .probe = hisi_clk_probe,
+ .remove = hisi_clk_remove,
.driver = {
.name = "hi3660-clk",
.of_match_table = hi3660_clk_match_table,
},
};
-static int __init hi3660_clk_init(void)
-{
- return platform_driver_register(&hi3660_clk_driver);
-}
-core_initcall(hi3660_clk_init);
+module_platform_driver(hi3660_clk_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3660 Clock Driver");
@@ -0,0 +1,283 @@
--- a/drivers/clk/hisilicon/clk-hi3670.c
+++ b/drivers/clk/hisilicon/clk-hi3670.c
@@ -9,8 +9,11 @@
#include <dt-bindings/clock/hi3670-clock.h>
#include <linux/clk-provider.h>
-#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
+
#include "clk.h"
static const struct hisi_fixed_rate_clock hi3670_fixed_rate_clks[] = {
@@ -822,195 +825,94 @@ static const struct hisi_gate_clock hi36
CLK_SET_RATE_PARENT, 0x00, 2, 0, },
};
-static void hi3670_clk_crgctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- int nr = ARRAY_SIZE(hi3670_fixed_rate_clks) +
- ARRAY_SIZE(hi3670_crgctrl_gate_sep_clks) +
- ARRAY_SIZE(hi3670_crgctrl_gate_clks) +
- ARRAY_SIZE(hi3670_crgctrl_mux_clks) +
- ARRAY_SIZE(hi3670_crg_fixed_factor_clks) +
- ARRAY_SIZE(hi3670_crgctrl_divider_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_fixed_rate(hi3670_fixed_rate_clks,
- ARRAY_SIZE(hi3670_fixed_rate_clks),
- clk_data);
- hisi_clk_register_gate_sep(hi3670_crgctrl_gate_sep_clks,
- ARRAY_SIZE(hi3670_crgctrl_gate_sep_clks),
- clk_data);
- hisi_clk_register_gate(hi3670_crgctrl_gate_clks,
- ARRAY_SIZE(hi3670_crgctrl_gate_clks),
- clk_data);
- hisi_clk_register_mux(hi3670_crgctrl_mux_clks,
- ARRAY_SIZE(hi3670_crgctrl_mux_clks),
- clk_data);
- hisi_clk_register_fixed_factor(hi3670_crg_fixed_factor_clks,
- ARRAY_SIZE(hi3670_crg_fixed_factor_clks),
- clk_data);
- hisi_clk_register_divider(hi3670_crgctrl_divider_clks,
- ARRAY_SIZE(hi3670_crgctrl_divider_clks),
- clk_data);
-}
-
-static void hi3670_clk_pctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3670_pctrl_gate_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
- hisi_clk_register_gate(hi3670_pctrl_gate_clks,
- ARRAY_SIZE(hi3670_pctrl_gate_clks), clk_data);
-}
-
-static void hi3670_clk_pmuctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3670_pmu_gate_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate(hi3670_pmu_gate_clks,
- ARRAY_SIZE(hi3670_pmu_gate_clks), clk_data);
-}
-
-static void hi3670_clk_sctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3670_sctrl_gate_sep_clks) +
- ARRAY_SIZE(hi3670_sctrl_gate_clks) +
- ARRAY_SIZE(hi3670_sctrl_mux_clks) +
- ARRAY_SIZE(hi3670_sctrl_divider_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi3670_sctrl_gate_sep_clks,
- ARRAY_SIZE(hi3670_sctrl_gate_sep_clks),
- clk_data);
- hisi_clk_register_gate(hi3670_sctrl_gate_clks,
- ARRAY_SIZE(hi3670_sctrl_gate_clks),
- clk_data);
- hisi_clk_register_mux(hi3670_sctrl_mux_clks,
- ARRAY_SIZE(hi3670_sctrl_mux_clks),
- clk_data);
- hisi_clk_register_divider(hi3670_sctrl_divider_clks,
- ARRAY_SIZE(hi3670_sctrl_divider_clks),
- clk_data);
-}
-
-static void hi3670_clk_iomcu_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3670_iomcu_gate_sep_clks) +
- ARRAY_SIZE(hi3670_iomcu_fixed_factor_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate(hi3670_iomcu_gate_sep_clks,
- ARRAY_SIZE(hi3670_iomcu_gate_sep_clks), clk_data);
-
- hisi_clk_register_fixed_factor(hi3670_iomcu_fixed_factor_clks,
- ARRAY_SIZE(hi3670_iomcu_fixed_factor_clks),
- clk_data);
-}
-
-static void hi3670_clk_media1_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- int nr = ARRAY_SIZE(hi3670_media1_gate_sep_clks) +
- ARRAY_SIZE(hi3670_media1_gate_clks) +
- ARRAY_SIZE(hi3670_media1_mux_clks) +
- ARRAY_SIZE(hi3670_media1_divider_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi3670_media1_gate_sep_clks,
- ARRAY_SIZE(hi3670_media1_gate_sep_clks),
- clk_data);
- hisi_clk_register_gate(hi3670_media1_gate_clks,
- ARRAY_SIZE(hi3670_media1_gate_clks),
- clk_data);
- hisi_clk_register_mux(hi3670_media1_mux_clks,
- ARRAY_SIZE(hi3670_media1_mux_clks),
- clk_data);
- hisi_clk_register_divider(hi3670_media1_divider_clks,
- ARRAY_SIZE(hi3670_media1_divider_clks),
- clk_data);
-}
-
-static void hi3670_clk_media2_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- int nr = ARRAY_SIZE(hi3670_media2_gate_sep_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi3670_media2_gate_sep_clks,
- ARRAY_SIZE(hi3670_media2_gate_sep_clks),
- clk_data);
-}
+static const struct hisi_clocks hi3670_clk_crgctrl_clks = {
+ .fixed_rate_clks = hi3670_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3670_fixed_rate_clks),
+ .fixed_factor_clks = hi3670_crg_fixed_factor_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hi3670_crg_fixed_factor_clks),
+ .mux_clks = hi3670_crgctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3670_crgctrl_mux_clks),
+ .divider_clks = hi3670_crgctrl_divider_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3670_crgctrl_divider_clks),
+ .gate_clks = hi3670_crgctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3670_crgctrl_gate_clks),
+ .gate_sep_clks = hi3670_crgctrl_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3670_crgctrl_gate_sep_clks),
+};
+
+static const struct hisi_clocks hi3670_clk_pctrl_clks = {
+ .gate_clks = hi3670_pctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3670_pctrl_gate_clks),
+};
+
+static const struct hisi_clocks hi3670_clk_pmuctrl_clks = {
+ .gate_clks = hi3670_pmu_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3670_pmu_gate_clks),
+};
+
+static const struct hisi_clocks hi3670_clk_sctrl_clks = {
+ .mux_clks = hi3670_sctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3670_sctrl_mux_clks),
+ .divider_clks = hi3670_sctrl_divider_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3670_sctrl_divider_clks),
+ .gate_clks = hi3670_sctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3670_sctrl_gate_clks),
+ .gate_sep_clks = hi3670_sctrl_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3670_sctrl_gate_sep_clks),
+};
+
+static const struct hisi_clocks hi3670_clk_iomcu_clks = {
+ .fixed_factor_clks = hi3670_iomcu_fixed_factor_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hi3670_iomcu_fixed_factor_clks),
+ .gate_clks = hi3670_iomcu_gate_sep_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3670_iomcu_gate_sep_clks),
+};
+
+static const struct hisi_clocks hi3670_clk_media1_clks = {
+ .mux_clks = hi3670_media1_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3670_media1_mux_clks),
+ .divider_clks = hi3670_media1_divider_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3670_media1_divider_clks),
+ .gate_clks = hi3670_media1_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3670_media1_gate_clks),
+ .gate_sep_clks = hi3670_media1_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3670_media1_gate_sep_clks),
+};
+
+static const struct hisi_clocks hi3670_clk_media2_clks = {
+ .gate_sep_clks = hi3670_media2_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3670_media2_gate_sep_clks),
+};
static const struct of_device_id hi3670_clk_match_table[] = {
{ .compatible = "hisilicon,hi3670-crgctrl",
- .data = hi3670_clk_crgctrl_init },
+ .data = &hi3670_clk_crgctrl_clks },
{ .compatible = "hisilicon,hi3670-pctrl",
- .data = hi3670_clk_pctrl_init },
+ .data = &hi3670_clk_pctrl_clks },
{ .compatible = "hisilicon,hi3670-pmuctrl",
- .data = hi3670_clk_pmuctrl_init },
+ .data = &hi3670_clk_pmuctrl_clks },
{ .compatible = "hisilicon,hi3670-sctrl",
- .data = hi3670_clk_sctrl_init },
+ .data = &hi3670_clk_sctrl_clks },
{ .compatible = "hisilicon,hi3670-iomcu",
- .data = hi3670_clk_iomcu_init },
+ .data = &hi3670_clk_iomcu_clks },
{ .compatible = "hisilicon,hi3670-media1-crg",
- .data = hi3670_clk_media1_init },
+ .data = &hi3670_clk_media1_clks },
{ .compatible = "hisilicon,hi3670-media2-crg",
- .data = hi3670_clk_media2_init },
+ .data = &hi3670_clk_media2_clks },
{ }
};
-
-static int hi3670_clk_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *np = pdev->dev.of_node;
- void (*init_func)(struct device_node *np);
-
- init_func = of_device_get_match_data(dev);
- if (!init_func)
- return -ENODEV;
-
- init_func(np);
-
- return 0;
-}
+MODULE_DEVICE_TABLE(of, hi3670_clk_match_table);
static struct platform_driver hi3670_clk_driver = {
- .probe = hi3670_clk_probe,
+ .probe = hisi_clk_probe,
+ .remove = hisi_clk_remove,
.driver = {
.name = "hi3670-clk",
.of_match_table = hi3670_clk_match_table,
},
};
-static int __init hi3670_clk_init(void)
-{
- return platform_driver_register(&hi3670_clk_driver);
-}
-core_initcall(hi3670_clk_init);
+module_platform_driver(hi3670_clk_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3670 Clock Driver");
@@ -0,0 +1,333 @@
--- a/drivers/clk/hisilicon/clk-hi6220.c
+++ b/drivers/clk/hisilicon/clk-hi6220.c
@@ -9,17 +9,22 @@
#include <linux/kernel.h>
#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/io.h>
-#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <dt-bindings/clock/hi6220-clock.h>
#include "clk.h"
+static int
+hi6220_clk_register_divider_stub(struct device *dev, const void *clks,
+ size_t num, struct hisi_clock_data *data)
+{
+ return hi6220_clk_register_divider(dev, clks, num, data);
+}
/* clocks in AO (always on) controller */
-static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
+static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] = {
{ HI6220_REF32K, "ref32k", NULL, 0, 32764, },
{ HI6220_CLK_TCXO, "clk_tcxo", NULL, 0, 19200000, },
{ HI6220_MMC1_PAD, "mmc1_pad", NULL, 0, 100000000, },
@@ -35,7 +40,7 @@ static struct hisi_fixed_rate_clock hi62
{ HI6220_PLL_DDR, "ddrpll0", NULL, 0, 1600000000,},
};
-static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
+static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] = {
{ HI6220_300M, "clk_300m", "syspll", 1, 4, 0, },
{ HI6220_150M, "clk_150m", "clk_300m", 1, 2, 0, },
{ HI6220_PICOPHY_SRC, "picophy_src", "clk_150m", 1, 4, 0, },
@@ -48,7 +53,7 @@ static struct hisi_fixed_factor_clock hi
{ HI6220_MMC2_SMP, "mmc2_sample", "mmc2_sel", 1, 8, 0, },
};
-static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
+static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] = {
{ HI6220_WDT0_PCLK, "wdt0_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
{ HI6220_WDT1_PCLK, "wdt1_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
{ HI6220_WDT2_PCLK, "wdt2_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
@@ -66,47 +71,43 @@ static struct hisi_gate_clock hi6220_sep
{ HI6220_RTC1_PCLK, "rtc1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 26, 0, },
};
-static void __init hi6220_clk_ao_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data_ao;
-
- clk_data_ao = hisi_clk_init(np, HI6220_AO_NR_CLKS);
- if (!clk_data_ao)
- return;
-
- hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
- ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data_ao);
-
- hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
- ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data_ao);
+static const struct hisi_clocks hi6220_ao_clks = {
+ .nr = HI6220_AO_NR_CLKS,
+ .fixed_rate_clks = hi6220_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi6220_fixed_rate_clks),
+ .fixed_factor_clks = hi6220_fixed_factor_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hi6220_fixed_factor_clks),
+ .gate_sep_clks = hi6220_separated_gate_clks_ao,
+ .gate_sep_clks_num = ARRAY_SIZE(hi6220_separated_gate_clks_ao),
+};
- hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
- ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data_ao);
+static void hi6220_clk_ao_early_init(struct device_node *np)
+{
+ hisi_clk_early_init(np, &hi6220_ao_clks);
}
/* Allow reset driver to probe as well */
-CLK_OF_DECLARE_DRIVER(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_init);
-
+CLK_OF_DECLARE_DRIVER(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_early_init);
/* clocks in sysctrl */
-static const char *mmc0_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
-static const char *mmc0_mux1_p[] __initdata = { "mmc0_mux0", "pll_media_gate", };
-static const char *mmc0_src_p[] __initdata = { "mmc0srcsel", "mmc0_div", };
-static const char *mmc1_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
-static const char *mmc1_mux1_p[] __initdata = { "mmc1_mux0", "pll_media_gate", };
-static const char *mmc1_src_p[] __initdata = { "mmc1srcsel", "mmc1_div", };
-static const char *mmc2_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
-static const char *mmc2_mux1_p[] __initdata = { "mmc2_mux0", "pll_media_gate", };
-static const char *mmc2_src_p[] __initdata = { "mmc2srcsel", "mmc2_div", };
-static const char *mmc0_sample_in[] __initdata = { "mmc0_sample", "mmc0_pad", };
-static const char *mmc1_sample_in[] __initdata = { "mmc1_sample", "mmc1_pad", };
-static const char *mmc2_sample_in[] __initdata = { "mmc2_sample", "mmc2_pad", };
-static const char *uart1_src[] __initdata = { "clk_tcxo", "clk_150m", };
-static const char *uart2_src[] __initdata = { "clk_tcxo", "clk_150m", };
-static const char *uart3_src[] __initdata = { "clk_tcxo", "clk_150m", };
-static const char *uart4_src[] __initdata = { "clk_tcxo", "clk_150m", };
-static const char *hifi_src[] __initdata = { "syspll", "pll_media_gate", };
+static const char *const mmc0_mux0_p[] = { "pll_ddr_gate", "syspll", };
+static const char *const mmc0_mux1_p[] = { "mmc0_mux0", "pll_media_gate", };
+static const char *const mmc0_src_p[] = { "mmc0srcsel", "mmc0_div", };
+static const char *const mmc1_mux0_p[] = { "pll_ddr_gate", "syspll", };
+static const char *const mmc1_mux1_p[] = { "mmc1_mux0", "pll_media_gate", };
+static const char *const mmc1_src_p[] = { "mmc1srcsel", "mmc1_div", };
+static const char *const mmc2_mux0_p[] = { "pll_ddr_gate", "syspll", };
+static const char *const mmc2_mux1_p[] = { "mmc2_mux0", "pll_media_gate", };
+static const char *const mmc2_src_p[] = { "mmc2srcsel", "mmc2_div", };
+static const char *const mmc0_sample_in[] = { "mmc0_sample", "mmc0_pad", };
+static const char *const mmc1_sample_in[] = { "mmc1_sample", "mmc1_pad", };
+static const char *const mmc2_sample_in[] = { "mmc2_sample", "mmc2_pad", };
+static const char *const uart1_src[] = { "clk_tcxo", "clk_150m", };
+static const char *const uart2_src[] = { "clk_tcxo", "clk_150m", };
+static const char *const uart3_src[] = { "clk_tcxo", "clk_150m", };
+static const char *const uart4_src[] = { "clk_tcxo", "clk_150m", };
+static const char *const hifi_src[] = { "syspll", "pll_media_gate", };
-static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
+static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] = {
{ HI6220_MMC0_CLK, "mmc0_clk", "mmc0_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, },
{ HI6220_MMC0_CIUCLK, "mmc0_ciuclk", "mmc0_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, },
{ HI6220_MMC1_CLK, "mmc1_clk", "mmc1_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1, 0, },
@@ -143,7 +144,7 @@ static struct hisi_gate_clock hi6220_sep
{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IS_CRITICAL, 0x270, 12, 0, },
};
-static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
+static struct hisi_mux_clock hi6220_mux_clks_sys[] = {
{ HI6220_MMC0_SRC, "mmc0_src", mmc0_src_p, ARRAY_SIZE(mmc0_src_p), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, },
{ HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, },
{ HI6220_MMC1_SRC, "mmc1_src", mmc1_src_p, ARRAY_SIZE(mmc1_src_p), CLK_SET_RATE_PARENT, 0x4, 2, 1, 0, },
@@ -163,7 +164,7 @@ static struct hisi_mux_clock hi6220_mux_
{ HI6220_MMC2_MUX1, "mmc2_mux1", mmc2_mux1_p, ARRAY_SIZE(mmc2_mux1_p), CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
};
-static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
+static struct hi6220_divider_clock hi6220_div_clks_sys[] = {
{ HI6220_CLK_BUS, "clk_bus", "clk_300m", CLK_SET_RATE_PARENT, 0x490, 0, 4, 7, },
{ HI6220_MMC0_DIV, "mmc0_div", "mmc0_syspll", CLK_SET_RATE_PARENT, 0x494, 0, 6, 7, },
{ HI6220_MMC1_DIV, "mmc1_div", "mmc1_syspll", CLK_SET_RATE_PARENT, 0x498, 0, 6, 7, },
@@ -174,32 +175,23 @@ static struct hi6220_divider_clock hi622
{ HI6220_CS_ATB_DIV, "cs_atb_div", "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0, 4, 7, },
};
-static void __init hi6220_clk_sys_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
- ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
-
- hisi_clk_register_mux(hi6220_mux_clks_sys,
- ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
-
- hi6220_clk_register_divider(hi6220_div_clks_sys,
- ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
-}
-CLK_OF_DECLARE_DRIVER(hi6220_clk_sys, "hisilicon,hi6220-sysctrl", hi6220_clk_sys_init);
-
+static const struct hisi_clocks hi6220_sys_clks = {
+ .nr = HI6220_SYS_NR_CLKS,
+ .mux_clks = hi6220_mux_clks_sys,
+ .mux_clks_num = ARRAY_SIZE(hi6220_mux_clks_sys),
+ .gate_sep_clks = hi6220_separated_gate_clks_sys,
+ .gate_sep_clks_num = ARRAY_SIZE(hi6220_separated_gate_clks_sys),
+ .customized_clks = hi6220_div_clks_sys,
+ .customized_clks_num = ARRAY_SIZE(hi6220_div_clks_sys),
+ .clk_register_customized = hi6220_clk_register_divider_stub,
+};
/* clocks in media controller */
-static const char *clk_1000_1200_src[] __initdata = { "pll_gpu_gate", "media_syspll_src", };
-static const char *clk_1440_1200_src[] __initdata = { "media_syspll_src", "media_pll_src", };
-static const char *clk_1000_1440_src[] __initdata = { "pll_gpu_gate", "media_pll_src", };
+static const char *const clk_1000_1200_src[] = { "pll_gpu_gate", "media_syspll_src", };
+static const char *const clk_1440_1200_src[] = { "media_syspll_src", "media_pll_src", };
+static const char *const clk_1000_1440_src[] = { "pll_gpu_gate", "media_pll_src", };
-static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
+static struct hisi_gate_clock hi6220_separated_gate_clks_media[] = {
{ HI6220_DSI_PCLK, "dsi_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0, 0, },
{ HI6220_G3D_PCLK, "g3d_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1, 0, },
{ HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu", "ade_core_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3, 0, },
@@ -215,13 +207,13 @@ static struct hisi_gate_clock hi6220_sep
{ HI6220_MED_SYSPLL, "media_syspll_src", "media_syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
};
-static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
+static struct hisi_mux_clock hi6220_mux_clks_media[] = {
{ HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
{ HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
{ HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
};
-static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
+static struct hi6220_divider_clock hi6220_div_clks_media[] = {
{ HI6220_CODEC_JPEG, "codec_jpeg_aclk", "media_pll_src", CLK_SET_RATE_PARENT, 0xcbc, 0, 4, 23, },
{ HI6220_ISP_SCLK_SRC, "isp_sclk_src", "isp_sclk_gate", CLK_SET_RATE_PARENT, 0xcbc, 8, 4, 15, },
{ HI6220_ISP_SCLK1, "isp_sclk1", "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
@@ -231,28 +223,19 @@ static struct hi6220_divider_clock hi622
{ HI6220_CODEC_VPU_SRC, "codec_vpu_src", "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
};
-static void __init hi6220_clk_media_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
- ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
-
- hisi_clk_register_mux(hi6220_mux_clks_media,
- ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
-
- hi6220_clk_register_divider(hi6220_div_clks_media,
- ARRAY_SIZE(hi6220_div_clks_media), clk_data);
-}
-CLK_OF_DECLARE_DRIVER(hi6220_clk_media, "hisilicon,hi6220-mediactrl", hi6220_clk_media_init);
-
+static const struct hisi_clocks hi6220_media_clks = {
+ .nr = HI6220_MEDIA_NR_CLKS,
+ .mux_clks = hi6220_mux_clks_media,
+ .mux_clks_num = ARRAY_SIZE(hi6220_mux_clks_media),
+ .gate_sep_clks = hi6220_separated_gate_clks_media,
+ .gate_sep_clks_num = ARRAY_SIZE(hi6220_separated_gate_clks_media),
+ .customized_clks = hi6220_div_clks_media,
+ .customized_clks_num = ARRAY_SIZE(hi6220_div_clks_media),
+ .clk_register_customized = hi6220_clk_register_divider_stub,
+};
/* clocks in pmctrl */
-static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
+static struct hisi_gate_clock hi6220_gate_clks_power[] = {
{ HI6220_PLL_GPU_GATE, "pll_gpu_gate", "gpupll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8, 0, 0, },
{ HI6220_PLL1_DDR_GATE, "pll1_ddr_gate", "ddrpll1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0, 0, },
{ HI6220_PLL_DDR_GATE, "pll_ddr_gate", "ddrpll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0, 0, },
@@ -260,26 +243,19 @@ static struct hisi_gate_clock hi6220_gat
{ HI6220_PLL0_BBP_GATE, "pll0_bbp_gate", "bbppll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0, 0, },
};
-static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
+static struct hi6220_divider_clock hi6220_div_clks_power[] = {
{ HI6220_DDRC_SRC, "ddrc_src", "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
{ HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src", CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
};
-static void __init hi6220_clk_power_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate(hi6220_gate_clks_power,
- ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
-
- hi6220_clk_register_divider(hi6220_div_clks_power,
- ARRAY_SIZE(hi6220_div_clks_power), clk_data);
-}
-CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-pmctrl", hi6220_clk_power_init);
+static const struct hisi_clocks hi6220_power_clks = {
+ .nr = HI6220_POWER_NR_CLKS,
+ .gate_clks = hi6220_gate_clks_power,
+ .gate_clks_num = ARRAY_SIZE(hi6220_gate_clks_power),
+ .customized_clks = hi6220_div_clks_power,
+ .customized_clks_num = ARRAY_SIZE(hi6220_div_clks_power),
+ .clk_register_customized = hi6220_clk_register_divider_stub,
+};
/* clocks in acpu */
static const struct hisi_gate_clock hi6220_acpu_sc_gate_sep_clks[] = {
@@ -287,18 +263,36 @@ static const struct hisi_gate_clock hi62
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0xc, 11, 0, },
};
-static void __init hi6220_clk_acpu_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi6220_acpu_sc_gate_sep_clks);
+static const struct hisi_clocks hi6220_acpu_clks = {
+ .gate_sep_clks = hi6220_acpu_sc_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi6220_acpu_sc_gate_sep_clks),
+};
+
+static const struct of_device_id hi6220_clk_match_table[] = {
+ { .compatible = "hisilicon,hi6220-aoctrl",
+ .data = &hi6220_ao_clks },
+ { .compatible = "hisilicon,hi6220-sysctrl",
+ .data = &hi6220_sys_clks },
+ { .compatible = "hisilicon,hi6220-mediactrl",
+ .data = &hi6220_media_clks },
+ { .compatible = "hisilicon,hi6220-pmctrl",
+ .data = &hi6220_power_clks },
+ { .compatible = "hisilicon,hi6220-acpu-sctrl",
+ .data = &hi6220_acpu_clks },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hi6220_clk_match_table);
+
+static struct platform_driver hi6220_clk_driver = {
+ .probe = hisi_clk_probe,
+ .remove = hisi_clk_remove,
+ .driver = {
+ .name = "hi6220-clock",
+ .of_match_table = hi6220_clk_match_table,
+ },
+};
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi6220_acpu_sc_gate_sep_clks,
- ARRAY_SIZE(hi6220_acpu_sc_gate_sep_clks),
- clk_data);
-}
+module_platform_driver(hi6220_clk_driver);
-CLK_OF_DECLARE(hi6220_clk_acpu, "hisilicon,hi6220-acpu-sctrl", hi6220_clk_acpu_init);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi6220 Clock Driver");
@@ -0,0 +1,58 @@
--- a/drivers/clk/hisilicon/clk-hi6220-stub.c
+++ b/drivers/clk/hisilicon/clk-hi6220-stub.c
@@ -161,11 +161,11 @@ static int hi6220_stub_clk_set_rate(stru
return ret;
}
-static long hi6220_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int hi6220_stub_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
- unsigned long new_rate = rate / 1000; /* kHz */
+ unsigned long new_rate = req->rate / 1000; /* kHz */
switch (stub_clk->id) {
case HI6220_STUB_ACPU0:
@@ -181,12 +181,14 @@ static long hi6220_stub_clk_round_rate(s
break;
}
- return new_rate;
+ req->rate = new_rate;
+
+ return 0;
}
static const struct clk_ops hi6220_stub_clk_ops = {
.recalc_rate = hi6220_stub_clk_recalc_rate,
- .round_rate = hi6220_stub_clk_round_rate,
+ .determine_rate = hi6220_stub_clk_determine_rate,
.set_rate = hi6220_stub_clk_set_rate,
};
@@ -195,7 +197,6 @@ static int hi6220_stub_clk_probe(struct
struct device *dev = &pdev->dev;
struct clk_init_data init;
struct hi6220_stub_clk *stub_clk;
- struct clk *clk;
struct device_node *np = pdev->dev.of_node;
int ret;
@@ -233,11 +234,11 @@ static int hi6220_stub_clk_probe(struct
init.num_parents = 0;
init.flags = 0;
- clk = devm_clk_register(dev, &stub_clk->hw);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ ret = devm_clk_hw_register(dev, &stub_clk->hw);
+ if (ret)
+ return ret;
- ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &stub_clk->hw);
if (ret) {
dev_err(dev, "failed to register OF clock provider\n");
return ret;
@@ -0,0 +1,55 @@
--- a/drivers/clk/hisilicon/clk-hip04.c
+++ b/drivers/clk/hisilicon/clk-hip04.c
@@ -10,8 +10,8 @@
#include <linux/kernel.h>
#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <dt-bindings/clock/hip04-clock.h>
@@ -24,16 +24,28 @@ static struct hisi_fixed_rate_clock hip0
{ HIP04_CLK_168M, "clk168m", NULL, 0, 168750000, },
};
-static void __init hip04_clk_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- clk_data = hisi_clk_init(np, HIP04_NR_CLKS);
- if (!clk_data)
- return;
-
- hisi_clk_register_fixed_rate(hip04_fixed_rate_clks,
- ARRAY_SIZE(hip04_fixed_rate_clks),
- clk_data);
-}
-CLK_OF_DECLARE(hip04_clk, "hisilicon,hip04-clock", hip04_clk_init);
+static const struct hisi_clocks hip04_clks = {
+ .fixed_rate_clks = hip04_fixed_rate_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hip04_fixed_rate_clks),
+};
+
+static const struct of_device_id hip04_clk_match_table[] = {
+ { .compatible = "hisilicon,hip04-clock",
+ .data = &hip04_clks },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hip04_clk_match_table);
+
+static struct platform_driver hip04_clk_driver = {
+ .probe = hisi_clk_probe,
+ .remove = hisi_clk_remove,
+ .driver = {
+ .name = "hip04-clock",
+ .of_match_table = hip04_clk_match_table,
+ },
+};
+
+module_platform_driver(hip04_clk_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HiSilicon HiP04 Clock Driver");
@@ -0,0 +1,43 @@
--- a/drivers/clk/hisilicon/clk-hisi-phase.c
+++ b/drivers/clk/hisilicon/clk-hisi-phase.c
@@ -5,11 +5,11 @@
* Simple HiSilicon phase clock implementation.
*/
+#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>
#include "clk.h"
@@ -90,12 +90,13 @@ static const struct clk_ops clk_phase_op
.set_phase = hisi_clk_set_phase,
};
-struct clk *clk_register_hisi_phase(struct device *dev,
+struct clk_hw *devm_clk_hw_register_hisi_phase(struct device *dev,
const struct hisi_phase_clock *clks,
void __iomem *base, spinlock_t *lock)
{
struct clk_hisi_phase *phase;
struct clk_init_data init;
+ int ret;
phase = devm_kzalloc(dev, sizeof(struct clk_hisi_phase), GFP_KERNEL);
if (!phase)
@@ -116,6 +117,10 @@ struct clk *clk_register_hisi_phase(stru
phase->phase_num = clks->phase_num;
phase->hw.init = &init;
- return devm_clk_register(dev, &phase->hw);
+ ret = devm_clk_hw_register(dev, &phase->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &phase->hw;
}
-EXPORT_SYMBOL_GPL(clk_register_hisi_phase);
+EXPORT_SYMBOL_GPL(devm_clk_hw_register_hisi_phase);
@@ -0,0 +1,168 @@
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -4,13 +4,17 @@
* Copyright (c) 2014 Hisilicon Limited.
*/
-#include <linux/of_address.h>
#include <dt-bindings/clock/hix5hd2-clock.h>
-#include <linux/slab.h>
+
+#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+
#include "clk.h"
-static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
+static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] = {
{ HIX5HD2_FIXED_1200M, "1200m", NULL, 0, 1200000000, },
{ HIX5HD2_FIXED_400M, "400m", NULL, 0, 400000000, },
{ HIX5HD2_FIXED_48M, "48m", NULL, 0, 48000000, },
@@ -43,19 +47,19 @@ static struct hisi_fixed_rate_clock hix5
{ HIX5HD2_FIXED_83M, "83m", NULL, 0, 83333333, },
};
-static const char *const sfc_mux_p[] __initconst = {
+static const char *const sfc_mux_p[] = {
"24m", "150m", "200m", "100m", "75m", };
static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
-static const char *const sdio_mux_p[] __initconst = {
+static const char *const sdio_mux_p[] = {
"75m", "100m", "50m", "15m", };
static u32 sdio_mux_table[] = {0, 1, 2, 3};
-static const char *const fephy_mux_p[] __initconst = { "25m", "125m"};
+static const char *const fephy_mux_p[] = { "25m", "125m"};
static u32 fephy_mux_table[] = {0, 1};
-static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = {
+static struct hisi_mux_clock hix5hd2_mux_clks[] = {
{ HIX5HD2_SFC_MUX, "sfc_mux", sfc_mux_p, ARRAY_SIZE(sfc_mux_p),
CLK_SET_RATE_PARENT, 0x5c, 8, 3, 0, sfc_mux_table, },
{ HIX5HD2_MMC_MUX, "mmc_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
@@ -67,7 +71,7 @@ static struct hisi_mux_clock hix5hd2_mux
CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, },
};
-static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = {
+static struct hisi_gate_clock hix5hd2_gate_clks[] = {
/* sfc */
{ HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux",
CLK_SET_RATE_PARENT, 0x5c, 0, 0, },
@@ -153,7 +157,7 @@ struct hix5hd2_clk_complex {
u32 phy_rst_mask;
};
-static struct hix5hd2_complex_clock hix5hd2_complex_clks[] __initdata = {
+static struct hix5hd2_complex_clock hix5hd2_complex_clks[] = {
{"clk_mac0", "clk_fephy", HIX5HD2_MAC0_CLK,
0xcc, 0xa, 0x500, 0x120, 0, 0x10, TYPE_ETHER},
{"clk_mac1", "clk_fwd_sys", HIX5HD2_MAC1_CLK,
@@ -249,21 +253,22 @@ static const struct clk_ops clk_complex_
.disable = clk_complex_disable,
};
-static void __init
-hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
+static int
+hix5hd2_clk_register_complex(struct device *dev, const void *clocks, size_t num,
struct hisi_clock_data *data)
{
+ const struct hix5hd2_complex_clock *clks = clocks;
void __iomem *base = data->base;
int i;
+ int ret;
- for (i = 0; i < nums; i++) {
+ for (i = 0; i < num; i++) {
struct hix5hd2_clk_complex *p_clk;
- struct clk *clk;
struct clk_init_data init;
- p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
+ p_clk = devm_kzalloc(dev, sizeof(*p_clk), GFP_KERNEL);
if (!p_clk)
- return;
+ return -ENOMEM;
init.name = clks[i].name;
if (clks[i].type == TYPE_ETHER)
@@ -284,36 +289,49 @@ hix5hd2_clk_register_complex(struct hix5
p_clk->phy_rst_mask = clks[i].phy_rst_mask;
p_clk->hw.init = &init;
- clk = clk_register(NULL, &p_clk->hw);
- if (IS_ERR(clk)) {
- kfree(p_clk);
+ ret = devm_clk_hw_register(dev, &p_clk->hw);
+ if (ret) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
- continue;
+ return ret;
}
- data->clk_data.clks[clks[i].id] = clk;
+ data->clk_data->hws[clks[i].id] = &p_clk->hw;
}
+
+ return 0;
}
-static void __init hix5hd2_clk_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
+static const struct hisi_clocks hix5hd2_clks = {
+ .nr = HIX5HD2_NR_CLKS,
+ .fixed_rate_clks = hix5hd2_fixed_rate_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hix5hd2_fixed_rate_clks),
+ .mux_clks = hix5hd2_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hix5hd2_mux_clks),
+ .gate_clks = hix5hd2_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hix5hd2_gate_clks),
+ .customized_clks = hix5hd2_complex_clks,
+ .customized_clks_num = ARRAY_SIZE(hix5hd2_complex_clks),
+ .clk_register_customized = hix5hd2_clk_register_complex,
+};
- clk_data = hisi_clk_init(np, HIX5HD2_NR_CLKS);
- if (!clk_data)
- return;
-
- hisi_clk_register_fixed_rate(hix5hd2_fixed_rate_clks,
- ARRAY_SIZE(hix5hd2_fixed_rate_clks),
- clk_data);
- hisi_clk_register_mux(hix5hd2_mux_clks, ARRAY_SIZE(hix5hd2_mux_clks),
- clk_data);
- hisi_clk_register_gate(hix5hd2_gate_clks,
- ARRAY_SIZE(hix5hd2_gate_clks), clk_data);
- hix5hd2_clk_register_complex(hix5hd2_complex_clks,
- ARRAY_SIZE(hix5hd2_complex_clks),
- clk_data);
-}
+static const struct of_device_id hix5hd2_clk_match_table[] = {
+ { .compatible = "hisilicon,hix5hd2-clock",
+ .data = &hix5hd2_clks },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hix5hd2_clk_match_table);
+
+static struct platform_driver hix5hd2_clk_driver = {
+ .probe = hisi_clk_probe,
+ .remove = hisi_clk_remove,
+ .driver = {
+ .name = "hix5hd2-clock",
+ .of_match_table = hix5hd2_clk_match_table,
+ },
+};
+
+module_platform_driver(hix5hd2_clk_driver);
-CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hix5hd2 Clock Driver");
@@ -0,0 +1,170 @@
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -4,6 +4,7 @@
*
* Copyright (c) 2012-2013 Hisilicon Limited.
* Copyright (c) 2012-2013 Linaro Limited.
+ * Copyright (c) 2023 David Yang
*
* Author: Haojian Zhuang <haojian.zhuang@linaro.org>
* Xin Li <li.xin@linaro.org>
@@ -15,12 +16,25 @@
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/spinlock.h>
+#include <linux/platform_device.h>
struct platform_device;
+struct hisi_clocks;
+/*
+ * (Virtual) fixed clocks, often depended by crucial peripherals, require
+ * early initialization before device probing, thus cannot use devm APIs.
+ * Otherwise, kernel will defer those peripherals, causing boot failure.
+ *
+ * fixed_rate and fixed_factor clocks are driver-managed. They are freed by
+ * `hisi_clk_free` altogether.
+ *
+ * Other clocks are devm-managed.
+ */
struct hisi_clock_data {
- struct clk_onecell_data clk_data;
- void __iomem *base;
+ struct clk_hw_onecell_data *clk_data;
+ void __iomem *base;
+ const struct hisi_clocks *clks;
};
struct hisi_fixed_rate_clock {
@@ -103,55 +117,83 @@ struct hisi_gate_clock {
const char *alias;
};
-struct clk *hisi_register_clkgate_sep(struct device *, const char *,
- const char *, unsigned long,
- void __iomem *, u8,
- u8, spinlock_t *);
-struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
- const char *parent_name, unsigned long flags, void __iomem *reg,
- u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
-
-struct hisi_clock_data *hisi_clk_alloc(struct platform_device *, int);
-struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
-int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *,
- int, struct hisi_clock_data *);
-int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *,
- int, struct hisi_clock_data *);
-int hisi_clk_register_mux(const struct hisi_mux_clock *, int,
- struct hisi_clock_data *);
-struct clk *clk_register_hisi_phase(struct device *dev,
- const struct hisi_phase_clock *clks,
+struct hisi_clocks {
+ /* if 0, sum all *_num */
+ size_t nr;
+
+ int (*prologue)(struct device *dev, struct hisi_clock_data *data);
+
+ const struct hisi_fixed_rate_clock *fixed_rate_clks;
+ size_t fixed_rate_clks_num;
+
+ const struct hisi_fixed_factor_clock *fixed_factor_clks;
+ size_t fixed_factor_clks_num;
+
+ const struct hisi_mux_clock *mux_clks;
+ size_t mux_clks_num;
+
+ const struct hisi_phase_clock *phase_clks;
+ size_t phase_clks_num;
+
+ const struct hisi_divider_clock *divider_clks;
+ size_t divider_clks_num;
+
+ const struct hisi_gate_clock *gate_clks;
+ size_t gate_clks_num;
+
+ const struct hisi_gate_clock *gate_sep_clks;
+ size_t gate_sep_clks_num;
+
+ const void *customized_clks;
+ size_t customized_clks_num;
+ int (*clk_register_customized)(struct device *dev, const void *clks,
+ size_t num, struct hisi_clock_data *data);
+};
+
+struct clk_hw *
+devm_clk_hw_register_hisi_phase(struct device *dev, const struct hisi_phase_clock *clks,
void __iomem *base, spinlock_t *lock);
+struct clk_hw *
+devm_clk_hw_register_hisi_gate_sep(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 clk_gate_flags, spinlock_t *lock);
+struct clk_hw *
+devm_clk_hw_register_hi6220_divider(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 shift,
+ u8 width, u32 mask_bit, spinlock_t *lock);
+
+struct hisi_clock_data *hisi_clk_init(struct device_node *np, size_t nr);
+void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data);
+
+int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+
+int hisi_clk_register_mux(struct device *dev, const struct hisi_mux_clock *clks,
+ size_t num, struct hisi_clock_data *data);
int hisi_clk_register_phase(struct device *dev,
- const struct hisi_phase_clock *clks,
- int nums, struct hisi_clock_data *data);
-int hisi_clk_register_divider(const struct hisi_divider_clock *,
- int, struct hisi_clock_data *);
-int hisi_clk_register_gate(const struct hisi_gate_clock *,
- int, struct hisi_clock_data *);
-void hisi_clk_register_gate_sep(const struct hisi_gate_clock *,
- int, struct hisi_clock_data *);
-void hi6220_clk_register_divider(const struct hi6220_divider_clock *,
- int, struct hisi_clock_data *);
-
-#define hisi_clk_unregister(type) \
-static inline \
-void hisi_clk_unregister_##type(const struct hisi_##type##_clock *clks, \
- int nums, struct hisi_clock_data *data) \
-{ \
- struct clk **clocks = data->clk_data.clks; \
- int i; \
- for (i = 0; i < nums; i++) { \
- int id = clks[i].id; \
- if (clocks[id]) \
- clk_unregister_##type(clocks[id]); \
- } \
-}
-
-hisi_clk_unregister(fixed_rate)
-hisi_clk_unregister(fixed_factor)
-hisi_clk_unregister(mux)
-hisi_clk_unregister(divider)
-hisi_clk_unregister(gate)
+ const struct hisi_phase_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_divider(struct device *dev,
+ const struct hisi_divider_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_gate(struct device *dev,
+ const struct hisi_gate_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_gate_sep(struct device *dev,
+ const struct hisi_gate_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hi6220_clk_register_divider(struct device *dev,
+ const struct hi6220_divider_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+
+/* helper functions for platform driver */
+
+int hisi_clk_early_init(struct device_node *np, const struct hisi_clocks *clks);
+int hisi_clk_probe(struct platform_device *pdev);
+void hisi_clk_remove(struct platform_device *pdev);
#endif /* __HISI_CLK_H */
@@ -0,0 +1,214 @@
--- a/drivers/clk/hisilicon/crg-hi3516cv300.c
+++ b/drivers/clk/hisilicon/crg-hi3516cv300.c
@@ -12,7 +12,6 @@
#include <linux/platform_device.h>
#include "clk.h"
#include "crg.h"
-#include "reset.h"
/* hi3516CV300 core CRG */
#define HI3516CV300_INNER_CLK_OFFSET 64
@@ -126,67 +125,14 @@ static const struct hisi_gate_clock hi35
{ HI3516CV300_USB2_PHY_CLK, "clk_usb2_phy", NULL, 0, 0xb8, 7, 0, },
};
-static struct hisi_clock_data *hi3516cv300_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3516CV300_CRG_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_fixed_rate(hi3516cv300_fixed_rate_clks,
- ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = hisi_clk_register_mux(hi3516cv300_mux_clks,
- ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
- if (ret)
- goto unregister_fixed_rate;
-
- ret = hisi_clk_register_gate(hi3516cv300_gate_clks,
- ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
- if (ret)
- goto unregister_mux;
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_gate:
- hisi_clk_unregister_gate(hi3516cv300_gate_clks,
- ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
-unregister_mux:
- hisi_clk_unregister_mux(hi3516cv300_mux_clks,
- ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
-unregister_fixed_rate:
- hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
- ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3516cv300_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3516cv300_gate_clks,
- ARRAY_SIZE(hi3516cv300_gate_clks), crg->clk_data);
- hisi_clk_unregister_mux(hi3516cv300_mux_clks,
- ARRAY_SIZE(hi3516cv300_mux_clks), crg->clk_data);
- hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
- ARRAY_SIZE(hi3516cv300_fixed_rate_clks), crg->clk_data);
-}
-
-static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
- .register_clks = hi3516cv300_clk_register,
- .unregister_clks = hi3516cv300_clk_unregister,
+static const struct hisi_clocks hi3516cv300_crg_clks = {
+ .nr = HI3516CV300_CRG_NR_CLKS,
+ .fixed_rate_clks = hi3516cv300_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3516cv300_fixed_rate_clks),
+ .mux_clks = hi3516cv300_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3516cv300_mux_clks),
+ .gate_clks = hi3516cv300_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3516cv300_gate_clks),
};
/* hi3516CV300 sysctrl CRG */
@@ -200,118 +146,35 @@ static const struct hisi_mux_clock hi351
CLK_SET_RATE_PARENT, 0x0, 23, 1, 0, wdt_mux_table, },
};
-static struct hisi_clock_data *hi3516cv300_sysctrl_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3516CV300_SYSCTRL_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_mux(hi3516cv300_sysctrl_mux_clks,
- ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
- if (ret)
- return ERR_PTR(ret);
-
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_mux;
-
- return clk_data;
-
-unregister_mux:
- hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
- ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3516cv300_sysctrl_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
- ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
- crg->clk_data);
-}
-
-static const struct hisi_crg_funcs hi3516cv300_sysctrl_funcs = {
- .register_clks = hi3516cv300_sysctrl_clk_register,
- .unregister_clks = hi3516cv300_sysctrl_clk_unregister,
+static const struct hisi_clocks hi3516cv300_sysctrl_clks = {
+ .nr = HI3516CV300_SYSCTRL_NR_CLKS,
+ .mux_clks = hi3516cv300_sysctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
};
static const struct of_device_id hi3516cv300_crg_match_table[] = {
{
.compatible = "hisilicon,hi3516cv300-crg",
- .data = &hi3516cv300_crg_funcs
+ .data = &hi3516cv300_crg_clks,
},
{
.compatible = "hisilicon,hi3516cv300-sysctrl",
- .data = &hi3516cv300_sysctrl_funcs
+ .data = &hi3516cv300_sysctrl_clks,
},
{ }
};
MODULE_DEVICE_TABLE(of, hi3516cv300_crg_match_table);
-static int hi3516cv300_crg_probe(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg;
-
- crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
- if (!crg)
- return -ENOMEM;
-
- crg->funcs = of_device_get_match_data(&pdev->dev);
- if (!crg->funcs)
- return -ENOENT;
-
- crg->rstc = hisi_reset_init(pdev);
- if (!crg->rstc)
- return -ENOMEM;
-
- crg->clk_data = crg->funcs->register_clks(pdev);
- if (IS_ERR(crg->clk_data)) {
- hisi_reset_exit(crg->rstc);
- return PTR_ERR(crg->clk_data);
- }
-
- platform_set_drvdata(pdev, crg);
- return 0;
-}
-
-static void hi3516cv300_crg_remove(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- hisi_reset_exit(crg->rstc);
- crg->funcs->unregister_clks(pdev);
-}
-
static struct platform_driver hi3516cv300_crg_driver = {
- .probe = hi3516cv300_crg_probe,
- .remove = hi3516cv300_crg_remove,
+ .probe = hisi_crg_probe,
+ .remove = hisi_crg_remove,
.driver = {
.name = "hi3516cv300-crg",
.of_match_table = hi3516cv300_crg_match_table,
},
};
-static int __init hi3516cv300_crg_init(void)
-{
- return platform_driver_register(&hi3516cv300_crg_driver);
-}
-core_initcall(hi3516cv300_crg_init);
-
-static void __exit hi3516cv300_crg_exit(void)
-{
- platform_driver_unregister(&hi3516cv300_crg_driver);
-}
-module_exit(hi3516cv300_crg_exit);
+module_platform_driver(hi3516cv300_crg_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("HiSilicon Hi3516CV300 CRG Driver");
@@ -0,0 +1,627 @@
--- /dev/null
+++ b/drivers/clk/hisilicon/crg-hi3798.c
@@ -0,0 +1,624 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hi3798 Clock and Reset Generator Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ */
+
+#include <dt-bindings/clock/histb-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "crg.h"
+
+/* hi3798 core CRG */
+#define HI3798_INNER_CLK_OFFSET 128
+#define HI3798_FIXED_24M (HI3798_INNER_CLK_OFFSET + 00)
+#define HI3798_FIXED_25M (HI3798_INNER_CLK_OFFSET + 01)
+#define HI3798_FIXED_50M (HI3798_INNER_CLK_OFFSET + 02)
+#define HI3798_FIXED_75M (HI3798_INNER_CLK_OFFSET + 03)
+#define HI3798_FIXED_100M (HI3798_INNER_CLK_OFFSET + 04)
+#define HI3798_FIXED_150M (HI3798_INNER_CLK_OFFSET + 05)
+#define HI3798_FIXED_200M (HI3798_INNER_CLK_OFFSET + 06)
+#define HI3798_FIXED_250M (HI3798_INNER_CLK_OFFSET + 07)
+#define HI3798_FIXED_300M (HI3798_INNER_CLK_OFFSET + 08)
+#define HI3798_FIXED_400M (HI3798_INNER_CLK_OFFSET + 09)
+#define HI3798_MMC_MUX (HI3798_INNER_CLK_OFFSET + 10)
+#define HI3798_ETH_PUB_CLK (HI3798_INNER_CLK_OFFSET + 11)
+#define HI3798_ETH_BUS_CLK (HI3798_INNER_CLK_OFFSET + 12)
+#define HI3798_ETH_BUS0_CLK (HI3798_INNER_CLK_OFFSET + 13)
+#define HI3798_ETH_BUS1_CLK (HI3798_INNER_CLK_OFFSET + 14)
+#define HI3798_COMBPHY1_MUX (HI3798_INNER_CLK_OFFSET + 15)
+#define HI3798_FIXED_12M (HI3798_INNER_CLK_OFFSET + 16)
+#define HI3798_FIXED_48M (HI3798_INNER_CLK_OFFSET + 17)
+#define HI3798_FIXED_60M (HI3798_INNER_CLK_OFFSET + 18)
+#define HI3798_FIXED_166P5M (HI3798_INNER_CLK_OFFSET + 19)
+#define HI3798_SDIO0_MUX (HI3798_INNER_CLK_OFFSET + 20)
+#define HI3798_COMBPHY0_MUX (HI3798_INNER_CLK_OFFSET + 21)
+#define HI3798_FIXED_3M (HI3798_INNER_CLK_OFFSET + 22)
+#define HI3798_FIXED_15M (HI3798_INNER_CLK_OFFSET + 23)
+#define HI3798_FIXED_83P3M (HI3798_INNER_CLK_OFFSET + 24)
+
+#define HI3798_CRG_NR_CLKS 256
+
+#define HI3798_SYSCTRL_NR_CLKS 16
+static const struct hisi_fixed_rate_clock hi3798_fixed_rate_clks[] = {
+ { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
+ { HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
+ { HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
+ { HI3798_FIXED_3M, "3m", NULL, 0, 3000000, },
+ { HI3798_FIXED_12M, "12m", NULL, 0, 12000000, },
+ { HI3798_FIXED_15M, "15m", NULL, 0, 15000000, },
+ { HI3798_FIXED_24M, "24m", NULL, 0, 24000000, },
+ { HI3798_FIXED_25M, "25m", NULL, 0, 25000000, },
+ { HI3798_FIXED_48M, "48m", NULL, 0, 48000000, },
+ { HI3798_FIXED_50M, "50m", NULL, 0, 50000000, },
+ { HI3798_FIXED_60M, "60m", NULL, 0, 60000000, },
+ { HI3798_FIXED_75M, "75m", NULL, 0, 75000000, },
+ { HI3798_FIXED_83P3M, "83p3m", NULL, 0, 83333333, },
+ { HI3798_FIXED_100M, "100m", NULL, 0, 100000000, },
+ { HI3798_FIXED_150M, "150m", NULL, 0, 150000000, },
+ { HI3798_FIXED_166P5M, "166p5m", NULL, 0, 165000000, },
+ { HI3798_FIXED_200M, "200m", NULL, 0, 200000000, },
+ { HI3798_FIXED_250M, "250m", NULL, 0, 250000000, },
+};
+
+struct hi3798_complex_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long offset;
+ u32 mask;
+ u32 value;
+};
+
+struct hi3798_clk_complex {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u32 mask;
+ u32 value;
+};
+
+#define to_complex_clk(_hw) container_of(_hw, struct hi3798_clk_complex, hw)
+
+static int hi3798_clk_complex_prepare(struct clk_hw *hw)
+{
+ struct hi3798_clk_complex *clk = to_complex_clk(hw);
+ u32 val;
+
+ val = readl_relaxed(clk->reg);
+ val &= ~(clk->mask);
+ val |= clk->value;
+ writel_relaxed(val, clk->reg);
+
+ return 0;
+}
+
+static void hi3798_clk_complex_unprepare(struct clk_hw *hw)
+{
+ struct hi3798_clk_complex *clk = to_complex_clk(hw);
+ u32 val;
+
+ val = readl_relaxed(clk->reg);
+ val &= ~(clk->mask);
+ writel_relaxed(val, clk->reg);
+}
+
+static int hi3798_clk_complex_is_prepared(struct clk_hw *hw)
+{
+ struct hi3798_clk_complex *clk = to_complex_clk(hw);
+ u32 val;
+
+ val = readl_relaxed(clk->reg);
+ return (val & clk->mask) == clk->value;
+}
+
+static const struct clk_ops hi3798_clk_complex_ops = {
+ .prepare = hi3798_clk_complex_prepare,
+ .unprepare = hi3798_clk_complex_unprepare,
+ .is_prepared = hi3798_clk_complex_is_prepared,
+};
+
+static int hi3798_clk_register_complex(struct device *dev,
+ const void *clocks, size_t num,
+ struct hisi_clock_data *data)
+{
+ const struct hi3798_complex_clock *clks = clocks;
+ void __iomem *base = data->base;
+
+ for (int i = 0; i < num; i++) {
+ struct hi3798_clk_complex *p_clk;
+ struct clk_init_data init;
+ int ret;
+
+ p_clk = devm_kzalloc(dev, sizeof(*p_clk), GFP_KERNEL);
+ if (!p_clk)
+ return -ENOMEM;
+
+ init.name = clks[i].name;
+ init.ops = &hi3798_clk_complex_ops;
+
+ init.flags = 0;
+ init.parent_names =
+ (clks[i].parent_name ? &clks[i].parent_name : NULL);
+ init.num_parents = (clks[i].parent_name ? 1 : 0);
+
+ p_clk->reg = base + clks[i].offset;
+ p_clk->mask = clks[i].mask;
+ p_clk->value = clks[i].value;
+ p_clk->hw.init = &init;
+
+ ret = devm_clk_hw_register(dev, &p_clk->hw);
+ if (ret) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ return ret;
+ }
+
+ data->clk_data->hws[clks[i].id] = &p_clk->hw;
+ }
+
+ return 0;
+}
+
+/* hi3798CV200 */
+
+static const char *const hi3798cv200_mmc_mux_p[] = {
+ "100m", "50m", "25m", "200m", "150m" };
+static u32 hi3798cv200_mmc_mux_table[] = {0, 1, 2, 3, 6};
+
+static const char *const hi3798cv200_comphy_mux_p[] = {
+ "100m", "25m"};
+static u32 hi3798cv200_comphy_mux_table[] = {2, 3};
+
+static const char *const hi3798cv200_sdio_mux_p[] = {
+ "100m", "50m", "150m", "166p5m" };
+static u32 hi3798cv200_sdio_mux_table[] = {0, 1, 2, 3};
+
+static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
+ { HI3798_MMC_MUX, "mmc_mux", hi3798cv200_mmc_mux_p,
+ ARRAY_SIZE(hi3798cv200_mmc_mux_p), CLK_SET_RATE_PARENT,
+ 0xa0, 8, 3, 0, hi3798cv200_mmc_mux_table, },
+ { HI3798_COMBPHY0_MUX, "combphy0_mux", hi3798cv200_comphy_mux_p,
+ ARRAY_SIZE(hi3798cv200_comphy_mux_p), CLK_SET_RATE_PARENT,
+ 0x188, 2, 2, 0, hi3798cv200_comphy_mux_table, },
+ { HI3798_COMBPHY1_MUX, "combphy1_mux", hi3798cv200_comphy_mux_p,
+ ARRAY_SIZE(hi3798cv200_comphy_mux_p), CLK_SET_RATE_PARENT,
+ 0x188, 10, 2, 0, hi3798cv200_comphy_mux_table, },
+ { HI3798_SDIO0_MUX, "sdio0_mux", hi3798cv200_sdio_mux_p,
+ ARRAY_SIZE(hi3798cv200_sdio_mux_p), CLK_SET_RATE_PARENT,
+ 0x9c, 8, 2, 0, hi3798cv200_sdio_mux_table, },
+};
+
+static u32 mmc_phase_regvals[] = {0, 1, 2, 3, 4, 5, 6, 7};
+static u32 mmc_phase_degrees[] = {0, 45, 90, 135, 180, 225, 270, 315};
+
+static struct hisi_phase_clock hi3798cv200_phase_clks[] = {
+ { HISTB_MMC_SAMPLE_CLK, "mmc_sample", "clk_mmc_ciu",
+ CLK_SET_RATE_PARENT, 0xa0, 12, 3, mmc_phase_degrees,
+ mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
+ { HISTB_MMC_DRV_CLK, "mmc_drive", "clk_mmc_ciu",
+ CLK_SET_RATE_PARENT, 0xa0, 16, 3, mmc_phase_degrees,
+ mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
+};
+
+static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
+ /* UART */
+ { HISTB_UART2_CLK, "clk_uart2", "75m",
+ CLK_SET_RATE_PARENT, 0x68, 4, 0, },
+ /* I2C */
+ { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
+ { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
+ { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
+ { HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 16, 0, },
+ { HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 20, 0, },
+ /* SPI */
+ { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x70, 0, 0, },
+ /* SDIO */
+ { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
+ CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
+ { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",
+ CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
+ /* EMMC */
+ { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
+ CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
+ { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
+ CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
+ /* PCIE*/
+ { HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
+ CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
+ { HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
+ CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
+ { HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
+ CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
+ { HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
+ CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
+ /* Ethernet */
+ { HI3798_ETH_PUB_CLK, "clk_pub", NULL,
+ CLK_SET_RATE_PARENT, 0xcc, 5, 0, },
+ { HI3798_ETH_BUS_CLK, "clk_bus", "clk_pub",
+ CLK_SET_RATE_PARENT, 0xcc, 0, 0, },
+ { HI3798_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",
+ CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
+ { HI3798_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",
+ CLK_SET_RATE_PARENT, 0xcc, 2, 0, },
+ { HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",
+ CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
+ { HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",
+ CLK_SET_RATE_PARENT, 0xcc, 24, 0, },
+ { HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",
+ CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
+ { HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
+ CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
+ /* COMBPHY0 */
+ { HISTB_COMBPHY0_CLK, "clk_combphy0", "combphy0_mux",
+ CLK_SET_RATE_PARENT, 0x188, 0, 0, },
+ /* COMBPHY1 */
+ { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
+ CLK_SET_RATE_PARENT, 0x188, 8, 0, },
+ /* USB2 */
+ { HISTB_USB2_BUS_CLK, "clk_u2_bus", "clk_ahb",
+ CLK_SET_RATE_PARENT, 0xb8, 0, 0, },
+ { HISTB_USB2_PHY_CLK, "clk_u2_phy", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 4, 0, },
+ { HISTB_USB2_12M_CLK, "clk_u2_12m", "12m",
+ CLK_SET_RATE_PARENT, 0xb8, 2, 0 },
+ { HISTB_USB2_48M_CLK, "clk_u2_48m", "48m",
+ CLK_SET_RATE_PARENT, 0xb8, 1, 0 },
+ { HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 5, 0 },
+ { HISTB_USB2_OTG_UTMI_CLK, "clk_u2_otg_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 3, 0 },
+ { HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",
+ CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
+ { HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
+ CLK_SET_RATE_PARENT, 0xbc, 2, 0 },
+ /* USB3 */
+ { HISTB_USB3_BUS_CLK, "clk_u3_bus", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 0, 0 },
+ { HISTB_USB3_UTMI_CLK, "clk_u3_utmi", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 4, 0 },
+ { HISTB_USB3_PIPE_CLK, "clk_u3_pipe", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 3, 0 },
+ { HISTB_USB3_SUSPEND_CLK, "clk_u3_suspend", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 2, 0 },
+ { HISTB_USB3_BUS_CLK1, "clk_u3_bus1", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 16, 0 },
+ { HISTB_USB3_UTMI_CLK1, "clk_u3_utmi1", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 20, 0 },
+ { HISTB_USB3_PIPE_CLK1, "clk_u3_pipe1", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 19, 0 },
+ { HISTB_USB3_SUSPEND_CLK1, "clk_u3_suspend1", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 18, 0 },
+};
+
+static const struct hisi_clocks hi3798cv200_crg_clks = {
+ .nr = HI3798_CRG_NR_CLKS,
+ .fixed_rate_clks = hi3798_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3798_fixed_rate_clks),
+ .mux_clks = hi3798cv200_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3798cv200_mux_clks),
+ .phase_clks = hi3798cv200_phase_clks,
+ .phase_clks_num = ARRAY_SIZE(hi3798cv200_phase_clks),
+ .gate_clks = hi3798cv200_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798cv200_gate_clks),
+};
+
+static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
+ { HISTB_IR_CLK, "clk_ir", "24m",
+ CLK_SET_RATE_PARENT, 0x48, 4, 0, },
+ { HISTB_TIMER01_CLK, "clk_timer01", "24m",
+ CLK_SET_RATE_PARENT, 0x48, 6, 0, },
+ { HISTB_UART0_CLK, "clk_uart0", "75m",
+ CLK_SET_RATE_PARENT, 0x48, 10, 0, },
+};
+
+static const struct hisi_clocks hi3798cv200_sysctrl_clks = {
+ .nr = HI3798_SYSCTRL_NR_CLKS,
+ .gate_clks = hi3798cv200_sysctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+};
+
+/* hi3798MV100 */
+
+static const char *const hi3798mv100_mmc_mux_p[] = {
+ "75m", "100m", "50m", "15m" };
+static u32 hi3798mv100_mmc_mux_table[] = {0, 1, 2, 3};
+
+static struct hisi_mux_clock hi3798mv100_mux_clks[] = {
+ { HI3798_MMC_MUX, "mmc_mux", hi3798mv100_mmc_mux_p,
+ ARRAY_SIZE(hi3798mv100_mmc_mux_p), CLK_SET_RATE_PARENT,
+ 0xa0, 8, 2, 0, hi3798mv100_mmc_mux_table, },
+ { HI3798_SDIO0_MUX, "sdio0_mux", hi3798mv100_mmc_mux_p,
+ ARRAY_SIZE(hi3798mv100_mmc_mux_p), CLK_SET_RATE_PARENT,
+ 0x9c, 8, 2, 0, hi3798mv100_mmc_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3798mv100_gate_clks[] = {
+ /* NAND */
+ /* hi3798MV100 NAND driver does not get into mainline yet,
+ * expose these clocks when it gets ready */
+ /* { HISTB_NAND_CLK, "clk_nand", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x60, 0, 0, }, */
+ /* UART */
+ { HISTB_UART1_CLK, "clk_uart1", "3m",
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0x68, 0, 0, },
+ { HISTB_UART2_CLK, "clk_uart2", "83p3m",
+ CLK_SET_RATE_PARENT, 0x68, 4, 0, },
+ /* I2C */
+ { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
+ { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
+ { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
+ /* SPI */
+ { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x70, 0, 0, },
+ /* SDIO */
+ { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
+ CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
+ { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",
+ CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
+ /* EMMC */
+ { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
+ CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
+ { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
+ CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
+ /* DMAC */
+ { HISTB_DMAC_CLK, "clk_dmac", "clk_ahb",
+ CLK_SET_RATE_PARENT, 0xa4, 0, 0, },
+ /* USB2 */
+ { HISTB_USB2_BUS_CLK, "clk_u2_bus", "clk_ahb",
+ CLK_SET_RATE_PARENT, 0xb8, 0, 0, },
+ { HISTB_USB2_PHY_CLK, "clk_u2_phy", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 4, 0, },
+ { HISTB_USB2_12M_CLK, "clk_u2_12m", "12m",
+ CLK_SET_RATE_PARENT, 0xb8, 2, 0 },
+ { HISTB_USB2_48M_CLK, "clk_u2_48m", "48m",
+ CLK_SET_RATE_PARENT, 0xb8, 1, 0 },
+ { HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 5, 0 },
+ { HISTB_USB2_UTMI_CLK1, "clk_u2_utmi1", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 6, 0 },
+ { HISTB_USB2_OTG_UTMI_CLK, "clk_u2_otg_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 3, 0 },
+ { HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",
+ CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
+ { HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
+ CLK_SET_RATE_PARENT, 0xbc, 2, 0 },
+ /* USB2 2 */
+ { HISTB_USB2_2_BUS_CLK, "clk_u2_2_bus", "clk_ahb",
+ CLK_SET_RATE_PARENT, 0x198, 0, 0, },
+ { HISTB_USB2_2_PHY_CLK, "clk_u2_2_phy", "60m",
+ CLK_SET_RATE_PARENT, 0x198, 4, 0, },
+ { HISTB_USB2_2_12M_CLK, "clk_u2_2_12m", "12m",
+ CLK_SET_RATE_PARENT, 0x198, 2, 0 },
+ { HISTB_USB2_2_48M_CLK, "clk_u2_2_48m", "48m",
+ CLK_SET_RATE_PARENT, 0x198, 1, 0 },
+ { HISTB_USB2_2_UTMI_CLK, "clk_u2_2_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0x198, 5, 0 },
+ { HISTB_USB2_2_UTMI_CLK1, "clk_u2_2_utmi1", "60m",
+ CLK_SET_RATE_PARENT, 0x198, 6, 0 },
+ { HISTB_USB2_2_OTG_UTMI_CLK, "clk_u2_2_otg_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0x198, 3, 0 },
+ { HISTB_USB2_2_PHY1_REF_CLK, "clk_u2_2_phy1_ref", "24m",
+ CLK_SET_RATE_PARENT, 0x190, 0, 0 },
+ { HISTB_USB2_2_PHY2_REF_CLK, "clk_u2_2_phy2_ref", "24m",
+ CLK_SET_RATE_PARENT, 0x190, 2, 0 },
+ /* USB3 */
+ { HISTB_USB3_BUS_CLK, "clk_u3_bus", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 0, 0 },
+ { HISTB_USB3_UTMI_CLK, "clk_u3_utmi", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 4, 0 },
+ { HISTB_USB3_PIPE_CLK, "clk_u3_pipe", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 3, 0 },
+ { HISTB_USB3_SUSPEND_CLK, "clk_u3_suspend", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 2, 0 },
+ /* GPU */
+ { HISTB_GPU_BUS_CLK, "clk_gpu", "200m",
+ CLK_SET_RATE_PARENT, 0xd4, 0, 0 },
+ /* FEPHY */
+ { HISTB_FEPHY_CLK, "clk_fephy", "25m",
+ CLK_SET_RATE_PARENT, 0x120, 0, 0, },
+};
+
+static const struct hi3798_complex_clock hi3798mv100_complex_clks[] = {
+ { HISTB_ETH0_MAC_CLK, "clk_mac0", NULL,
+ CLK_SET_RATE_PARENT, 0xcc, 0xf, 0xb, },
+ { HISTB_GPU_CORE_CLK, "clk_gpu_gp", "200m",
+ CLK_SET_RATE_PARENT, 0xd4, 0x700, 0x700, },
+};
+
+static const struct hisi_clocks hi3798mv100_crg_clks = {
+ .nr = HI3798_CRG_NR_CLKS,
+ .fixed_rate_clks = hi3798_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3798_fixed_rate_clks),
+ .gate_clks = hi3798mv100_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798mv100_gate_clks),
+ .mux_clks = hi3798mv100_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3798mv100_mux_clks),
+ .phase_clks = hi3798cv200_phase_clks,
+ .phase_clks_num = ARRAY_SIZE(hi3798cv200_phase_clks),
+ .customized_clks = hi3798mv100_complex_clks,
+ .customized_clks_num = ARRAY_SIZE(hi3798mv100_complex_clks),
+ .clk_register_customized = hi3798_clk_register_complex,
+};
+
+static const struct hisi_gate_clock hi3798mv100_sysctrl_gate_clks[] = {
+ { HISTB_IR_CLK, "clk_ir", "24m",
+ CLK_SET_RATE_PARENT, 0x48, 4, 0, },
+ { HISTB_TIMER01_CLK, "clk_timer01", "24m",
+ CLK_SET_RATE_PARENT, 0x48, 6, 0, },
+ { HISTB_UART0_CLK, "clk_uart0", "83p3m",
+ CLK_SET_RATE_PARENT, 0x48, 12, 0, },
+};
+
+static const struct hisi_clocks hi3798mv100_sysctrl_clks = {
+ .nr = HI3798_SYSCTRL_NR_CLKS,
+ .gate_clks = hi3798mv100_sysctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798mv100_sysctrl_gate_clks),
+};
+
+/* hi3798MV200 */
+
+static struct hisi_mux_clock hi3798mv200_mux_clks[] = {
+ { HI3798_MMC_MUX, "mmc_mux", hi3798cv200_mmc_mux_p,
+ ARRAY_SIZE(hi3798cv200_mmc_mux_p), CLK_SET_RATE_PARENT,
+ 0xa0, 8, 3, 0, hi3798cv200_mmc_mux_table, },
+ { HI3798_COMBPHY0_MUX, "combphy0_mux", hi3798cv200_comphy_mux_p,
+ ARRAY_SIZE(hi3798cv200_comphy_mux_p), CLK_SET_RATE_PARENT,
+ 0x188, 3, 1, 0, hi3798cv200_comphy_mux_table, },
+ { HI3798_SDIO0_MUX, "sdio0_mux", hi3798cv200_sdio_mux_p,
+ ARRAY_SIZE(hi3798cv200_sdio_mux_p), CLK_SET_RATE_PARENT,
+ 0x9c, 8, 2, 0, hi3798cv200_sdio_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3798mv200_gate_clks[] = {
+ /* UART */
+ { HISTB_UART2_CLK, "clk_uart2", "75m",
+ CLK_SET_RATE_PARENT, 0x68, 4, 0, },
+ /* I2C */
+ { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
+ { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
+ { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
+ /* SPI */
+ { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
+ CLK_SET_RATE_PARENT, 0x70, 0, 0, },
+ /* SDIO */
+ { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
+ CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
+ { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",
+ CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
+ /* EMMC */
+ { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
+ CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
+ { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
+ CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
+ { HISTB_MMC_SAP_DLL_MODE_CLK, "clk_mmc_sap_dll_mode", "mmc_sample",
+ CLK_SET_RATE_PARENT, 0x39c, 16, 0, },
+ /* PCIE*/
+ { HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
+ CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
+ { HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
+ CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
+ { HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
+ CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
+ { HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
+ CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
+ /* GSF */
+ { HISTB_ETH0_MAC_CLK, "clk_gsf", NULL,
+ CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
+ { HISTB_ETH0_MACIF_CLK, "clk_gmac", "clk_gsf",
+ CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
+ /* FEPHY */
+ { HISTB_FEPHY_CLK, "clk_fephy", NULL,
+ CLK_SET_RATE_PARENT, 0x388, 0, 0, },
+ /* COMBPHY */
+ { HISTB_COMBPHY0_CLK, "clk_combphy0", "combphy0_mux",
+ CLK_SET_RATE_PARENT, 0x188, 0, 0, },
+ /* USB2 */
+ { HISTB_USB2_BUS_CLK, "clk_u2_bus", "clk_ahb",
+ CLK_SET_RATE_PARENT, 0xb8, 0, 0, },
+ { HISTB_USB2_PHY_CLK, "clk_u2_phy", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 4, 0, },
+ { HISTB_USB2_12M_CLK, "clk_u2_12m", "12m",
+ CLK_SET_RATE_PARENT, 0xb8, 2, 0 },
+ { HISTB_USB2_48M_CLK, "clk_u2_48m", "48m",
+ CLK_SET_RATE_PARENT, 0xb8, 1, 0 },
+ { HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 5, 0 },
+ { HISTB_USB2_OTG_UTMI_CLK, "clk_u2_otg_utmi", "60m",
+ CLK_SET_RATE_PARENT, 0xb8, 3, 0 },
+ { HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",
+ CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
+ { HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
+ CLK_SET_RATE_PARENT, 0xbc, 2, 0 },
+ /* USB3 */
+ { HISTB_USB3_BUS_CLK, "clk_u3_bus", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 0, 0 },
+ { HISTB_USB3_UTMI_CLK, "clk_u3_utmi", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 4, 0 },
+ { HISTB_USB3_PIPE_CLK, "clk_u3_pipe", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 3, 0 },
+ { HISTB_USB3_SUSPEND_CLK, "clk_u3_suspend", NULL,
+ CLK_SET_RATE_PARENT, 0xb0, 2, 0 },
+};
+
+static const struct hi3798_complex_clock hi3798mv200_complex_clks[] = {
+ { HISTB_ETH1_MAC_CLK, "clk_mac0", NULL,
+ CLK_SET_RATE_PARENT, 0xd0, 0xf, 0xb, },
+};
+
+static const struct hisi_clocks hi3798mv200_crg_clks = {
+ .nr = HI3798_CRG_NR_CLKS,
+ .fixed_rate_clks = hi3798_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3798_fixed_rate_clks),
+ .gate_clks = hi3798mv200_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798mv200_gate_clks),
+ .mux_clks = hi3798mv200_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3798mv200_mux_clks),
+ .phase_clks = hi3798cv200_phase_clks,
+ .phase_clks_num = ARRAY_SIZE(hi3798cv200_phase_clks),
+ .customized_clks = hi3798mv200_complex_clks,
+ .customized_clks_num = ARRAY_SIZE(hi3798mv200_complex_clks),
+ .clk_register_customized = hi3798_clk_register_complex,
+};
+
+static const struct hisi_gate_clock hi3798mv200_sysctrl_gate_clks[] = {
+ { HISTB_IR_CLK, "clk_ir", "24m",
+ CLK_SET_RATE_PARENT, 0x48, 4, 0, },
+ { HISTB_TIMER01_CLK, "clk_timer01", "24m",
+ CLK_SET_RATE_PARENT, 0x48, 6, 0, },
+ { HISTB_UART0_CLK, "clk_uart0", "75m",
+ CLK_SET_RATE_PARENT, 0x48, 12, 0, },
+};
+
+static const struct hisi_clocks hi3798mv200_sysctrl_clks = {
+ .nr = HI3798_SYSCTRL_NR_CLKS,
+ .gate_clks = hi3798mv200_sysctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798mv200_sysctrl_gate_clks),
+};
+
+static const struct of_device_id hi3798_crg_match_table[] = {
+ { .compatible = "hisilicon,hi3798cv200-crg",
+ .data = &hi3798cv200_crg_clks },
+ { .compatible = "hisilicon,hi3798cv200-sysctrl",
+ .data = &hi3798cv200_sysctrl_clks },
+ { .compatible = "hisilicon,hi3798mv100-crg",
+ .data = &hi3798mv100_crg_clks },
+ { .compatible = "hisilicon,hi3798mv100-sysctrl",
+ .data = &hi3798mv100_sysctrl_clks },
+ { .compatible = "hisilicon,hi3798mv200-crg",
+ .data = &hi3798mv200_crg_clks },
+ { .compatible = "hisilicon,hi3798mv200-sysctrl",
+ .data = &hi3798mv200_sysctrl_clks },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hi3798_crg_match_table);
+
+static struct platform_driver hi3798_crg_driver = {
+ .probe = hisi_crg_probe,
+ .remove = hisi_crg_remove,
+ .driver = {
+ .name = "hi3798-crg",
+ .of_match_table = hi3798_crg_match_table,
+ },
+};
+
+module_platform_driver(hi3798_crg_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3798 CRG Driver");
@@ -0,0 +1,23 @@
--- a/drivers/clk/hisilicon/crg.h
+++ b/drivers/clk/hisilicon/crg.h
@@ -11,15 +11,14 @@
struct hisi_clock_data;
struct hisi_reset_controller;
-struct hisi_crg_funcs {
- struct hisi_clock_data* (*register_clks)(struct platform_device *pdev);
- void (*unregister_clks)(struct platform_device *pdev);
-};
-
struct hisi_crg_dev {
struct hisi_clock_data *clk_data;
struct hisi_reset_controller *rstc;
- const struct hisi_crg_funcs *funcs;
};
+/* helper functions for platform driver */
+
+int hisi_crg_probe(struct platform_device *pdev);
+void hisi_crg_remove(struct platform_device *pdev);
+
#endif /* __HISI_CRG_H */
@@ -0,0 +1,19 @@
--- a/drivers/clk/hisilicon/Kconfig
+++ b/drivers/clk/hisilicon/Kconfig
@@ -37,13 +37,13 @@ config COMMON_CLK_HI3670
help
Build the clock driver for hi3670.
-config COMMON_CLK_HI3798CV200
- tristate "Hi3798CV200 Clock Driver"
+config COMMON_CLK_HI3798
+ tristate "Hi3798 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
select RESET_HISI
default ARCH_HISI
help
- Build the clock driver for hi3798cv200.
+ Build the clock driver for hi3798.
config COMMON_CLK_HI6220
bool "Hi6220 Clock Driver"
@@ -0,0 +1,11 @@
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_COMMON_CLK_HI3519) += clk-h
obj-$(CONFIG_COMMON_CLK_HI3559A) += clk-hi3559a.o
obj-$(CONFIG_COMMON_CLK_HI3660) += clk-hi3660.o
obj-$(CONFIG_COMMON_CLK_HI3670) += clk-hi3670.o
-obj-$(CONFIG_COMMON_CLK_HI3798CV200) += crg-hi3798cv200.o
+obj-$(CONFIG_COMMON_CLK_HI3798) += crg-hi3798.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
obj-$(CONFIG_RESET_HISI) += reset.o
obj-$(CONFIG_STUB_CLK_HI6220) += clk-hi6220-stub.o
@@ -0,0 +1,60 @@
--- a/drivers/clk/hisilicon/reset.c
+++ b/drivers/clk/hisilicon/reset.c
@@ -6,11 +6,15 @@
*/
#include <linux/io.h>
+#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+
+#include "clk.h"
+#include "crg.h"
#include "reset.h"
#define HISI_RESET_BIT_MASK 0x1f
@@ -116,3 +120,41 @@ void hisi_reset_exit(struct hisi_reset_c
reset_controller_unregister(&rstc->rcdev);
}
EXPORT_SYMBOL_GPL(hisi_reset_exit);
+
+int hisi_crg_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct hisi_crg_dev *crg;
+ int ret;
+
+ crg = devm_kmalloc(dev, sizeof(*crg), GFP_KERNEL);
+ if (!crg)
+ return -ENOMEM;
+
+ ret = hisi_clk_probe(pdev);
+ if (ret)
+ return ret;
+
+ crg->rstc = hisi_reset_init(pdev);
+ if (!crg->rstc) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, crg);
+ return 0;
+
+err:
+ hisi_clk_remove(pdev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_crg_probe);
+
+void hisi_crg_remove(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ hisi_reset_exit(crg->rstc);
+ hisi_clk_remove(pdev);
+}
+EXPORT_SYMBOL_GPL(hisi_crg_remove);
@@ -0,0 +1,11 @@
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -102,7 +102,7 @@ obj-$(CONFIG_CLK_BAIKAL_T1) += baikal-t
obj-y += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
-obj-$(CONFIG_ARCH_HISI) += hisilicon/
+obj-y += hisilicon/
obj-y += imgtec/
obj-y += imx/
obj-y += ingenic/
@@ -0,0 +1,724 @@
--- /dev/null
+++ b/drivers/crypto/hisilicon/advca/hisi-advca-sha.c
@@ -0,0 +1,721 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * SHA - hash device for SHA1/2
+ *
+ * Copyright (c) 2024 David Yang
+ */
+
+#include <crypto/internal/hash.h>
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/string.h>
+
+/******** hardware definitions ********/
+
+#define SHA_TOTAL_LEN_LOW 0x00
+#define SHA_TOTAL_LEN_HIGH 0x04
+#define SHA_STATUS 0x08
+#define SHA_HASH_READY BIT(0)
+#define SHA_DMA_READY BIT(1)
+#define SHA_MSG_READY BIT(2)
+#define SHA_RECORD_READY BIT(3)
+#define SHA_ERR_STATE GENMASK(5, 4)
+#define SHA_LEN_ERR BIT(6)
+#define SHA_CTRL 0x0c
+#define SHA_CTRL_SINGLE_READ BIT(0)
+#define SHA_CTRL_ALG GENMASK(2, 1)
+#define SHA_ALG_SHA1 0
+#define SHA_ALG_SHA256 1
+#define SHA_ALG_SHA224 5
+#define SHA_CTRL_HMAC BIT(3)
+#define SHA_CTRL_KEY_FROM_MKL BIT(4) /* key from (not directly accessible) Machine Key Ladder (DRM) */
+#define SHA_CTRL_ENDIAN BIT(5) /* misleading reg; always set it */
+#define SHA_CTRL_USED_BY_ARM BIT(6) /* v1 only */
+#define SHA_CTRL_USED_BY_C51 BIT(7) /* v1 only */
+#define SHA_CTRL_SET_INIT BIT(6) /* v2 only; use designated initial status */
+#define SHA_START 0x10
+#define SHA_START_BIT BIT(0)
+#define SHA_DMA_ADDR 0x14
+#define SHA_DMA_LEN 0x18
+#define SHA_DATA_IN 0x1c
+#define SHA_RECORD_LEN_LOW 0x20
+#define SHA_RECORD_LEN_HIGH 0x24
+#define SHA_OUT0 0x30 /* till 7 (0x4c) */
+#define SHA_MCU_KEY0 0x70 /* till 3 (0x7c) */
+#define SHA_KL_KEY0 0x80 /* till 3 (0x8c) */
+#define SHA_INIT0 0x90 /* till 7 (0xac) */
+
+#define SHA_KEY_SIZE 16u
+#define SHA_DIGEST_SIZE 32u
+#define SHA_BLOCK_SIZE 64u
+
+/******** driver definitions ********/
+
+#define SHA_TYPE_HASH 0
+/* untested; do test before actually using it */
+#define SHA_TYPE_MHASH 1
+
+struct hica_sha_ctrl {
+ unsigned int alg;
+};
+
+struct hica_sha_alg {
+ struct shash_alg alg;
+ struct hica_sha_ctrl ctrl;
+ struct hica_sha_priv *priv;
+};
+
+/* only used for driver registration */
+struct hica_sha_tmpl {
+ struct hica_sha_ctrl ctrl;
+
+ unsigned int digestsize;
+ unsigned int statesize;
+ unsigned int blocksize;
+
+ int (*update)(struct shash_desc *desc, const u8 *data,
+ unsigned int len);
+
+ const char *alg_name;
+};
+
+struct hica_sha_priv {
+ void __iomem *base;
+ struct device *dev;
+
+ struct reset_control *rst;
+ struct clk_bulk_data *clks;
+ unsigned int clks_n;
+
+ struct hica_sha_alg *algs;
+ unsigned int algs_n;
+
+ unsigned int type;
+ struct mutex lock;
+};
+
+struct hica_sha_tfm_ctx {
+ struct hica_sha_priv *priv;
+ struct hica_sha_ctrl ctrl;
+
+ unsigned int digestsize;
+ unsigned int blocksize;
+
+ struct crypto_shash *fallback;
+};
+
+struct hica_sha_desc_ctx {
+ bool bypass;
+
+ /* keep this at the end of struct! */
+ struct shash_desc fallback;
+};
+
+static unsigned int bypass_size = 16 * SHA_BLOCK_SIZE;
+module_param(bypass_size, uint, S_IRUGO | S_IWUSR);
+
+/******** reg ********/
+
+static int hica_sha_wait(const struct hica_sha_priv *priv, u32 mask,
+ bool nonblocking)
+{
+ u32 val;
+
+ if (nonblocking)
+ return readl_relaxed_poll_timeout_atomic(priv->base + SHA_STATUS,
+ val, val & mask,
+ USEC_PER_MSEC,
+ 500 * USEC_PER_MSEC);
+ else
+ return readl_relaxed_poll_timeout(priv->base + SHA_STATUS, val,
+ val & mask, USEC_PER_MSEC,
+ 500 * USEC_PER_MSEC);
+}
+
+static int hica_sha_record(const struct hica_sha_priv *priv, dma_addr_t addr,
+ unsigned int len, bool nonblocking)
+{
+ if (WARN_ON(addr & 3 || len & 3))
+ return -EINVAL;
+
+ if (hica_sha_wait(priv, SHA_RECORD_READY, nonblocking))
+ return -ETIMEDOUT;
+
+ writel_relaxed(addr, priv->base + SHA_DMA_ADDR);
+ writel(len, priv->base + SHA_DMA_LEN);
+ return 0;
+}
+
+/* must be called before setting SHA_START, and not for SHA_TYPE_HASH */
+static void hica_sha_import(const struct hica_sha_priv *priv, const void *state)
+{
+ for (unsigned int i = 0; i < SHA_DIGEST_SIZE; i += sizeof(u32))
+ writel_relaxed((__force __u32)
+ cpu_to_be32(*(const u32 *) (state + i)),
+ priv->base + SHA_INIT0 + i);
+}
+
+static int
+hica_sha_init(const struct hica_sha_priv *priv,
+ const struct hica_sha_ctrl *ctrl, bool imported, bool nonblocking)
+{
+ void __iomem *base = priv->base;
+
+ u32 val;
+ int ret;
+
+ /* re-enable SHA_START */
+ ret = reset_control_assert(priv->rst) ?:
+ reset_control_deassert(priv->rst);
+ if (ret)
+ return ret;
+
+ /* config SHA_CTRL */
+ val = readl_relaxed(base + SHA_CTRL);
+
+ val &= ~SHA_CTRL_SINGLE_READ;
+ val &= ~SHA_CTRL_ALG;
+ val |= (ctrl->alg << 1) & SHA_CTRL_ALG;
+ val &= ~SHA_CTRL_HMAC;
+ /* evil config; it is the endianness of every 4-byte input data */
+ val |= SHA_CTRL_ENDIAN;
+
+ if (priv->type == SHA_TYPE_HASH)
+ val |= SHA_CTRL_USED_BY_ARM;
+ else if (imported)
+ val |= SHA_CTRL_SET_INIT;
+
+ writel(val, base + SHA_CTRL);
+
+ /* check if we acquired SHA */
+ val = readl_relaxed(base + SHA_CTRL);
+ if (val & SHA_CTRL_USED_BY_C51)
+ return -EBUSY;
+
+ /* wait hardware ready */
+ if (hica_sha_wait(priv, SHA_HASH_READY, nonblocking))
+ return -ENODEV;
+
+ /* ask hardware to set internal state */
+ writel(SHA_START_BIT, base + SHA_START);
+
+ dev_dbg(priv->dev, "alg %u\n", ctrl->alg);
+ return 0;
+}
+
+static int hica_sha_update(const struct hica_sha_priv *priv, const void *data,
+ unsigned int len, bool nonblocking)
+{
+ struct device *dev = priv->dev;
+
+ bool inplace = !((uintptr_t) data & 3);
+ void *newbuf = NULL;
+ dma_addr_t addr;
+ int ret;
+
+ if (!len)
+ return 0;
+
+ if (WARN_ON(len % SHA_BLOCK_SIZE))
+ return -EINVAL;
+
+ /* hardware wants aligned data; check if we can use phyaddr directly */
+ if (inplace) {
+ addr = dma_map_single(dev, (void *) data, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, addr)) {
+ dev_err(dev, "error mapping src\n");
+ return -EIO;
+ }
+
+ inplace = !(addr & 3);
+ if (!inplace)
+ dma_unmap_single(dev, addr, len, DMA_TO_DEVICE);
+ }
+
+ /* if not, manually request an aligned space */
+ if (!inplace) {
+ newbuf = dma_alloc_attrs(dev, len, &addr,
+ nonblocking ? GFP_ATOMIC : GFP_KERNEL,
+ 0);
+ if (!newbuf)
+ return -ENOMEM;
+ memcpy(newbuf, data, len);
+ }
+
+ dma_sync_single_for_device(dev, addr, len, DMA_TO_DEVICE);
+ ret = hica_sha_record(priv, addr, len, nonblocking) ?:
+ hica_sha_wait(priv, SHA_RECORD_READY, nonblocking);
+
+ if (!newbuf)
+ dma_unmap_single(dev, addr, len, DMA_TO_DEVICE);
+ else {
+ memzero_explicit(newbuf, len);
+ dma_free_attrs(dev, len, newbuf, addr, 0);
+ }
+
+ dev_dbg(dev, "read %u\n", len);
+ return ret;
+}
+
+static int hica_sha_export(const struct hica_sha_priv *priv, void *out,
+ unsigned int digestsize)
+{
+ if (hica_sha_wait(priv, SHA_RECORD_READY, false))
+ return -ETIMEDOUT;
+
+ for (unsigned int i = 0; i < digestsize; i += sizeof(u32))
+ *(u32 *) (out + i) =
+ be32_to_cpu((__force __be32)
+ readl_relaxed(priv->base + SHA_OUT0 + i));
+
+ return 0;
+}
+
+/******** shash_alg ********/
+
+static int hica_sha_alg_init(struct shash_desc *desc)
+{
+ struct hica_sha_desc_ctx *dctx = shash_desc_ctx(desc);
+ struct hica_sha_tfm_ctx *ctx = crypto_shash_ctx(desc->tfm);
+
+ dctx->bypass = false;
+
+ dctx->fallback.tfm = ctx->fallback;
+ return crypto_shash_init(&dctx->fallback);
+}
+
+static int
+_hica_sha_alg_update(struct shash_desc *desc, const u8 *data, unsigned int len,
+ void *buf, u32 *state, u64 *count)
+{
+ struct hica_sha_desc_ctx *dctx = shash_desc_ctx(desc);
+ struct hica_sha_tfm_ctx *ctx = crypto_shash_ctx(desc->tfm);
+ struct hica_sha_priv *priv = ctx->priv;
+ struct device *dev = priv->dev;
+
+ unsigned int top;
+ unsigned int bottom;
+ int ret;
+
+ if (dctx->bypass || len < bypass_size)
+ /* use software directly */
+ goto fallback;
+
+ /* how much data has been processed? (struct sha*_state *)buf->count */
+ ret = crypto_shash_export(&dctx->fallback, buf);
+ if (ret)
+ return ret;
+
+ /* chop input data; hardware can only handle full blocks */
+ bottom = ALIGN(*count, ctx->blocksize);
+ top = ALIGN_DOWN(*count + len, ctx->blocksize);
+ /* try using acceleration */
+ if ((priv->type == SHA_TYPE_MHASH || !*count) && bottom < top &&
+ top - bottom >= bypass_size) {
+ unsigned int head_len = bottom - *count;
+ unsigned int body_len = top - bottom;
+
+ /* head: software */
+ if (head_len) {
+ ret = crypto_shash_update(&dctx->fallback, data,
+ head_len);
+ if (ret)
+ return ret;
+
+ data += head_len;
+ len -= head_len;
+ }
+
+ /* body: hardware */
+ do {
+ bool nonblocking = crypto_shash_get_flags(desc->tfm) &
+ CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ bool imported;
+
+ if (!bypass_size)
+ /* testing; force hardware */
+ mutex_lock(&priv->lock);
+ else if (!mutex_trylock(&priv->lock))
+ break;
+
+ if (head_len) {
+ ret = crypto_shash_export(&dctx->fallback, buf);
+ if (ret) {
+ mutex_unlock(&priv->lock);
+ return ret;
+ }
+ }
+
+ dev_dbg(dev, "before %llu\n", *count);
+ pm_runtime_get_sync(dev);
+
+ imported = priv->type == SHA_TYPE_MHASH && *count;
+ if (imported)
+ hica_sha_import(priv, state);
+ ret = hica_sha_init(priv, &ctx->ctrl, imported,
+ nonblocking) ?:
+ hica_sha_update(priv, data, body_len,
+ nonblocking) ?:
+ hica_sha_export(priv, state, ctx->digestsize);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ mutex_unlock(&priv->lock);
+ if (ret)
+ return ret;
+
+ *count += body_len;
+ dev_dbg(dev, "after %llu\n", *count);
+
+ ret = crypto_shash_import(&dctx->fallback, buf);
+ if (ret)
+ return ret;
+
+ data += body_len;
+ len -= body_len;
+ } while (0);
+
+ /* tail: software -> fallback */
+ }
+
+ if (priv->type != SHA_TYPE_MHASH)
+ dctx->bypass = true;
+
+fallback:
+ return crypto_shash_update(&dctx->fallback, data, len);
+}
+
+static int hica_sha_alg_update_sha1(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha1_state state;
+
+ return !len ? 0 : _hica_sha_alg_update(desc, data, len, &state,
+ state.state, &state.count);
+}
+
+static int hica_sha_alg_update_sha256(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha256_state state;
+
+ return !len ? 0 : _hica_sha_alg_update(desc, data, len, &state,
+ state.state, &state.count);
+}
+
+static int hica_sha_alg_final(struct shash_desc *desc, u8 *out)
+{
+ struct hica_sha_desc_ctx *dctx = shash_desc_ctx(desc);
+
+ return crypto_shash_final(&dctx->fallback, out);
+}
+
+static int hica_sha_alg_export(struct shash_desc *desc, void *out)
+{
+ struct hica_sha_desc_ctx *dctx = shash_desc_ctx(desc);
+
+ return crypto_shash_export(&dctx->fallback, out);
+}
+
+static int hica_sha_alg_import(struct shash_desc *desc, const void *in)
+{
+ struct hica_sha_desc_ctx *dctx = shash_desc_ctx(desc);
+ struct hica_sha_tfm_ctx *ctx = crypto_shash_ctx(desc->tfm);
+
+ dctx->bypass = false;
+
+ dctx->fallback.tfm = ctx->fallback;
+ return crypto_shash_import(&dctx->fallback, in);
+}
+
+static int hica_sha_alg_init_tfm(struct crypto_shash *tfm)
+{
+ struct hica_sha_tfm_ctx *ctx = crypto_shash_ctx(tfm);
+ struct hash_alg_common *halg =
+ __crypto_hash_alg_common(tfm->base.__crt_alg);
+ struct hica_sha_alg *p_alg = container_of(halg, typeof(*p_alg),
+ alg.halg);
+
+ /* copy parameters to avoid pointer hell */
+ ctx->digestsize = halg->digestsize;
+ ctx->blocksize = crypto_shash_blocksize(tfm);
+ if (ctx->digestsize > SHA_DIGEST_SIZE ||
+ ctx->blocksize > SHA_BLOCK_SIZE)
+ return -EINVAL;
+
+ ctx->fallback = crypto_alloc_shash(crypto_shash_alg_name(tfm), 0,
+ CRYPTO_ALG_ALLOCATES_MEMORY);
+ if (IS_ERR(ctx->fallback))
+ return PTR_ERR(ctx->fallback);
+
+ /* update statesize from fallback algorithm */
+ tfm->descsize += crypto_shash_descsize(ctx->fallback);
+
+ ctx->priv = p_alg->priv;
+ ctx->ctrl = p_alg->ctrl;
+
+ return 0;
+}
+
+static void hica_sha_alg_exit_tfm(struct crypto_shash *tfm)
+{
+ struct hica_sha_tfm_ctx *ctx = crypto_shash_ctx(tfm);
+
+ crypto_free_shash(ctx->fallback);
+}
+
+static int hica_sha_alg_register(struct hica_sha_alg *p_alg,
+ const struct hica_sha_tmpl *tmpl,
+ struct hica_sha_priv *priv)
+{
+ struct crypto_alg *base = &p_alg->alg.halg.base;
+
+ *p_alg = (typeof(*p_alg)) {
+ .alg = {
+ .init = hica_sha_alg_init,
+ .update = tmpl->update,
+ .final = hica_sha_alg_final,
+ .export = hica_sha_alg_export,
+ .import = hica_sha_alg_import,
+ .init_tfm = hica_sha_alg_init_tfm,
+ .exit_tfm = hica_sha_alg_exit_tfm,
+
+ .descsize = sizeof(struct hica_sha_desc_ctx),
+
+ .halg = {
+ .digestsize = tmpl->digestsize,
+ .statesize = tmpl->statesize,
+ .base = {
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH |
+ CRYPTO_ALG_NEED_FALLBACK |
+ CRYPTO_ALG_KERN_DRIVER_ONLY |
+ CRYPTO_ALG_ALLOCATES_MEMORY,
+ .cra_blocksize = tmpl->blocksize,
+ .cra_ctxsize = sizeof(struct hica_sha_tfm_ctx),
+ .cra_alignmask = 0,
+
+ .cra_priority = 200,
+ .cra_module = THIS_MODULE,
+ },
+ },
+ },
+ .ctrl = tmpl->ctrl,
+ .priv = priv,
+ };
+
+ snprintf(base->cra_name, sizeof(base->cra_name), "%s", tmpl->alg_name);
+ snprintf(base->cra_driver_name, sizeof(base->cra_driver_name),
+ "hisi-advca-%s", tmpl->alg_name);
+
+ return crypto_register_shash(&p_alg->alg);
+}
+
+#define hica_sha_tmpl_define(_ALG, _alg, state) { \
+ .ctrl = { \
+ .alg = SHA_ALG_##_ALG, \
+ }, \
+ .digestsize = _ALG##_DIGEST_SIZE, \
+ .statesize = sizeof(struct state##_state), \
+ .blocksize = _ALG##_BLOCK_SIZE, \
+ .update = hica_sha_alg_update_##state, \
+ .alg_name = #_alg, \
+}
+
+static const struct hica_sha_tmpl hica_sha_tmpls[] = {
+ hica_sha_tmpl_define(SHA1, sha1, sha1),
+ hica_sha_tmpl_define(SHA256, sha256, sha256),
+
+ /* MHASH only */
+ hica_sha_tmpl_define(SHA224, sha224, sha256),
+};
+
+/******** device ********/
+
+static int __maybe_unused hica_sha_suspend(struct device *dev)
+{
+ struct hica_sha_priv *priv = dev_get_drvdata(dev);
+
+ int ret;
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+
+ clk_bulk_unprepare(priv->clks_n, priv->clks);
+
+ return 0;
+}
+
+static int __maybe_unused hica_sha_resume(struct device *dev)
+{
+ struct hica_sha_priv *priv = dev_get_drvdata(dev);
+
+ return clk_bulk_prepare(priv->clks_n, priv->clks) ?:
+ pm_runtime_force_resume(dev);
+}
+
+static int __maybe_unused hica_sha_runtime_suspend(struct device *dev)
+{
+ struct hica_sha_priv *priv = dev_get_drvdata(dev);
+
+ clk_bulk_disable(priv->clks_n, priv->clks);
+
+ return 0;
+}
+
+static int __maybe_unused hica_sha_runtime_resume(struct device *dev)
+{
+ struct hica_sha_priv *priv = dev_get_drvdata(dev);
+
+ return clk_bulk_enable(priv->clks_n, priv->clks);
+}
+
+static const struct dev_pm_ops hica_sha_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(hica_sha_suspend, hica_sha_resume)
+ SET_RUNTIME_PM_OPS(hica_sha_runtime_suspend, hica_sha_runtime_resume,
+ NULL)
+};
+
+static void hica_sha_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct hica_sha_priv *priv = platform_get_drvdata(pdev);
+
+ for (int i = priv->algs_n; i > 0; ) {
+ i--;
+ crypto_unregister_shash(&priv->algs[i].alg);
+ }
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ clk_bulk_disable_unprepare(priv->clks_n, priv->clks);
+ reset_control_assert(priv->rst);
+}
+
+static int hica_sha_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ unsigned int saved_bypass_size = bypass_size;
+
+ struct hica_sha_priv *priv;
+ int ret;
+
+ /* acquire resources */
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ ret = devm_clk_bulk_get_all(dev, &priv->clks);
+ if (ret < 0)
+ return ret;
+ priv->clks_n = ret;
+
+ priv->rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(priv->rst))
+ return PTR_ERR(priv->rst);
+
+ priv->type = (uintptr_t) of_device_get_match_data(dev);
+
+ priv->algs_n = ARRAY_SIZE(hica_sha_tmpls);
+ if (priv->type != SHA_TYPE_MHASH)
+ priv->algs_n -= 1;
+
+ priv->algs = devm_kmalloc_array(dev, priv->algs_n,
+ sizeof(priv->algs[0]), GFP_KERNEL);
+ if (!priv->algs)
+ return -ENOMEM;
+
+ mutex_init(&priv->lock);
+
+ priv->dev = dev;
+ platform_set_drvdata(pdev, priv);
+ dev_set_drvdata(dev, priv);
+
+ /* bring up device */
+ ret = reset_control_assert(priv->rst);
+ if (ret)
+ return ret;
+ ret = clk_bulk_prepare_enable(priv->clks_n, priv->clks);
+ if (ret)
+ goto err_rst;
+ ret = reset_control_deassert(priv->rst);
+ if (ret)
+ goto err_clk;
+
+ if (hica_sha_wait(priv, SHA_HASH_READY, false)) {
+ dev_err(dev, "cannot bring up device\n");
+ ret = -ENODEV;
+ goto err_clk;
+ }
+
+ /* register algs */
+ bypass_size = 0;
+ for (int i = 0; i < priv->algs_n; i++) {
+ ret = hica_sha_alg_register(&priv->algs[i], &hica_sha_tmpls[i],
+ priv);
+ if (ret) {
+ while (i > 0) {
+ i--;
+ crypto_unregister_shash(&priv->algs[i].alg);
+ }
+ bypass_size = saved_bypass_size;
+ goto err_clk;
+ }
+ }
+ bypass_size = saved_bypass_size;
+
+ pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_irq_safe(dev);
+ pm_runtime_enable(dev);
+ return 0;
+
+err_clk:
+ clk_bulk_disable_unprepare(priv->clks_n, priv->clks);
+err_rst:
+ reset_control_assert(priv->rst);
+ return ret;
+}
+
+static const struct of_device_id hica_sha_of_match[] = {
+ { .compatible = "hisilicon,hi3798mv100-advca-sha",
+ .data = (void *) SHA_TYPE_HASH },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hica_sha_of_match);
+
+static struct platform_driver hica_sha_driver = {
+ .probe = hica_sha_probe,
+ .remove = hica_sha_remove,
+ .driver = {
+ .name = "hisi-advca-sha",
+ .of_match_table = hica_sha_of_match,
+ .pm = &hica_sha_pm_ops,
+ },
+};
+
+module_platform_driver(hica_sha_driver);
+
+MODULE_DESCRIPTION("HiSilicon Advanced Conditional Access Subsystem - SHA");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Yang <mmyangfl@gmail.com>");
@@ -0,0 +1,5 @@
--- /dev/null
+++ b/drivers/crypto/hisilicon/advca/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_HISI_ADVCA) += hisi-advca-muc.o
+obj-$(CONFIG_CRYPTO_DEV_HISI_ADVCA) += hisi-advca-sha.o
@@ -0,0 +1,27 @@
--- a/drivers/crypto/hisilicon/Kconfig
+++ b/drivers/crypto/hisilicon/Kconfig
@@ -1,5 +1,16 @@
# SPDX-License-Identifier: GPL-2.0
+config CRYPTO_DEV_HISI_ADVCA
+ tristate "Support for Hisilicon ADVCA Subsystem"
+ depends on ARCH_HISI || COMPILE_TEST
+ select CRYPTO_SKCIPHER
+ select CRYPTO_HASH
+ select CRYPTO_SHA1
+ select CRYPTO_SHA256
+ help
+ Support for Hisilicon ADVCA (Advanced Conditional Access) Subsystem,
+ which can be found on HiSilicon STB SoCs, such as Hi37xx.
+
config CRYPTO_DEV_HISI_SEC
tristate "Support for Hisilicon SEC crypto block cipher accelerator"
select CRYPTO_SKCIPHER
@@ -69,7 +80,6 @@ config CRYPTO_DEV_HISI_HPRE
select CRYPTO_DEV_HISI_QM
select CRYPTO_DH
select CRYPTO_RSA
- select CRYPTO_CURVE25519
select CRYPTO_ECDH
help
Support for HiSilicon HPRE(High Performance RSA Engine)
@@ -0,0 +1,8 @@
--- a/drivers/crypto/hisilicon/Makefile
+++ b/drivers/crypto/hisilicon/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_CRYPTO_DEV_HISI_ADVCA) += advca/
obj-$(CONFIG_CRYPTO_DEV_HISI_HPRE) += hpre/
obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += sec/
obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/
@@ -0,0 +1,836 @@
--- /dev/null
+++ b/drivers/dma/histb_dma.c
@@ -0,0 +1,833 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HiSilicon STB SoCs DMA Controller
+ *
+ * Copyright (c) 2024 David Yang
+ */
+#define DEBUG
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/string.h>
+
+#include "virt-dma.h"
+
+/******** hardware definitions ********/
+
+#define DMAC_INT_STATUS 0x00 /* interrupt status */
+#define DMAC_INT_TC_STATUS 0x04 /* transmission completion interrupt status */
+#define DMAC_INT_TC_CLR 0x08 /* transmission completion interrupt clear */
+#define DMAC_INT_ERR_STATUS 0x0c /* error interrupt status */
+#define DMAC_INT_ERR_CLR 0x10 /* error interrupt clear */
+#define DMAC_RAW_INT_TC_STATUS 0x14
+#define DMAC_RAW_INT_ERR_STATUS 0x18
+#define DMAC_ENBLD_CHNS 0x1c /* enabled channels */
+#define DMAC_SOFT_BRST_REQ 0x20 /* software burst request */
+#define DMAC_SOFT_SGLE_REQ 0x24 /* software single request */
+#define DMAC_SOFT_LST_BRST_REQ 0x28 /* software last burst request */
+#define DMAC_SOFT_LST_SGLE_REQ 0x2c /* software last single request */
+#define DMAC_CFG 0x30
+#define DMAC_CFG_M2 BIT(2) /* use big endian for Master 2 */
+#define DMAC_CFG_M1 BIT(1) /* use big endian for Master 1 */
+#define DMAC_CFG_EN BIT(0)
+#define DMAC_SYNC 0x34
+
+#define DMAC_CHAN_SRC_ADDR(n) (0x100 + 0x20 * (n) + 0x00)
+#define DMAC_CHAN_DST_ADDR(n) (0x100 + 0x20 * (n) + 0x04)
+#define DMAC_CHAN_LLI(n) (0x100 + 0x20 * (n) + 0x08) /* channel link list item */
+#define DMAC_CHAN_LLI_W0 BIT(1)
+#define DMAC_CHAN_LLI_NEXT GENMASK(31, 2) /* addr / 4, 0: disable */
+#define DMAC_CHAN_LLI_MST BIT(0) /* master to be loaded, 0: 1, 1: 2 */
+#define DMAC_CHAN_CTRL(n) (0x100 + 0x20 * (n) + 0x0c)
+#define DMAC_CHAN_CTRL_INT BIT(31) /* interrupt for this node */
+#define DMAC_CHAN_CTRL_PROT GENMASK(30, 28) /* bus HPROT value */
+#define DMAC_CHAN_CTRL_PROT_CACHEABLE BIT(30)
+#define DMAC_CHAN_CTRL_PROT_BUFFERABLE BIT(29)
+#define DMAC_CHAN_CTRL_PROT_PRIVILEGED BIT(28)
+#define DMAC_CHAN_CTRL_DST_INC BIT(27)
+#define DMAC_CHAN_CTRL_SRC_INC BIT(26)
+#define DMAC_CHAN_CTRL_DST_MST BIT(25)
+#define DMAC_CHAN_CTRL_SRC_MST BIT(24)
+#define DMAC_CHAN_CTRL_DST_WIDTH GENMASK(23, 21)
+#define DMAC_CHAN_CTRL_SRC_WIDTH GENMASK(20, 18)
+#define DMAC_WIDTH_8 0
+#define DMAC_WIDTH_16 1
+#define DMAC_WIDTH_32 2
+#define DMAC_CHAN_CTRL_DST_BSIZE GENMASK(17, 15)
+#define DMAC_CHAN_CTRL_SRC_BSIZE GENMASK(14, 12)
+#define DMAC_BSIZE_1 0
+#define DMAC_BSIZE_4 1
+#define DMAC_BSIZE_8 2
+#define DMAC_BSIZE_16 3
+#define DMAC_BSIZE_32 4
+#define DMAC_BSIZE_64 5
+#define DMAC_BSIZE_128 6
+#define DMAC_BSIZE_256 7
+#define DMAC_CHAN_CTRL_TX GENMASK(11, 0)
+#define DMAC_CHAN_CFG(n) (0x100 + 0x20 * (n) + 0x10)
+#define DMAC_CHAN_CFG_W0 (GENMASK(31, 19) & BIT(10) & BIT(5))
+#define DMAC_CHAN_CFG_HALT BIT(18) /* halt, ignore further requests */
+#define DMAC_CHAN_CFG_ACTIVE BIT(17) /* active, data exists */
+#define DMAC_CHAN_CFG_LOCK BIT(16) /* lock bus */
+#define DMAC_CHAN_CFG_INT_TC_MASK BIT(15)
+#define DMAC_CHAN_CFG_INT_ERR_MASK BIT(14)
+#define DMAC_CHAN_CFG_FLOW GENMASK(13, 11) /* src, dst, controller */
+#define DMAC_FLOW_MMC 0 /* memory -> memory (DMAC) */
+#define DMAC_FLOW_MDC 1 /* memory -> peripheral (DMAC) */
+#define DMAC_FLOW_SMC 2 /* peripheral -> memory (DMAC) */
+#define DMAC_FLOW_SDC 3 /* peripheral -> peripheral (DMAC) */
+#define DMAC_FLOW_SDD 4 /* peripheral -> peripheral (dst) */
+#define DMAC_FLOW_MDD 5 /* memory -> peripheral (dst) */
+#define DMAC_FLOW_SMS 6 /* peripheral -> memory (src) */
+#define DMAC_FLOW_SDS 7 /* peripheral -> peripheral (src) */
+#define DMAC_CHAN_CFG_DST_PERI GENMASK(9, 6)
+#define DMAC_CHAN_CFG_SRC_PERI GENMASK(4, 1)
+#define DMAC_CHAN_CFG_EN BIT(0)
+
+#define DMAC_CHAN_NUM 4u
+
+struct histb_dma_item {
+ __le32 src_addr;
+ __le32 dst_addr;
+ __le32 lli;
+ __le32 ctrl;
+} __packed __aligned(4);
+
+/******** driver definitions ********/
+
+struct histb_dma_desc {
+ struct virt_dma_desc vdesc;
+
+ dma_addr_t src_addr;
+ dma_addr_t dst_addr;
+ u32 lli;
+ u32 ctrl;
+
+ struct histb_dma_item *list;
+ dma_addr_t list_addr;
+ unsigned int list_size;
+
+ /* memset src buf */
+ int *value;
+ /* to free value */
+ struct dma_pool *pool;
+};
+
+struct histb_dma_chan {
+ void __iomem *base;
+ struct device *dev;
+ unsigned char id;
+ /* managed DMA pool of memset srcs */
+ struct dma_pool *pool;
+
+ struct virt_dma_chan vchan;
+
+ struct histb_dma_desc *desc;
+ bool completed;
+ bool error;
+};
+
+struct histb_dma_priv {
+ void __iomem *base;
+ struct device *dev;
+
+ struct reset_control *rst;
+ struct clk_bulk_data *clks;
+ unsigned int clks_n;
+ int irq;
+
+ struct dma_device dmadev;
+
+ struct histb_dma_chan chans[DMAC_CHAN_NUM];
+};
+
+static struct histb_dma_desc *to_histb_dma_desc(struct virt_dma_desc *vdesc)
+{
+ return container_of(vdesc, struct histb_dma_desc, vdesc);
+}
+
+static struct histb_dma_chan *to_histb_dma_chan(struct dma_chan *dmachan)
+{
+ return container_of(dmachan, struct histb_dma_chan, vchan.chan);
+}
+
+/******** desc ********/
+
+static void histb_dma_desc_free(struct histb_dma_desc *desc)
+{
+ if (desc->value)
+ dma_pool_free(desc->pool, desc->value, desc->src_addr);
+
+ kfree(desc);
+}
+
+static struct histb_dma_desc *
+histb_dma_desc_new_memset(struct dma_pool *pool, unsigned char value)
+{
+ struct histb_dma_desc *desc;
+ int *buf;
+
+ desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+ if (!desc)
+ return NULL;
+ buf = dma_pool_alloc(pool, GFP_NOWAIT, &desc->src_addr);
+ if (!buf) {
+ kfree(desc);
+ return NULL;
+ }
+
+ desc->value = buf;
+ desc->pool = pool;
+
+ for (int i = 0; i < sizeof(*buf); i++)
+ ((char *) buf)[i] = value;
+
+ return desc;
+}
+
+static void histb_dma_vdesc_free(struct virt_dma_desc *vdesc)
+{
+ histb_dma_desc_free(to_histb_dma_desc(vdesc));
+}
+
+/******** channel ********/
+
+static void
+_histb_dma_chan_debug(struct device *dev, unsigned int id, unsigned int n,
+ u32 src_addr, u32 dst_addr, u32 lli, u32 ctrl)
+{
+ static const unsigned int width[] = { 8, 16, 32, 0 };
+ static const unsigned int bsize[] = { 1, 4, 8, 16, 32, 64, 128, 256 };
+
+ dev_dbg(dev,
+ "%u: %2u %c[%lu], %08x%c @ %2u-%2u -> %08x%c @ %2u-%2u * %lu\n",
+ id, n, (ctrl & DMAC_CHAN_CTRL_INT) ? 'I' : ' ',
+ (ctrl & DMAC_CHAN_CTRL_PROT) >> 28,
+ src_addr, (ctrl & DMAC_CHAN_CTRL_SRC_INC) ? '+' : ' ',
+ width[(ctrl & DMAC_CHAN_CTRL_SRC_WIDTH) >> 18],
+ bsize[(ctrl & DMAC_CHAN_CTRL_SRC_BSIZE) >> 12],
+ dst_addr, (ctrl & DMAC_CHAN_CTRL_DST_INC) ? '+' : ' ',
+ width[(ctrl & DMAC_CHAN_CTRL_DST_WIDTH) >> 21],
+ bsize[(ctrl & DMAC_CHAN_CTRL_DST_BSIZE) >> 15],
+ ctrl & DMAC_CHAN_CTRL_TX);
+}
+
+static void histb_dma_chan_debug(struct histb_dma_chan *chan)
+{
+ static const char * const flow[] = {
+ "MMC", "MDC", "SMC", "SDC", "SDD", "MDD", "SMS", "SDS"
+ };
+
+ void __iomem *base = chan->base;
+ struct device *dev = chan->dev;
+ unsigned int id = chan->id;
+
+ u32 src_addr = readl_relaxed(base + DMAC_CHAN_SRC_ADDR(id));
+ u32 dst_addr = readl_relaxed(base + DMAC_CHAN_DST_ADDR(id));
+ u32 lli = readl_relaxed(base + DMAC_CHAN_LLI(id));
+ u32 ctrl = readl_relaxed(base + DMAC_CHAN_CTRL(id));
+ u32 cfg = readl_relaxed(base + DMAC_CHAN_CFG(id));
+
+ dev_dbg(dev, "%u: flow %s, peri %lu -> %lu, %c%c%c%c%c%c\n", id,
+ flow[(cfg & DMAC_CHAN_CFG_FLOW) >> 1],
+ (cfg & DMAC_CHAN_CFG_SRC_PERI) >> 6,
+ (cfg & DMAC_CHAN_CFG_DST_PERI) >> 1,
+ (cfg & DMAC_CHAN_CFG_HALT) ? 'H' : ' ',
+ (cfg & DMAC_CHAN_CFG_ACTIVE) ? 'A' : ' ',
+ (cfg & DMAC_CHAN_CFG_LOCK) ? 'L' : ' ',
+ (cfg & DMAC_CHAN_CFG_INT_TC_MASK) ? 'i' : ' ',
+ (cfg & DMAC_CHAN_CFG_INT_ERR_MASK) ? 'e' : ' ',
+ (cfg & DMAC_CHAN_CFG_EN) ? 'E' : ' ');
+
+ _histb_dma_chan_debug(dev, id, 0, src_addr, dst_addr, lli, ctrl);
+}
+
+static int histb_dma_chan_halt(struct histb_dma_chan *chan)
+{
+ void __iomem *cfg = chan->base + DMAC_CHAN_CFG(chan->id);
+
+ u32 val;
+
+ val = readl_relaxed(cfg);
+ if (!(val & DMAC_CHAN_CFG_EN))
+ return 0;
+
+ if (!(val & DMAC_CHAN_CFG_HALT)) {
+ val &= ~DMAC_CHAN_CFG_W0;
+ val |= DMAC_CHAN_CFG_HALT;
+ writel(val, cfg);
+ }
+
+ return readl_relaxed_poll_timeout_atomic(cfg, val,
+ !(val & DMAC_CHAN_CFG_ACTIVE),
+ 10, USEC_PER_SEC);
+}
+
+static void histb_dma_chan_enable(struct histb_dma_chan *chan)
+{
+ void __iomem *cfg = chan->base + DMAC_CHAN_CFG(chan->id);
+
+ u32 val;
+
+ val = readl_relaxed(cfg);
+ if (val & DMAC_CHAN_CFG_EN)
+ return;
+
+ if (val & DMAC_CHAN_CFG_HALT) {
+ val &= ~DMAC_CHAN_CFG_HALT;
+ writel_relaxed(val, cfg);
+ }
+}
+
+static int histb_dma_chan_wait_disable(struct histb_dma_chan *chan)
+{
+ void __iomem *base = chan->base;
+ unsigned int id = chan->id;
+
+ u32 val;
+
+ return readl_relaxed_poll_timeout_atomic(base + DMAC_ENBLD_CHNS, val,
+ !(val & BIT(id)),
+ 10, USEC_PER_SEC);
+}
+
+/*
+ * start transferring chan->desc, chan->desc.vdesc.lock should be held by caller
+ */
+static void histb_dma_chan_start(struct histb_dma_chan *chan)
+{
+ struct histb_dma_desc *desc = chan->desc;
+ void __iomem *base = chan->base;
+ unsigned int id = chan->id;
+
+ u32 val;
+
+ writel_relaxed(desc->src_addr, base + DMAC_CHAN_SRC_ADDR(id));
+ writel_relaxed(desc->dst_addr, base + DMAC_CHAN_DST_ADDR(id));
+ writel_relaxed(desc->lli, base + DMAC_CHAN_LLI(id));
+ writel_relaxed(desc->ctrl, base + DMAC_CHAN_CTRL(id));
+
+ // set in chan enable?
+ val = readl_relaxed(base + DMAC_CHAN_CFG(id));
+ val &= ~DMAC_CHAN_CFG_W0;
+ val |= DMAC_CHAN_CFG_INT_TC_MASK;
+ val |= DMAC_CHAN_CFG_INT_ERR_MASK;
+ val &= ~DMAC_CHAN_CFG_FLOW;
+ val |= DMAC_FLOW_MMC << 11;
+ val |= DMAC_CHAN_CFG_EN;
+ writel_relaxed(val, base + DMAC_CHAN_CFG(id));
+
+ histb_dma_chan_debug(chan);
+}
+
+static struct dma_async_tx_descriptor *
+histb_dma_chan_prep(struct histb_dma_chan *chan, struct histb_dma_desc *desc,
+ size_t len, unsigned long flags)
+{
+ u32 ctrl = DMAC_CHAN_CTRL_INT | DMAC_CHAN_CTRL_PROT |
+ DMAC_CHAN_CTRL_DST_INC |
+ (DMAC_WIDTH_32 << 21) | (DMAC_WIDTH_32 << 18) | (len / 4);
+
+ dev_dbg(chan->dev, "prep dma operation on channel %d\n", chan->id);
+ dev_dbg(chan->dev, "dst = %llu, src = %llu, len = %zu\n", dst, src, len);
+
+ if (!desc->value)
+ ctrl |= DMAC_CHAN_CTRL_SRC_INC;
+
+ desc->ctrl = ctrl;
+
+ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
+}
+
+static int
+histb_dma_chan_init(struct histb_dma_chan *chan, struct histb_dma_priv *priv,
+ unsigned int id, struct dma_pool *pool)
+{
+ chan->base = priv->base;
+ chan->id = id;
+ chan->dev = priv->dev;
+ chan->pool = pool;
+
+ chan->vchan.desc_free = histb_dma_vdesc_free;
+ vchan_init(&chan->vchan, &priv->dmadev);
+
+ return 0;
+}
+
+/******** dma_chan ********/
+
+static int histb_dma_alloc_chan_resources(struct dma_chan *dmachan)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+
+ histb_dma_chan_enable(chan);
+ return 0;
+}
+
+static void histb_dma_free_chan_resources(struct dma_chan *dmachan)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+
+ histb_dma_chan_halt(chan);
+ vchan_free_chan_resources(&chan->vchan);
+}
+
+static struct dma_async_tx_descriptor *
+histb_dma_prep_dma_memcpy(struct dma_chan *dmachan, dma_addr_t dst,
+ dma_addr_t src, size_t len, unsigned long flags)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+ struct histb_dma_desc *desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+
+ if (!desc)
+ return NULL;
+
+ desc->src_addr = src;
+ desc->dst_addr = dst;
+
+ return histb_dma_chan_prep(chan, desc, len, flags);
+}
+
+static struct dma_async_tx_descriptor *
+histb_dma_prep_dma_memset(struct dma_chan *dmachan, dma_addr_t dst, int value,
+ size_t len, unsigned long flags)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+ struct histb_dma_desc *desc = histb_dma_desc_new_memset(chan->pool,
+ value);
+
+ if (!desc)
+ return NULL;
+
+ desc->dst_addr = dst;
+
+ return histb_dma_chan_prep(chan, desc, len, flags);
+}
+
+static struct dma_async_tx_descriptor *
+histb_dma_dma_memset_sg(struct dma_chan *dmachan, struct scatterlist *sgl,
+ unsigned int sg_len, int value, unsigned long flags)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+ struct histb_dma_desc *desc = histb_dma_desc_new_memset(chan->pool,
+ value);
+
+ if (!desc)
+ return NULL;
+
+ return NULL;
+}
+
+static enum dma_status
+histb_dma_tx_status(struct dma_chan *dmachan, dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+
+ enum dma_status status;
+
+ status = dma_cookie_status(dmachan, cookie, txstate);
+ if (status == DMA_COMPLETE)
+ return status;
+
+ return DMA_COMPLETE;
+}
+
+static int histb_dma_terminate_all(struct dma_chan *dmachan)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+ LIST_HEAD(list);
+ unsigned long int flags;
+ int ret;
+
+ spin_lock_irqsave(&chan->vchan.lock, flags);
+
+ ret = histb_dma_chan_halt(chan);
+ if (ret < 0)
+ return ret;
+
+ if (chan->desc) {
+ vchan_terminate_vdesc(&chan->desc->vdesc);
+ chan->desc = NULL;
+ }
+
+ vchan_get_all_descriptors(&chan->vchan, &list);
+
+ spin_unlock_irqrestore(&chan->vchan.lock, flags);
+
+ vchan_dma_desc_free_list(&chan->vchan, &list);
+
+ return 0;
+}
+
+static void histb_dma_synchronize(struct dma_chan *dmachan)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+ histb_dma_chan_wait_disable(chan);
+ return;
+}
+
+static void histb_dma_issue_pending(struct dma_chan *dmachan)
+{
+ struct histb_dma_chan *chan = to_histb_dma_chan(dmachan);
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vchan.lock, flags);
+ /*
+ * chan->desc is NULL when the channel is available
+ */
+ if (vchan_issue_pending(&chan->vchan) && !chan->desc) {
+ pr_debug("%s %u: vchan %pK issued\n", __func__, chan->id,
+ &chan->vchan);
+
+ struct virt_dma_desc *vnext = vchan_next_desc(&chan->vchan);
+ struct histb_dma_desc *next = to_histb_dma_desc(vnext);
+ chan->desc = next;
+ list_del(&vnext->node);
+ histb_dma_chan_start(chan);
+ }
+ spin_unlock_irqrestore(&chan->vchan.lock, flags);
+}
+
+/******** irq ********/
+
+static void
+histb_dma_handle_chan(struct histb_dma_chan *chan)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vchan.lock, flags);
+
+ struct histb_dma_desc *old = chan->desc;
+ vchan_cookie_complete(&old->vdesc);
+
+ struct virt_dma_desc *vnext = vchan_next_desc(&chan->vchan);
+ if (!vnext) { // no more issued descriptors
+ chan->desc = NULL;
+ goto end;
+ }
+
+ /* set new descriptor */
+ struct histb_dma_desc *next = to_histb_dma_desc(vnext);
+ chan->desc = next;
+ list_del(&vnext->node);
+
+ histb_dma_chan_start(chan); // start the new descritpor
+
+end:
+ spin_unlock_irqrestore(&chan->vchan.lock, flags);
+ return;
+}
+
+static irqreturn_t histb_dma_handle(int irq, void *dev_id)
+{
+ struct histb_dma_priv *priv = dev_id;
+
+ u32 stat = readl_relaxed(priv->base + DMAC_INT_STATUS);
+ if (!stat)
+ return IRQ_NONE;
+
+ u32 tc = readl_relaxed(priv->base + DMAC_INT_TC_STATUS);
+ if (tc)
+ writel_relaxed(tc, priv->base + DMAC_INT_TC_CLR);
+ u32 err = readl_relaxed(priv->base + DMAC_INT_ERR_STATUS);
+ if (err)
+ writel_relaxed(tc, priv->base + DMAC_INT_ERR_CLR);
+
+ for (unsigned int i = 0; i < DMAC_CHAN_NUM; i++) {
+ if (err & BIT(i))
+ dev_err(priv->dev, "Channel %i transfer error\n", i);
+ else if (tc & BIT(i))
+ histb_dma_handle_chan(priv->chans + i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/******** device ********/
+
+static int __maybe_unused histb_dma_suspend(struct device *dev)
+{
+ struct histb_dma_priv *priv = dev_get_drvdata(dev);
+
+ int ret;
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+
+ clk_bulk_unprepare(priv->clks_n, priv->clks);
+
+ return 0;
+}
+
+static int __maybe_unused histb_dma_resume(struct device *dev)
+{
+ struct histb_dma_priv *priv = dev_get_drvdata(dev);
+ return clk_bulk_prepare(priv->clks_n, priv->clks) ?:
+ pm_runtime_force_resume(dev);
+}
+
+static int __maybe_unused histb_dma_runtime_suspend(struct device *dev)
+{
+ struct histb_dma_priv *priv = dev_get_drvdata(dev);
+
+ u32 val;
+
+ for (unsigned int id = 0; id < DMAC_CHAN_NUM; id++) {
+ val = readl_relaxed(priv->base + DMAC_CHAN_CFG(id));
+ val &= ~DMAC_CHAN_CFG_EN;
+ val &= ~DMAC_CHAN_CFG_W0;
+ writel_relaxed(val, priv->base + DMAC_CHAN_CFG(id));
+ }
+ val = readl_relaxed(priv->base + DMAC_CFG);
+ writel_relaxed(val & ~DMAC_CFG_EN, priv->base + DMAC_CFG);
+
+ clk_bulk_disable(priv->clks_n, priv->clks);
+
+ return 0;
+}
+
+static int __maybe_unused histb_dma_runtime_resume(struct device *dev)
+{
+ struct histb_dma_priv *priv = dev_get_drvdata(dev);
+
+ u32 val;
+ int ret;
+
+ ret = clk_bulk_enable(priv->clks_n, priv->clks);
+ if (ret)
+ return ret;
+
+ val = readl_relaxed(priv->base + DMAC_CFG);
+ val |= DMAC_CFG_M2;
+ val |= DMAC_CFG_M1;
+ val |= DMAC_CFG_EN;
+ writel_relaxed(val, priv->base + DMAC_CFG);
+
+ val = readl_relaxed(priv->base + DMAC_CFG);
+ if (!val) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ writel_relaxed(~0, priv->base + DMAC_INT_ERR_CLR);
+ writel_relaxed(~0, priv->base + DMAC_INT_TC_CLR);
+
+ for (unsigned int id = 0; id < DMAC_CHAN_NUM; id++) {
+ val = readl_relaxed(priv->base + DMAC_CHAN_CFG(id));
+ val &= ~DMAC_CHAN_CFG_EN;
+ val &= ~DMAC_CHAN_CFG_W0;
+ writel_relaxed(val, priv->base + DMAC_CHAN_CFG(id));
+ }
+
+ return 0;
+
+err:
+ clk_bulk_disable(priv->clks_n, priv->clks);
+ return ret;
+}
+
+static const struct dev_pm_ops histb_dma_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(histb_dma_suspend, histb_dma_resume)
+ SET_RUNTIME_PM_OPS(histb_dma_runtime_suspend,
+ histb_dma_runtime_resume, NULL)
+};
+
+static void histb_dma_remove(struct platform_device *pdev)
+{
+ struct histb_dma_priv *priv = platform_get_drvdata(pdev);
+ struct device *dev = priv->dev;
+
+ /*pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);*/
+ clk_bulk_disable_unprepare(priv->clks_n, priv->clks);
+ reset_control_assert(priv->rst);
+}
+
+static int histb_dma_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ struct histb_dma_priv *priv;
+ struct dma_device *dmadev;
+ struct dma_pool *pool;
+ u32 val;
+ int ret;
+
+ /* acquire resources */
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ pool = dmam_pool_create("histb-dma-memset-src", dev, sizeof(int),
+ sizeof(int), 0);
+ if (!pool)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ ret = devm_clk_bulk_get_all(dev, &priv->clks);
+ if (ret < 0)
+ return ret;
+ priv->clks_n = ret;
+
+ priv->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
+ if (IS_ERR(priv->rst))
+ return PTR_ERR(priv->rst);
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
+ priv->irq = ret;
+
+ priv->dev = dev;
+ platform_set_drvdata(pdev, priv);
+ dev_set_drvdata(dev, priv);
+
+ /* bring up device */
+ ret = reset_control_assert(priv->rst);
+ if (ret)
+ return ret;
+ ret = clk_bulk_prepare_enable(priv->clks_n, priv->clks);
+ if (ret)
+ goto err_rst;
+ ret = reset_control_deassert(priv->rst);
+ if (ret)
+ goto err_clk;
+
+ val = readl_relaxed(priv->base + DMAC_CFG);
+ if (!val) {
+ writel_relaxed(val | DMAC_CFG_EN, priv->base + DMAC_CFG);
+ val = readl_relaxed(priv->base + DMAC_CFG);
+ if (!(val & DMAC_CFG_EN)) {
+ dev_err(dev, "cannot bring up device\n");
+ ret = -ENODEV;
+ goto err_clk;
+ }
+ }
+
+ /* register irq */
+ ret = devm_request_irq(dev, priv->irq, histb_dma_handle,
+ IRQF_SHARED, pdev->name, priv);
+ if (ret)
+ goto err_clk;
+
+
+ /* register dma engine */
+ dmadev = &priv->dmadev;
+ dma_cap_set(DMA_MEMCPY, dmadev->cap_mask);
+ dma_cap_set(DMA_MEMSET, dmadev->cap_mask);
+ dmadev->copy_align = DMAENGINE_ALIGN_4_BYTES;
+ dmadev->fill_align = DMAENGINE_ALIGN_4_BYTES;
+ dmadev->dev = dev;
+ dmadev->descriptor_reuse = true;
+ dmadev->directions = BIT(DMA_MEM_TO_MEM);
+ dmadev->device_alloc_chan_resources = histb_dma_alloc_chan_resources;
+ dmadev->device_free_chan_resources = histb_dma_free_chan_resources;
+ dmadev->device_prep_dma_memcpy = histb_dma_prep_dma_memcpy;
+ dmadev->device_prep_dma_memset = histb_dma_prep_dma_memset;
+ dmadev->device_prep_dma_memset_sg = histb_dma_prep_dma_memset_sg;
+ dmadev->device_tx_status = histb_dma_tx_status;
+ dmadev->device_terminate_all = histb_dma_terminate_all;
+ dmadev->device_synchronize = histb_dma_synchronize;
+ dmadev->device_issue_pending = histb_dma_issue_pending;
+ INIT_LIST_HEAD(&dmadev->channels);
+
+ for (unsigned int id = 0; id < DMAC_CHAN_NUM; id++) {
+ histb_dma_chan_init(&priv->chans[id], priv, id, pool);
+ }
+
+ ret = dmaenginem_async_device_register(dmadev);
+ if (ret)
+ goto err_clk;
+
+#if 0
+ unsigned int *buf;
+ dma_addr_t buf_addr;
+ buf = dmam_alloc_attrs(dev, PAGE_SIZE, &buf_addr, GFP_KERNEL | __GFP_ZERO, 0);
+ buf[0] = 0x11223344;
+printk("%s %d %llx %llx\n", __func__, __LINE__, buf_addr, buf_addr + PAGE_SIZE / 2);
+
+ writel_relaxed(buf_addr, priv->base + DMAC_CHAN_SRC_ADDR(0));
+ writel_relaxed(buf_addr + PAGE_SIZE / 2, priv->base + DMAC_CHAN_DST_ADDR(0));
+ writel_relaxed(0, priv->base + DMAC_CHAN_LLI(0));
+
+ val = readl_relaxed(priv->base + DMAC_CHAN_CTRL(0));
+ val |= DMAC_CHAN_CTRL_INT;
+ val |= DMAC_CHAN_CTRL_PROT_CACHEABLE;
+ val |= DMAC_CHAN_CTRL_PROT_BUFFERABLE;
+ val |= DMAC_CHAN_CTRL_PROT_PRIVILEGED;
+ //val |= DMAC_CHAN_CTRL_DST_INC;
+ val |= DMAC_CHAN_CTRL_SRC_INC;
+ val &= ~DMAC_CHAN_CTRL_DST_WIDTH;
+ val |= DMAC_WIDTH_32 << 21;
+ val &= ~DMAC_CHAN_CTRL_SRC_WIDTH;
+ val |= DMAC_WIDTH_32 << 18;
+ /*val &= ~DMAC_CHAN_CTRL_DST_BSIZE;
+ val |= DMAC_BSIZE_1 << 15;
+ val &= ~DMAC_CHAN_CTRL_SRC_BSIZE;
+ val |= DMAC_BSIZE_4 << 12;*/
+ val &= ~DMAC_CHAN_CTRL_TX;
+ val |= 4;
+ writel_relaxed(val, priv->base + DMAC_CHAN_CTRL(0));
+
+ val = readl_relaxed(priv->base + DMAC_CHAN_CFG(0));
+ val &= ~DMAC_CHAN_CFG_W0;
+ val |= DMAC_CHAN_CFG_INT_TC_MASK;
+ val |= DMAC_CHAN_CFG_INT_ERR_MASK;
+ val &= ~DMAC_CHAN_CFG_FLOW;
+ val |= DMAC_FLOW_MMC << 11;
+ val |= DMAC_CHAN_CFG_EN;
+ writel_relaxed(val, priv->base + DMAC_CHAN_CFG(0));
+#endif // #if 0
+
+// pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
+// pm_runtime_use_autosuspend(dev);
+// pm_runtime_set_active(dev);
+// pm_runtime_irq_safe(dev);
+// pm_runtime_enable(dev);
+
+ return 0;
+
+err_clk:
+ clk_bulk_disable_unprepare(priv->clks_n, priv->clks);
+err_rst:
+ reset_control_assert(priv->rst);
+ return ret;
+}
+
+static const struct of_device_id histb_dma_of_match[] = {
+ { .compatible = "hisilicon,hi3798mv100-dmac", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, histb_dma_of_match);
+
+static struct platform_driver histb_dma_driver = {
+ .probe = histb_dma_probe,
+ .remove_new = histb_dma_remove,
+ .driver = {
+ .name = "histb-dma",
+ .of_match_table = histb_dma_of_match,
+ .pm = &histb_dma_pm_ops,
+ },
+};
+
+module_platform_driver(histb_dma_driver);
+
+MODULE_DESCRIPTION("HiSilicon STB SoCs DMA Controller");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Yang <mmyangfl@gmail.com>");
@@ -0,0 +1,26 @@
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -253,6 +253,14 @@ config HISI_DMA
help
Support HiSilicon Kunpeng DMA engine.
+config HISTB_DMA
+ tristate "HiSilicon STB SoCs DMA Controller support"
+ depends on ARCH_HISI || COMPILE_TEST
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Support HiSilicon STB SoCs DMA Controller.
+
config IMG_MDC_DMA
tristate "IMG MDC support"
depends on MIPS || COMPILE_TEST
@@ -464,7 +472,7 @@ config MOXART_DMA
select DMA_VIRTUAL_CHANNELS
help
Enable support for the MOXA ART SoC DMA controller.
-
+
Say Y here if you enabled MMP ADMA, otherwise say N.
config MPC512X_DMA
@@ -0,0 +1,10 @@
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_MCF_EDMA) += mcf-edma.o
obj-$(CONFIG_FSL_QDMA) += fsl-qdma.o
obj-$(CONFIG_FSL_RAID) += fsl_raid.o
obj-$(CONFIG_HISI_DMA) += hisi_dma.o
+obj-$(CONFIG_HISTB_DMA) += histb_dma.o
obj-$(CONFIG_HSU_DMA) += hsu/
obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
obj-$(CONFIG_IMX_DMA) += imx-dma.o
@@ -0,0 +1,165 @@
--- /dev/null
+++ b/drivers/net/phy/hisi-festa.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Driver for HiSilicon Festa PHYs
+ *
+ * This module does nothing than firmware injection. If you don't use firmware,
+ * simply blacklist this module.
+ *
+ * Copyright (c) 2023 David Yang
+ */
+#include <linux/errno.h>
+#include <linux/firmware.h>
+#include <linux/init.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define PHY_ID_HISILICON_FESTAV200 0x20669813
+#define PHY_ID_HISILICON_FESTAV220 0x20669823
+#define PHY_ID_HISILICON_FESTAV300 0x20669833
+#define PHY_ID_HISILICON_FESTAV320 0x20669843
+#define PHY_ID_HISILICON_FESTAV330 0x20669853
+#define PHY_ID_HISILICON_FESTAV331 0x20669863
+
+#define MII_EXPMD 0x1d /* Expanded memory data */
+#define MII_EXPMA 0x1e /* Expanded memory address */
+
+/* bus->mdio_lock should be locked when using this function */
+static int hisi_festa_write_expanded(struct phy_device *phydev, u16 addr, u8 val)
+{
+ __phy_write(phydev, MII_EXPMA, addr);
+ __phy_write(phydev, MII_EXPMD, val);
+ return 0;
+}
+
+/* bus->mdio_lock should be locked when using this function */
+static int hisi_festa_write_expanded_mem(struct phy_device *phydev, u16 addr,
+ const u8 *data, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ hisi_festa_write_expanded(phydev, addr + i, data[i]);
+ return 0;
+}
+
+static int hisi_festa_write_fw(struct phy_device *phydev, const struct firmware *fw)
+{
+ static const u8 prologue[] = {0xbd, 0x34, 0x00, 0x39};
+ int ret;
+
+ phy_lock_mdio_bus(phydev);
+
+ ret = __phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
+ if (ret) {
+ phydev_err(phydev, "cannot suspend device\n");
+ goto out;
+ }
+
+ hisi_festa_write_expanded_mem(phydev, 0x33f9, prologue, sizeof(prologue));
+ /* mask jump instruction */
+ hisi_festa_write_expanded(phydev, 0x3400, 0x39);
+ hisi_festa_write_expanded_mem(phydev, 0x3401, fw->data + 1, fw->size - 1);
+ /* now release firmware */
+ hisi_festa_write_expanded(phydev, 0x3400, fw->data[0]);
+ hisi_festa_write_expanded(phydev, 0x33f8, 0x01);
+
+ ret = __phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);
+
+out:
+ phy_unlock_mdio_bus(phydev);
+ return ret;
+}
+
+static int hisi_festa_patch_fw(struct phy_device *phydev)
+{
+ int ret;
+ char fw_name[64];
+ const struct firmware *fw;
+
+ snprintf(fw_name, sizeof(fw_name), "hisilicon/festa.%08x.ucode", phydev->phy_id);
+
+ ret = request_firmware(&fw, fw_name, &phydev->mdio.dev);
+ if (ret) {
+ /* err message already printed by request_firmware */
+ return -EAGAIN;
+ }
+
+ if (fw->data[0] != 0x01 || fw->data[1] != 0xcc) {
+ phydev_err(phydev, "%s does not look like valid firmware; refused to load\n",
+ fw_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = hisi_festa_write_fw(phydev, fw);
+ if (ret) {
+ phydev_err(phydev, "download firmware %s failed\n", fw_name);
+ goto out;
+ }
+
+ phydev_info(phydev, "using firmware %s\n", fw_name);
+
+out:
+ release_firmware(fw);
+ return ret;
+}
+
+static int hisi_festa_config_init(struct phy_device *phydev)
+{
+ hisi_festa_patch_fw(phydev);
+ /* ok, use programmed firmware */
+ return 0;
+}
+
+static struct phy_driver hisi_festa_driver[] = {
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV200),
+ .name = "HiSilicon Festa v200/v210",
+ .config_init = hisi_festa_config_init,
+ },
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV220),
+ .name = "HiSilicon Festa v220",
+ .config_init = hisi_festa_config_init,
+ },
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV300),
+ .name = "HiSilicon Festa v300",
+ .config_init = hisi_festa_config_init,
+ },
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV320),
+ .name = "HiSilicon Festa v320",
+ .config_init = hisi_festa_config_init,
+ },
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV330),
+ .name = "HiSilicon Festa v330",
+ .config_init = hisi_festa_config_init,
+ },
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV331),
+ .name = "HiSilicon Festa v331",
+ .config_init = hisi_festa_config_init,
+ },
+};
+
+module_phy_driver(hisi_festa_driver);
+
+static struct mdio_device_id __maybe_unused hisi_festa_tbl[] = {
+ { PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV200) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV220) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV300) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV320) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV330) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_HISILICON_FESTAV331) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, hisi_festa_tbl);
+MODULE_DESCRIPTION("HiSilicon Festa PHY driver");
+MODULE_LICENSE("Dual MIT/GPL");
@@ -0,0 +1,14 @@
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -298,6 +298,11 @@ config DAVICOM_PHY
help
Currently supports dm9161e and dm9131
+config HISI_FESTA_PHY
+ tristate "HiSilicon Festa PHYs"
+ help
+ Supports the HiSilicon Festa PHYs.
+
config ICPLUS_PHY
tristate "ICPlus PHYs"
help
@@ -0,0 +1,10 @@
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_DP83TC811_PHY) += dp83tc811
obj-$(CONFIG_DP83TD510_PHY) += dp83td510.o
obj-$(CONFIG_DP83TG720_PHY) += dp83tg720.o
obj-$(CONFIG_FIXED_PHY) += fixed_phy.o
+obj-$(CONFIG_HISI_FESTA_PHY) += hisi-festa.o
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
@@ -0,0 +1,154 @@
--- /dev/null
+++ b/drivers/regulator/histb-regulator.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Device driver for regulators in HiSTB SoCs
+ *
+ * Copyright (c) 2023 David Yang
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/rational.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+/*
+ * duty + 1 = reg & 0xffff0000
+ * period + 1 = reg & 0x0000ffff
+ * clock: xtal (usually 24M)
+ */
+
+/* 24000 kHz / 4094 ~= 6 kHz ~= 0.17 ms */
+#define HISTB_REGULATOR_MAX_PERIOD 0xfff
+
+struct histb_regulator {
+ struct regulator_desc desc;
+ void __iomem *base;
+ int min_uV;
+ int max_uV;
+};
+
+static int histb_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct histb_regulator *reg = rdev_get_drvdata(rdev);
+ u32 val;
+ u32 duty;
+ u32 period;
+
+ val = readl_relaxed(reg->base);
+ duty = (val & 0xffff0000) >> 16;
+ period = (val & 0x0000ffff) >> 0;
+
+ if (duty <= 1 || period <= 1)
+ return reg->max_uV;
+ if (duty >= period)
+ return reg->min_uV;
+
+ duty -= 1;
+ period -= 1;
+
+ return reg->max_uV - (reg->max_uV - reg->min_uV) * duty / period;
+}
+
+static int histb_regulator_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned int *selector)
+{
+ struct histb_regulator *reg = rdev_get_drvdata(rdev);
+ unsigned long duty;
+ unsigned long period;
+
+ if (min_uV >= reg->max_uV) {
+ writel_relaxed(0x00010002, reg->base);
+ return 0;
+ }
+ if (min_uV <= reg->min_uV) {
+ writel_relaxed(0x00020002, reg->base);
+ return 0;
+ }
+
+ rational_best_approximation(reg->max_uV - min_uV, reg->max_uV - reg->min_uV,
+ HISTB_REGULATOR_MAX_PERIOD, HISTB_REGULATOR_MAX_PERIOD,
+ &duty, &period);
+ writel_relaxed(((duty + 1) << 16) | (period + 1), reg->base);
+
+ return 0;
+}
+
+static const struct regulator_ops histb_regulator_ops = {
+ .get_voltage = histb_regulator_get_voltage,
+ .set_voltage = histb_regulator_set_voltage,
+};
+
+static int histb_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct histb_regulator *reg;
+ struct regulator_desc *desc;
+ struct regulator_init_data *init_data;
+ struct regulator_config config = { };
+ struct regulator_dev *rdev;
+ int ret;
+
+ reg = devm_kzalloc(dev, sizeof(*reg), GFP_KERNEL);
+ if (!reg)
+ return -ENOMEM;
+
+ desc = &reg->desc;
+
+ init_data = of_get_regulator_init_data(dev, np, desc);
+ if (!init_data)
+ return -ENOMEM;
+
+ reg->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg->base))
+ return -ENOMEM;
+
+ desc->name = dev_name(&pdev->dev);
+ desc->type = REGULATOR_VOLTAGE;
+ desc->owner = THIS_MODULE;
+ desc->ops = &histb_regulator_ops;
+ desc->continuous_voltage_range = true;
+
+ reg->min_uV = init_data->constraints.min_uV;
+ reg->max_uV = init_data->constraints.max_uV;
+
+ config.dev = dev;
+ config.init_data = init_data;
+ config.driver_data = reg;
+ config.of_node = np;
+
+ rdev = devm_regulator_register(dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(dev, "failed to register %s (%d)\n", desc->name, ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, reg);
+ return 0;
+}
+
+static const struct of_device_id histb_regulator_of_match[] = {
+ { .compatible = "hisilicon,histb-volt", },
+ { }
+};
+
+static struct platform_driver histb_regulator_driver = {
+ .probe = histb_regulator_probe,
+ .driver = {
+ .name = "histb-regulator",
+ .of_match_table = of_match_ptr(histb_regulator_of_match),
+ },
+};
+
+module_platform_driver(histb_regulator_driver);
+
+MODULE_DESCRIPTION("HiSTB regulator");
+MODULE_LICENSE("Dual MIT/GPL");
@@ -0,0 +1,16 @@
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -468,6 +468,13 @@ config REGULATOR_HI6421V600
HiSilicon Hi6421v600 PMU / Codec IC.
This is used on Kirin 3670 boards, like HiKey 970.
+config REGULATOR_HISTB
+ tristate "Hisilicon STB regulators support"
+ depends on ARCH_HISI || COMPILE_TEST
+ help
+ This driver provides support for the voltage regulators of the
+ Hisilicon STB device.
+
config REGULATOR_ISL9305
tristate "Intersil ISL9305 regulator"
depends on I2C
@@ -0,0 +1,18 @@
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_REGULATOR_HI6421) += hi6421
obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
+obj-$(CONFIG_REGULATOR_HISTB) += histb-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
@@ -86,7 +87,6 @@ obj-$(CONFIG_REGULATOR_MAX8973) += max89
obj-$(CONFIG_REGULATOR_MAX8997) += max8997-regulator.o
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
obj-$(CONFIG_REGULATOR_MAX20086) += max20086-regulator.o
-obj-$(CONFIG_REGULATOR_MAX20411) += max20411-regulator.o
obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o
obj-$(CONFIG_REGULATOR_MAX77693) += max77693-regulator.o
obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
@@ -0,0 +1,24 @@
--- a/include/dt-bindings/clock/histb-clock.h
+++ b/include/dt-bindings/clock/histb-clock.h
@@ -58,6 +58,21 @@
#define HISTB_USB3_UTMI_CLK1 48
#define HISTB_USB3_PIPE_CLK1 49
#define HISTB_USB3_SUSPEND_CLK1 50
+#define HISTB_USB2_UTMI_CLK1 51
+#define HISTB_USB2_2_BUS_CLK 52
+#define HISTB_USB2_2_PHY_CLK 53
+#define HISTB_USB2_2_UTMI_CLK 54
+#define HISTB_USB2_2_UTMI_CLK1 55
+#define HISTB_USB2_2_12M_CLK 56
+#define HISTB_USB2_2_48M_CLK 57
+#define HISTB_USB2_2_OTG_UTMI_CLK 58
+#define HISTB_USB2_2_PHY1_REF_CLK 59
+#define HISTB_USB2_2_PHY2_REF_CLK 60
+#define HISTB_FEPHY_CLK 61
+#define HISTB_GPU_BUS_CLK 62
+#define HISTB_GPU_CORE_CLK 63
+#define HISTB_DMAC_CLK 64
+#define HISTB_MMC_SAP_DLL_MODE_CLK 65
/* clocks provided by mcu CRG */
#define HISTB_MCE_CLK 1
+9
View File
@@ -0,0 +1,9 @@
ARCH:=arm
SUBTARGET:=hi3798mv100
BOARDNAME:=Hi3798MV100
CPU_TYPE:=cortex-a7
CPU_SUBTYPE:=neon-vfpv4
define Target/Description
Build firmware images for HiSilicon Hi3798MV100 devices
endef
@@ -0,0 +1,207 @@
/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
/dts-v1/;
#include "mt7987a.dtsi"
#include <dt-bindings/input/input.h>
/ {
model = "GL.iNet GL-MT5000";
compatible = "glinet,gl-mt5000",
"mediatek,mt7987a", "mediatek,mt7987";
aliases {
label-mac-device = &gmac0;
led-boot = &led_power;
led-failsafe = &led_power;
led-running = &led_power;
led-upgrade = &led_power;
};
chosen {
bootargs = "console=ttyS0,115200n1 loglevel=8 \
earlycon=uart8250,mmio32,0x11000000 \
root=PARTLABEL=rootfs rootwait \
rootfstype=squashfs,f2fs pci=pcie_bus_perf";
};
gpio-keys {
compatible = "gpio-keys";
reset {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&pio 4 GPIO_ACTIVE_LOW>;
debounce-interval = <10>;
};
};
gpio-export {
compatible = "gpio-export";
usb_power {
gpio-export,name = "usb_power";
gpio-export,output = <1>;
gpios = <&pio 9 GPIO_ACTIVE_HIGH>;
};
};
leds {
compatible = "gpio-leds";
led_power: led@0 {
label = "blue:run";
gpios = <&pio 44 GPIO_ACTIVE_LOW>;
default-state = "on";
};
led@1 {
label = "white:system";
gpios = <&pio 7 GPIO_ACTIVE_LOW>;
};
led@2 {
label = "vpn";
gpios = <&pio 43 GPIO_ACTIVE_LOW>;
};
};
reg_1p8v: regulator-1p8v {
compatible = "regulator-fixed";
regulator-name = "fixed-1.8V";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
reg_3p3v: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "fixed-3.3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
};
&mmc0 {
pinctrl-names = "default", "state_uhs";
pinctrl-0 = <&mmc_pins_default>;
pinctrl-1 = <&mmc_pins_uhs>;
bus-width = <8>;
max-frequency = <26000000>;
cap-mmc-highspeed;
vqmmc-supply = <&reg_3p3v>;
vmmc-supply = <&reg_3p3v>;
mmc-ddr-3_3v;
non-removable;
no-sd;
no-sdio;
status = "okay";
card@0 {
compatible = "mmc-card";
reg = <0>;
block {
compatible = "block-device";
partitions {
block-partition-env {
partname = "u-boot-env";
nvmem-layout {
compatible = "u-boot,env";
};
};
block-partition-factory {
partname = "factory";
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
macaddr_base: macaddr@4000 {
compatible = "mac-base";
reg = <0x4000 0x6>;
#nvmem-cell-cells = <1>;
};
};
};
};
};
};
};
&gmac0 {
compatible = "mediatek,eth-mac";
reg = <0>;
mac-type = "gdm";
phy-mode = "2500base-x";
status = "okay";
nvmem-cells = <&macaddr_base 0>;
nvmem-cell-names = "mac-address";
fixed-link {
speed = <2500>;
full-duplex;
pause;
};
};
&gmac1 {
reg = <1>;
mac-type = "xgdm";
phy-mode = "internal";
phy-handle = <&phy15>;
status = "okay";
nvmem-cells = <&macaddr_base 1>;
nvmem-cell-names = "mac-address";
};
&mdio {
#address-cells = <1>;
#size-cells = <0>;
reset-gpios = <&pio 0 GPIO_ACTIVE_LOW>;
reset-delay-us = <10000>;
phy15: phy@f {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <15>;
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
phy-mode = "internal";
};
};
&ssusb {
status = "okay";
};
&tphyu3port0 {
status = "okay";
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&infra_bus_prot {
status = "okay";
};
&boottrap {
status = "okay";
};
&trng {
status = "okay";
};
&lvts {
status = "okay";
};
@@ -37,6 +37,7 @@ mediatek_setup_interfaces()
ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 sfp2" "eth1 wan"
;;
bananapi,bpi-r3-mini|\
glinet,gl-mt5000|\
huasifei,wh3000-emmc|\
huasifei,wh3000-pro)
ucidef_set_interfaces_lan_wan eth0 eth1
@@ -48,6 +48,7 @@ platform_do_upgrade() {
cmcc,rax3000m-emmc|\
cmcc,xr30-emmc|\
glinet,gl-mt2500|\
glinet,gl-mt5000|\
glinet,gl-mt6000|\
glinet,gl-x3000|\
glinet,gl-xe3000|\
@@ -110,6 +111,7 @@ platform_copy_config() {
cmcc,rax3000m-emmc|\
cmcc,xr30-emmc|\
glinet,gl-mt2500|\
glinet,gl-mt5000|\
glinet,gl-mt6000|\
glinet,gl-x3000|\
glinet,gl-xe3000|\
@@ -536,6 +536,20 @@ define Device/glinet_gl-mt3000
endef
TARGET_DEVICES += glinet_gl-mt3000
define Device/glinet_gl-mt5000
DEVICE_VENDOR := GL.iNet
DEVICE_MODEL := GL-MT5000
DEVICE_DTS := mt7987a-gl-mt5000
DEVICE_DTS_DIR := ../dts
SUPPORTED_DEVICES := glinet,gl-mt5000
DEVICE_PACKAGES := mkf2fs blkid blockdev kmod-fs-ext4 mt7987-2p5g-phy-firmware \
kmod-mmc kmod-fs-f2fs kmod-fs-vfat
IMAGES += factory.bin
IMAGE/factory.bin := append-kernel | pad-to 32M | append-rootfs
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
endef
TARGET_DEVICES += glinet_gl-mt5000
define Device/glinet_gl-mt6000
DEVICE_VENDOR := GL.iNet
DEVICE_MODEL := GL-MT6000
+1
View File
@@ -55,6 +55,7 @@ tools-y += m4
tools-y += make-ext4fs
tools-y += meson
tools-y += missing-macros
tools-y += mkbootargs
tools-y += mkimage
tools-y += mklibs
tools-y += mtd-utils
+17
View File
@@ -0,0 +1,17 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mkbootargs
PKG_VERSION:=1.0
include $(INCLUDE_DIR)/host-build.mk
define Host/Compile
$(HOSTCC) $(HOST_CFLAGS) -o $(HOST_BUILD_DIR)/mkbootargs src/crc32.c src/mkbootargs.c
endef
define Host/Install
$(INSTALL_BIN) $(HOST_BUILD_DIR)/mkbootargs $(STAGING_DIR_HOST)/bin/
endef
$(eval $(call HostBuild))
+126
View File
@@ -0,0 +1,126 @@
#include <stdio.h>
#include <string.h>
#define tole(x) (x)
/* ========================================================================
* Table of CRC-32's of all single-byte values (made by make_crc_table)
*/
static const unsigned int crc_table[256] = {
tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
};
/* ========================================================================= */
# define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
/* ========================================================================= */
/* No ones complement version. JFFS2 (and other things ?)
* don't use ones compliment in their CRC calculations.
*/
unsigned long crc32_no_comp(unsigned int crc, const unsigned char *buf, unsigned int len)
{
const unsigned int *tab = crc_table;
const unsigned int *b =(const unsigned int *)buf;
unsigned long rem_len;
/* Align it */
if (((long)b) & 3 && len) {
unsigned char *p = (unsigned char *)b;
do {
DO_CRC(*p++);
} while ((--len) && ((long)p)&3);
b = (unsigned int *)p;
}
rem_len = len & 3;
len = len >> 2;
for (--b; len; --len) {
/* load data 32 bits wide, xor data 32 bits wide. */
crc ^= *++b; /* use pre increment for speed */
DO_CRC(0);
DO_CRC(0);
DO_CRC(0);
DO_CRC(0);
}
len = rem_len;
/* And the last few bytes */
if (len) {
unsigned char *p = (unsigned char *)(b + 1) - 1;
do {
DO_CRC(*++p); /* use pre increment for speed */
} while (--len);
}
return crc;
}
unsigned long crc32 (unsigned int crc, const unsigned char *p, unsigned int len)
{
return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
}
+127
View File
@@ -0,0 +1,127 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
extern unsigned long crc32 (unsigned int crc, const unsigned char *p, unsigned int len);
#define MAX_LINE_LENGTH (4096)
int main(int argc, char *argv[])
{
FILE *fp = NULL;
FILE *fp_input = NULL;
char *buf = NULL;
int size = MAX_LINE_LENGTH;
long int totalhiflashsize = -1;
long int totalnandflashsize = 256 * 1024;
unsigned long crc;
char line[MAX_LINE_LENGTH];
char bootargs_input[1024] = "bootargs_input.txt";
char bootargs_bin[1024] = "bootargs.bin";
char *strsrc;
int offset = 0;
int oc = 0;
char *tmp = NULL;
int len = 0;
if (argc < 2) {
printf("\r\nUsage: mkbootargs [-s Size] [-r Input File] [-o Output File] :\n"
" -r Input File: A TXT file that describes the Boot Env config, default 'bootargs_input.txt'\n"
" -o Output File: The output bin file, default 'bootargs.bin'\n"
" -s Size: Boot Env size in KB, usually, equal to the bootargs partition size. default '512'.\n"
"\r\nmkbootargs will read 'Input File' and create 'Output File'.\n");
printf("\r\nExample:./makebootargs -s 64 -r bootargs_input.txt -o bootargs.bin\n\n");
return 1;
}
while ((oc = getopt(argc, argv, "r:o:s:p:n:")) != -1) {
switch (oc) {
case 'r':
sprintf(bootargs_input, "%s", optarg);
printf("optarg:%s\n", optarg);
break;
case 'o':
sprintf(bootargs_bin, "%s", optarg);
printf("optarg:%s\n", optarg);
break;
case 's':
size = atoi(optarg);
printf("optarg:%s\n", optarg);
break;
default:
printf("unknow args\n");
break;
}
}
if (size > 1) {
printf("flash size is %dKB.\n", size);
size = size * 1024;
} else
printf("flash size too small.\n");
fp = fopen(bootargs_bin, "w+b");
if (NULL == fp) {
printf("open 'Output File' error.\n");
return -1;
}
fp_input = fopen(bootargs_input, "rb");
if (NULL == fp_input) {
printf("no 'Input File'!\n");
fclose(fp);
return -1;
}
buf = malloc(size);
if (NULL == buf) {
printf("open bootargs out of memory\n");
fclose(fp);
fclose(fp_input);
return -1;
}
strsrc = malloc(size * sizeof(char));
if (NULL == strsrc) {
printf("open bootargs out of memory\n");
fclose(fp);
fclose(fp_input);
free(buf);
return -1;
}
memset(buf, 0x00, size);
memset(strsrc, 0x00, size);
while (fgets(line, size-1, fp_input) != NULL) {
strcat(strsrc, line);
tmp = line;
while (*tmp != '\0') {
if (*tmp == '\n' || (*tmp == 0xd))
*tmp = '\0';
tmp++;
}
len = strlen(line);
printf("%d--%s\n", len, line);
memcpy(buf + 4 + offset, line, len);
offset += len + 1;
memset(line, 512, 0);
}
crc = crc32(0, buf + 4, size - 4);
memcpy(buf, (unsigned char *)&crc, 4);
/* init flash data */
fwrite(buf, size, 1, fp);
free(buf);
free(strsrc);
fclose(fp);
if (fp_input != stdin)
fclose(fp_input);
return 0;
}